aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore12
-rw-r--r--AUTHORS5
-rw-r--r--NEWS33
-rw-r--r--README184
-rw-r--r--audio/fmopl.cpp31
-rw-r--r--audio/mixer.cpp5
-rw-r--r--audio/module.mk12
-rw-r--r--audio/opl2lpt.cpp154
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_midi.cpp2
-rw-r--r--audio/softsynth/opl/mame.cpp8
-rw-r--r--audio/softsynth/opl/nuked.cpp1487
-rw-r--r--audio/softsynth/opl/nuked.h188
-rw-r--r--backends/audiocd/audiocd.h5
-rw-r--r--backends/audiocd/default/default-audiocd.cpp5
-rw-r--r--backends/audiocd/default/default-audiocd.h3
-rw-r--r--backends/audiocd/win32/win32-audiocd.cpp18
-rw-r--r--backends/events/default/default-events.h20
-rw-r--r--backends/events/psp2sdl/psp2sdl-events.cpp91
-rw-r--r--backends/events/psp2sdl/psp2sdl-events.h8
-rw-r--r--backends/events/sdl/sdl-events.cpp209
-rw-r--r--backends/events/sdl/sdl-events.h6
-rw-r--r--backends/fs/amigaos4/amigaos4-fs.cpp2
-rw-r--r--backends/fs/ds/ds-fs-factory.cpp2
-rw-r--r--backends/fs/ds/ds-fs.cpp2
-rw-r--r--backends/fs/posix/posix-fs.cpp23
-rw-r--r--backends/fs/psp2/psp2-fs-factory.cpp2
-rw-r--r--backends/graphics/psp2sdl/psp2sdl-graphics.cpp6
-rw-r--r--backends/graphics/windowed.h2
-rw-r--r--backends/midi/dmedia.cpp6
-rw-r--r--backends/modular-backend.h104
-rw-r--r--backends/platform/androidsdl/androidsdl-sdl.cpp8
-rw-r--r--backends/platform/dc/dc-fs.cpp2
-rw-r--r--backends/platform/dc/selector.cpp21
-rw-r--r--backends/platform/ds/arm7/source/main.cpp694
-rw-r--r--backends/platform/ds/arm9/source/cdaudio.cpp2
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp53
-rw-r--r--backends/platform/ds/arm9/source/dsmain.h2
-rw-r--r--backends/platform/ds/arm9/source/dsoptions.cpp2
-rw-r--r--backends/platform/ds/arm9/source/fat/disc_io.c2
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp3
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h4
-rw-r--r--backends/platform/ds/arm9/source/wordcompletion.cpp2
-rw-r--r--backends/platform/ds/arm9/source/zipreader.cpp3
-rw-r--r--backends/platform/ds/ds.mk23
-rw-r--r--backends/platform/ios7/README.md127
-rw-r--r--backends/platform/ios7/ios7_osys_main.h2
-rw-r--r--backends/platform/n64/osys_n64_base.cpp2
-rw-r--r--backends/platform/n64/portdefs.h15
-rw-r--r--backends/platform/psp/display_manager.cpp2
-rw-r--r--backends/platform/psp/input.cpp2
-rw-r--r--backends/platform/sdl/macosx/macosx.cpp4
-rw-r--r--backends/platform/sdl/macosx/macosx.h1
-rw-r--r--backends/platform/sdl/macosx/macosx_wrapper.h1
-rw-r--r--backends/platform/sdl/macosx/macosx_wrapper.mm32
-rw-r--r--backends/platform/sdl/psp2/psp2-main.cpp4
-rw-r--r--backends/platform/sdl/psp2/psp2.cpp8
-rw-r--r--backends/platform/sdl/riscos/riscos-main.cpp2
-rw-r--r--backends/platform/sdl/riscos/riscos.cpp2
-rw-r--r--backends/platform/sdl/riscos/riscos.mk3
-rw-r--r--backends/platform/sdl/sdl.cpp34
-rw-r--r--backends/platform/sdl/sdl.h1
-rw-r--r--backends/platform/wii/osystem_events.cpp2
-rw-r--r--backends/plugins/ds/ds-provider.cpp4
-rw-r--r--backends/plugins/elf/version.cpp2
-rw-r--r--backends/saves/psp/psp-saves.cpp5
-rw-r--r--base/commandLine.cpp316
-rw-r--r--base/main.cpp40
-rw-r--r--base/plugins.cpp97
-rw-r--r--base/plugins.h6
-rw-r--r--base/version.h8
-rw-r--r--common/EventDispatcher.cpp4
-rw-r--r--common/algorithm.h3
-rw-r--r--common/archive.cpp6
-rw-r--r--common/array.h10
-rw-r--r--common/config-manager.cpp14
-rw-r--r--common/config-manager.h4
-rw-r--r--common/coroutines.cpp88
-rw-r--r--common/coroutines.h10
-rw-r--r--common/dcl.cpp2
-rw-r--r--common/dct.cpp2
-rw-r--r--common/fft.cpp2
-rw-r--r--common/file.cpp20
-rw-r--r--common/fs.cpp32
-rw-r--r--common/fs.h2
-rw-r--r--common/gui_options.cpp2
-rw-r--r--common/hash-str.h8
-rw-r--r--common/hashmap.cpp8
-rw-r--r--common/hashmap.h56
-rw-r--r--common/huffman.h4
-rw-r--r--common/iff_container.cpp2
-rw-r--r--common/iff_container.h2
-rw-r--r--common/ini-file.cpp10
-rw-r--r--common/installshield_cab.cpp4
-rw-r--r--common/json.cpp56
-rw-r--r--common/json.h2
-rw-r--r--common/language.cpp10
-rw-r--r--common/list.h2
-rw-r--r--common/list_intern.h4
-rw-r--r--common/macresman.cpp26
-rw-r--r--common/math.h42
-rw-r--r--common/memorypool.cpp8
-rw-r--r--common/memstream.h8
-rw-r--r--common/mutex.cpp4
-rw-r--r--common/mutex.h4
-rw-r--r--common/osd_message_queue.cpp6
-rw-r--r--common/osd_message_queue.h6
-rw-r--r--common/platform.cpp6
-rw-r--r--common/ptr.h8
-rw-r--r--common/quicktime.cpp18
-rw-r--r--common/quicktime.h2
-rw-r--r--common/rdft.cpp2
-rw-r--r--common/recorderfile.cpp9
-rw-r--r--common/rect.h8
-rw-r--r--common/rendermode.cpp6
-rw-r--r--common/safe-bool.h2
-rw-r--r--common/scummsys.h12
-rw-r--r--common/serializer.h10
-rw-r--r--common/singleton.h4
-rw-r--r--common/str.cpp97
-rw-r--r--common/str.h6
-rw-r--r--common/stream.cpp22
-rw-r--r--common/system.cpp32
-rw-r--r--common/system.h27
-rw-r--r--common/textconsole.cpp4
-rw-r--r--common/translation.cpp8
-rw-r--r--common/translation.h2
-rw-r--r--common/unarj.cpp22
-rw-r--r--common/unzip.cpp136
-rw-r--r--common/updates.cpp2
-rw-r--r--common/updates.h2
-rw-r--r--common/ustr.cpp18
-rw-r--r--common/util.h2
-rw-r--r--common/winexe_ne.cpp8
-rw-r--r--common/winexe_pe.cpp12
-rw-r--r--common/xmlparser.cpp10
-rw-r--r--common/xmlparser.h4
-rw-r--r--common/zlib.cpp12
-rw-r--r--common/zlib.h2
-rwxr-xr-xconfigure81
-rw-r--r--devtools/create_cryo/create_cryo_dat.cpp28
-rw-r--r--devtools/create_cryo/eden_rooms.h2
-rw-r--r--devtools/create_project/cmake.cpp23
-rw-r--r--devtools/create_project/create_project.cpp2
-rw-r--r--devtools/create_project/create_project.h2
-rw-r--r--devtools/create_supernova/po_parser.cpp2
-rw-r--r--devtools/create_supernova/strings-en.po11
-rw-r--r--devtools/create_titanic/create_titanic_dat.cpp2
-rw-r--r--devtools/create_xeen/cc.h6
-rw-r--r--devtools/create_xeen/constants.cpp465
-rw-r--r--devtools/create_xeen/create_xeen.cpp13
-rw-r--r--devtools/create_xeen/file.h2
-rw-r--r--devtools/create_xeen/map.cpp6
-rw-r--r--devtools/create_xeen/module.mk3
-rw-r--r--devtools/create_xeen/swords.cpp53
-rw-r--r--devtools/create_xeen/swords.h (renamed from engines/sludge/transition.h)11
-rwxr-xr-xdevtools/credits.pl38
-rw-r--r--dists/engine-data/supernova.datbin77779 -> 116261 bytes
-rw-r--r--dists/engine-data/xeen.ccsbin43490 -> 55594 bytes
-rw-r--r--doc/QuickStart6
-rw-r--r--doc/cz/PrectiMe30
-rw-r--r--doc/da/HurtigStart6
-rw-r--r--doc/de/LIESMICH35
-rw-r--r--doc/de/NEUES2
-rw-r--r--doc/de/Schnellstart6
-rw-r--r--doc/es/InicioRapido6
-rw-r--r--doc/fr/DemarrageRapide6
-rw-r--r--doc/it/GuidaRapida6
-rw-r--r--doc/no-nb/HurtigStart6
-rw-r--r--doc/se/LasMig16
-rw-r--r--doc/se/Snabbstart6
-rw-r--r--engines/access/access.cpp12
-rw-r--r--engines/access/access.h2
-rw-r--r--engines/access/detection.cpp12
-rw-r--r--engines/access/scripts.cpp2
-rw-r--r--engines/adl/detection.cpp75
-rw-r--r--engines/adl/graphics.cpp2
-rw-r--r--engines/advancedDetector.cpp332
-rw-r--r--engines/advancedDetector.h89
-rw-r--r--engines/agi/detection.cpp14
-rw-r--r--engines/agos/detection.cpp2
-rw-r--r--engines/agos/detection_tables.h150
-rw-r--r--engines/agos/intern.h3
-rw-r--r--engines/agos/midi.cpp12
-rw-r--r--engines/agos/sound.cpp2
-rw-r--r--engines/agos/string.cpp2
-rw-r--r--engines/avalanche/avalanche.cpp8
-rw-r--r--engines/avalanche/avalanche.h7
-rw-r--r--engines/avalanche/detection.cpp15
-rw-r--r--engines/avalanche/dropdown.cpp4
-rw-r--r--engines/bbvs/bbvs.h2
-rw-r--r--engines/bbvs/detection.cpp4
-rw-r--r--engines/bbvs/saveload.cpp10
-rw-r--r--engines/bladerunner/actor.cpp296
-rw-r--r--engines/bladerunner/actor.h77
-rw-r--r--engines/bladerunner/actor_clues.cpp186
-rw-r--r--engines/bladerunner/actor_clues.h23
-rw-r--r--engines/bladerunner/actor_combat.cpp654
-rw-r--r--engines/bladerunner/actor_combat.h79
-rw-r--r--engines/bladerunner/actor_dialogue_queue.cpp58
-rw-r--r--engines/bladerunner/actor_dialogue_queue.h8
-rw-r--r--engines/bladerunner/actor_walk.cpp48
-rw-r--r--engines/bladerunner/actor_walk.h5
-rw-r--r--engines/bladerunner/ambient_sounds.cpp122
-rw-r--r--engines/bladerunner/ambient_sounds.h51
-rw-r--r--engines/bladerunner/archive.cpp30
-rw-r--r--engines/bladerunner/archive.h7
-rw-r--r--engines/bladerunner/aud_stream.cpp7
-rw-r--r--engines/bladerunner/audio_player.cpp2
-rw-r--r--engines/bladerunner/audio_speech.cpp10
-rw-r--r--engines/bladerunner/audio_speech.h3
-rw-r--r--engines/bladerunner/bladerunner.cpp306
-rw-r--r--engines/bladerunner/bladerunner.h25
-rw-r--r--engines/bladerunner/boundingbox.cpp2
-rw-r--r--engines/bladerunner/boundingbox.h2
-rw-r--r--engines/bladerunner/chapters.cpp3
-rw-r--r--engines/bladerunner/combat.cpp126
-rw-r--r--engines/bladerunner/combat.h45
-rw-r--r--engines/bladerunner/crimes_database.cpp16
-rw-r--r--engines/bladerunner/crimes_database.h7
-rw-r--r--engines/bladerunner/debugger.cpp75
-rw-r--r--engines/bladerunner/debugger.h2
-rw-r--r--engines/bladerunner/detection_tables.h32
-rw-r--r--engines/bladerunner/dialogue_menu.cpp51
-rw-r--r--engines/bladerunner/dialogue_menu.h6
-rw-r--r--engines/bladerunner/fog.cpp7
-rw-r--r--engines/bladerunner/fog.h3
-rw-r--r--engines/bladerunner/font.cpp8
-rw-r--r--engines/bladerunner/font.h1
-rw-r--r--engines/bladerunner/game_constants.h60
-rw-r--r--engines/bladerunner/game_flags.cpp16
-rw-r--r--engines/bladerunner/game_flags.h6
-rw-r--r--engines/bladerunner/game_info.cpp66
-rw-r--r--engines/bladerunner/game_info.h18
-rw-r--r--engines/bladerunner/item.cpp70
-rw-r--r--engines/bladerunner/item.h20
-rw-r--r--engines/bladerunner/item_pickup.h2
-rw-r--r--engines/bladerunner/items.cpp141
-rw-r--r--engines/bladerunner/items.h22
-rw-r--r--engines/bladerunner/light.cpp4
-rw-r--r--engines/bladerunner/light.h3
-rw-r--r--engines/bladerunner/matrix.h4
-rw-r--r--engines/bladerunner/module.mk14
-rw-r--r--engines/bladerunner/mouse.cpp67
-rw-r--r--engines/bladerunner/mouse.h7
-rw-r--r--engines/bladerunner/movement_track.cpp30
-rw-r--r--engines/bladerunner/movement_track.h5
-rw-r--r--engines/bladerunner/music.cpp63
-rw-r--r--engines/bladerunner/music.h11
-rw-r--r--engines/bladerunner/obstacles.cpp502
-rw-r--r--engines/bladerunner/obstacles.h68
-rw-r--r--engines/bladerunner/overlays.cpp53
-rw-r--r--engines/bladerunner/overlays.h22
-rw-r--r--engines/bladerunner/rect.h75
-rw-r--r--engines/bladerunner/regions.cpp20
-rw-r--r--engines/bladerunner/regions.h6
-rw-r--r--engines/bladerunner/savefile.cpp166
-rw-r--r--engines/bladerunner/savefile.h75
-rw-r--r--engines/bladerunner/scene.cpp42
-rw-r--r--engines/bladerunner/scene.h11
-rw-r--r--engines/bladerunner/scene_objects.cpp81
-rw-r--r--engines/bladerunner/scene_objects.h38
-rw-r--r--engines/bladerunner/screen_effects.h14
-rw-r--r--engines/bladerunner/script/ai/bullet_bob.cpp555
-rw-r--r--engines/bladerunner/script/ai/clovis.cpp216
-rw-r--r--engines/bladerunner/script/ai/dektora.cpp10
-rw-r--r--engines/bladerunner/script/ai/early_q.cpp1037
-rw-r--r--engines/bladerunner/script/ai/free_slot_a.cpp659
-rw-r--r--engines/bladerunner/script/ai/free_slot_b.cpp541
-rw-r--r--engines/bladerunner/script/ai/gaff.cpp2
-rw-r--r--engines/bladerunner/script/ai/generic_walker_a.cpp5
-rw-r--r--engines/bladerunner/script/ai/generic_walker_b.cpp5
-rw-r--r--engines/bladerunner/script/ai/generic_walker_c.cpp5
-rw-r--r--engines/bladerunner/script/ai/gordo.cpp2
-rw-r--r--engines/bladerunner/script/ai/guzza.cpp2
-rw-r--r--engines/bladerunner/script/ai/hanoi.cpp740
-rw-r--r--engines/bladerunner/script/ai/hasan.cpp315
-rw-r--r--engines/bladerunner/script/ai/hysteria_patron1.cpp2
-rw-r--r--engines/bladerunner/script/ai/leon.cpp2
-rw-r--r--engines/bladerunner/script/ai/lucy.cpp6
-rw-r--r--engines/bladerunner/script/ai/luther.cpp439
-rw-r--r--engines/bladerunner/script/ai/mccoy.cpp36
-rw-r--r--engines/bladerunner/script/ai/mutant1.cpp15
-rw-r--r--engines/bladerunner/script/ai/mutant2.cpp12
-rw-r--r--engines/bladerunner/script/ai/mutant3.cpp12
-rw-r--r--engines/bladerunner/script/ai/officer_grayford.cpp1422
-rw-r--r--engines/bladerunner/script/ai/officer_leary.cpp2
-rw-r--r--engines/bladerunner/script/ai/rajif.cpp2
-rw-r--r--engines/bladerunner/script/ai/sadik.cpp1039
-rw-r--r--engines/bladerunner/script/ai/steele.cpp2
-rw-r--r--engines/bladerunner/script/ai/taffy_patron.cpp6
-rw-r--r--engines/bladerunner/script/ai/zuben.cpp4
-rw-r--r--engines/bladerunner/script/ai_script.cpp51
-rw-r--r--engines/bladerunner/script/ai_script.h76
-rw-r--r--engines/bladerunner/script/police_maze.cpp603
-rw-r--r--engines/bladerunner/script/police_maze.h106
-rw-r--r--engines/bladerunner/script/scene/ct07.cpp2
-rw-r--r--engines/bladerunner/script/scene/ct11.cpp8
-rw-r--r--engines/bladerunner/script/scene/ct12.cpp2
-rw-r--r--engines/bladerunner/script/scene/dr02.cpp2
-rw-r--r--engines/bladerunner/script/scene/dr04.cpp2
-rw-r--r--engines/bladerunner/script/scene/dr06.cpp4
-rw-r--r--engines/bladerunner/script/scene/hf01.cpp12
-rw-r--r--engines/bladerunner/script/scene/hf03.cpp4
-rw-r--r--engines/bladerunner/script/scene/hf05.cpp20
-rw-r--r--engines/bladerunner/script/scene/hf06.cpp13
-rw-r--r--engines/bladerunner/script/scene/hf07.cpp8
-rw-r--r--engines/bladerunner/script/scene/kp05.cpp2
-rw-r--r--engines/bladerunner/script/scene/ma04.cpp4
-rw-r--r--engines/bladerunner/script/scene/nr01.cpp2
-rw-r--r--engines/bladerunner/script/scene/nr04.cpp2
-rw-r--r--engines/bladerunner/script/scene/nr09.cpp2
-rw-r--r--engines/bladerunner/script/scene/nr11.cpp6
-rw-r--r--engines/bladerunner/script/scene/ps10.cpp459
-rw-r--r--engines/bladerunner/script/scene/ps11.cpp2
-rw-r--r--engines/bladerunner/script/scene/ps12.cpp8
-rw-r--r--engines/bladerunner/script/scene/ps13.cpp8
-rw-r--r--engines/bladerunner/script/scene/rc01.cpp2
-rw-r--r--engines/bladerunner/script/scene/tb05.cpp4
-rw-r--r--engines/bladerunner/script/scene/ug02.cpp4
-rw-r--r--engines/bladerunner/script/scene/ug05.cpp4
-rw-r--r--engines/bladerunner/script/scene/ug07.cpp2
-rw-r--r--engines/bladerunner/script/scene/ug15.cpp4
-rw-r--r--engines/bladerunner/script/scene/ug18.cpp5
-rw-r--r--engines/bladerunner/script/scene_script.cpp2
-rw-r--r--engines/bladerunner/script/scene_script.h2
-rw-r--r--engines/bladerunner/script/script.cpp116
-rw-r--r--engines/bladerunner/script/script.h26
-rw-r--r--engines/bladerunner/script/vk_script.cpp8
-rw-r--r--engines/bladerunner/set.cpp93
-rw-r--r--engines/bladerunner/set.h34
-rw-r--r--engines/bladerunner/set_effects.cpp8
-rw-r--r--engines/bladerunner/set_effects.h6
-rw-r--r--engines/bladerunner/settings.cpp61
-rw-r--r--engines/bladerunner/settings.h22
-rw-r--r--engines/bladerunner/slice_animations.cpp32
-rw-r--r--engines/bladerunner/slice_animations.h6
-rw-r--r--engines/bladerunner/slice_renderer.cpp134
-rw-r--r--engines/bladerunner/slice_renderer.h2
-rw-r--r--engines/bladerunner/text_resource.cpp6
-rw-r--r--engines/bladerunner/time.cpp68
-rw-r--r--engines/bladerunner/time.h50
-rw-r--r--engines/bladerunner/ui/elevator.cpp3
-rw-r--r--engines/bladerunner/ui/end_credits.cpp170
-rw-r--r--engines/bladerunner/ui/end_credits.h42
-rw-r--r--engines/bladerunner/ui/kia.cpp2
-rw-r--r--engines/bladerunner/ui/kia_log.cpp2
-rw-r--r--engines/bladerunner/ui/kia_log.h2
-rw-r--r--engines/bladerunner/ui/scores.cpp218
-rw-r--r--engines/bladerunner/ui/scores.h82
-rw-r--r--engines/bladerunner/ui/spinner.cpp15
-rw-r--r--engines/bladerunner/ui/spinner.h7
-rw-r--r--engines/bladerunner/ui/ui_scroll_box.cpp5
-rw-r--r--engines/bladerunner/vector.h12
-rw-r--r--engines/bladerunner/view.cpp19
-rw-r--r--engines/bladerunner/waypoints.cpp22
-rw-r--r--engines/bladerunner/waypoints.h6
-rw-r--r--engines/cge/cge.h9
-rw-r--r--engines/cge/cge_main.cpp35
-rw-r--r--engines/cge/detection.cpp55
-rw-r--r--engines/cge/vga13h.cpp2
-rw-r--r--engines/cge2/cge2.h12
-rw-r--r--engines/cge2/detection.cpp55
-rw-r--r--engines/cge2/events.cpp1
-rw-r--r--engines/cge2/saveload.cpp36
-rw-r--r--engines/cge2/vga13h.cpp4
-rw-r--r--engines/chewy/chewy.cpp2
-rw-r--r--engines/chewy/console.cpp2
-rw-r--r--engines/chewy/detection.cpp4
-rw-r--r--engines/chewy/scene.cpp6
-rw-r--r--engines/cine/detection.cpp2
-rw-r--r--engines/cine/sound.cpp6
-rw-r--r--engines/composer/detection.cpp4
-rw-r--r--engines/cruise/detection.cpp11
-rw-r--r--engines/cruise/saveload.cpp13
-rw-r--r--engines/cruise/saveload.h2
-rw-r--r--engines/cruise/sound.cpp6
-rw-r--r--engines/cryo/cryo.h3
-rw-r--r--engines/cryo/eden.cpp5
-rw-r--r--engines/cryo/sound.cpp226
-rw-r--r--engines/cryo/sound.h140
-rw-r--r--engines/cryo/video.cpp2
-rw-r--r--engines/director/detection.cpp8
-rw-r--r--engines/director/frame.cpp2
-rw-r--r--engines/director/lingo/lingo-gr.cpp8
-rw-r--r--engines/director/lingo/lingo-lex.cpp42
-rw-r--r--engines/director/resource.cpp2
-rw-r--r--engines/dm/dm.h2
-rw-r--r--engines/dm/dungeonman.cpp1
-rw-r--r--engines/dm/gfx.cpp23
-rw-r--r--engines/dm/group.cpp1
-rw-r--r--engines/dm/loadsave.cpp13
-rw-r--r--engines/dm/menus.cpp5
-rw-r--r--engines/dm/projexpl.cpp2
-rw-r--r--engines/draci/detection.cpp10
-rw-r--r--engines/draci/game.cpp2
-rw-r--r--engines/draci/game.h2
-rw-r--r--engines/draci/saveload.cpp15
-rw-r--r--engines/draci/saveload.h2
-rw-r--r--engines/drascula/detection.cpp6
-rw-r--r--engines/dreamweb/detection.cpp7
-rw-r--r--engines/fullpipe/detection.cpp8
-rw-r--r--engines/fullpipe/gameloader.h4
-rw-r--r--engines/fullpipe/interaction.h3
-rw-r--r--engines/fullpipe/modal.cpp19
-rw-r--r--engines/fullpipe/scenes/scene22.cpp2
-rw-r--r--engines/fullpipe/stateloader.cpp33
-rw-r--r--engines/fullpipe/utils.cpp4
-rw-r--r--engines/game.cpp222
-rw-r--r--engines/game.h176
-rw-r--r--engines/gnap/detection.cpp15
-rw-r--r--engines/gnap/gnap.cpp2
-rw-r--r--engines/gnap/gnap.h2
-rw-r--r--engines/gnap/menu.cpp7
-rw-r--r--engines/gob/detection/detection.cpp29
-rw-r--r--engines/hopkins/computer.cpp4
-rw-r--r--engines/hopkins/detection.cpp9
-rw-r--r--engines/hopkins/dialogs.cpp6
-rw-r--r--engines/hopkins/font.cpp4
-rw-r--r--engines/hopkins/hopkins.cpp44
-rw-r--r--engines/hopkins/objects.cpp4
-rw-r--r--engines/hopkins/saveload.cpp19
-rw-r--r--engines/hopkins/saveload.h4
-rw-r--r--engines/hopkins/talk.cpp16
-rw-r--r--engines/hugo/detection.cpp7
-rw-r--r--engines/hugo/hugo.cpp1
-rw-r--r--engines/kyra/detection.cpp4
-rw-r--r--engines/kyra/eobcommon.h2
-rw-r--r--engines/kyra/kyra_v1.h2
-rw-r--r--engines/kyra/saveload.cpp11
-rw-r--r--engines/kyra/screen_eob.cpp4
-rw-r--r--engines/kyra/sequences_darkmoon.cpp2
-rw-r--r--engines/kyra/sequences_hof.cpp2
-rw-r--r--engines/kyra/sequences_lok.cpp2
-rw-r--r--engines/kyra/sound_digital.cpp8
-rw-r--r--engines/kyra/sound_intern.h72
-rw-r--r--engines/lab/lab.h2
-rw-r--r--engines/lab/map.cpp6
-rw-r--r--engines/lab/savegame.cpp14
-rw-r--r--engines/lastexpress/menu/menu.cpp2
-rw-r--r--engines/lilliput/configure.engine3
-rw-r--r--engines/lilliput/console.cpp34
-rw-r--r--engines/lilliput/console.h49
-rw-r--r--engines/lilliput/detection.cpp292
-rw-r--r--engines/lilliput/lilliput.cpp2856
-rw-r--r--engines/lilliput/lilliput.h384
-rw-r--r--engines/lilliput/module.mk20
-rw-r--r--engines/lilliput/script.cpp3355
-rw-r--r--engines/lilliput/script.h316
-rw-r--r--engines/lilliput/sound.cpp248
-rw-r--r--engines/lilliput/sound.h71
-rw-r--r--engines/lilliput/stream.cpp42
-rw-r--r--engines/lilliput/stream.h42
-rw-r--r--engines/lure/sound.cpp5
-rw-r--r--engines/macventure/detection.cpp19
-rw-r--r--engines/macventure/saveload.cpp9
-rw-r--r--engines/made/detection.cpp6
-rw-r--r--engines/made/resource.cpp3
-rw-r--r--engines/mads/detection.cpp12
-rw-r--r--engines/mads/game.cpp12
-rw-r--r--engines/mads/game.h2
-rw-r--r--engines/mads/nebular/game_nebular.cpp5
-rw-r--r--engines/mads/nebular/nebular_scenes4.cpp4
-rw-r--r--engines/metaengine.h21
-rw-r--r--engines/mohawk/bitmap.cpp8
-rw-r--r--engines/mohawk/bitmap.h22
-rw-r--r--engines/mohawk/console.h12
-rw-r--r--engines/mohawk/cstime.h4
-rw-r--r--engines/mohawk/cursors.cpp8
-rw-r--r--engines/mohawk/cursors.h54
-rw-r--r--engines/mohawk/detection.cpp40
-rw-r--r--engines/mohawk/detection_tables.h233
-rw-r--r--engines/mohawk/dialogs.cpp37
-rw-r--r--engines/mohawk/dialogs.h34
-rw-r--r--engines/mohawk/graphics.cpp4
-rw-r--r--engines/mohawk/graphics.h2
-rw-r--r--engines/mohawk/installer_archive.cpp6
-rw-r--r--engines/mohawk/installer_archive.h12
-rw-r--r--engines/mohawk/livingbooks.cpp1
-rw-r--r--engines/mohawk/livingbooks.h4
-rw-r--r--engines/mohawk/livingbooks_code.cpp3
-rw-r--r--engines/mohawk/mohawk.cpp8
-rw-r--r--engines/mohawk/mohawk.h17
-rw-r--r--engines/mohawk/myst.cpp287
-rw-r--r--engines/mohawk/myst.h19
-rw-r--r--engines/mohawk/myst_areas.cpp58
-rw-r--r--engines/mohawk/myst_areas.h54
-rw-r--r--engines/mohawk/myst_graphics.cpp9
-rw-r--r--engines/mohawk/myst_graphics.h5
-rw-r--r--engines/mohawk/myst_scripts.cpp29
-rw-r--r--engines/mohawk/myst_scripts.h3
-rw-r--r--engines/mohawk/myst_sound.h2
-rw-r--r--engines/mohawk/myst_stacks/channelwood.cpp28
-rw-r--r--engines/mohawk/myst_stacks/channelwood.h6
-rw-r--r--engines/mohawk/myst_stacks/credits.cpp13
-rw-r--r--engines/mohawk/myst_stacks/credits.h4
-rw-r--r--engines/mohawk/myst_stacks/demo.cpp8
-rw-r--r--engines/mohawk/myst_stacks/demo.h6
-rw-r--r--engines/mohawk/myst_stacks/dni.cpp40
-rw-r--r--engines/mohawk/myst_stacks/dni.h4
-rw-r--r--engines/mohawk/myst_stacks/intro.cpp9
-rw-r--r--engines/mohawk/myst_stacks/intro.h4
-rw-r--r--engines/mohawk/myst_stacks/makingof.cpp3
-rw-r--r--engines/mohawk/myst_stacks/makingof.h4
-rw-r--r--engines/mohawk/myst_stacks/mechanical.cpp56
-rw-r--r--engines/mohawk/myst_stacks/mechanical.h6
-rw-r--r--engines/mohawk/myst_stacks/myst.cpp313
-rw-r--r--engines/mohawk/myst_stacks/myst.h22
-rw-r--r--engines/mohawk/myst_stacks/preview.cpp15
-rw-r--r--engines/mohawk/myst_stacks/preview.h4
-rw-r--r--engines/mohawk/myst_stacks/selenitic.cpp84
-rw-r--r--engines/mohawk/myst_stacks/selenitic.h16
-rw-r--r--engines/mohawk/myst_stacks/slides.cpp8
-rw-r--r--engines/mohawk/myst_stacks/slides.h4
-rw-r--r--engines/mohawk/myst_stacks/stoneship.cpp49
-rw-r--r--engines/mohawk/myst_stacks/stoneship.h6
-rw-r--r--engines/mohawk/myst_state.cpp71
-rw-r--r--engines/mohawk/myst_state.h58
-rw-r--r--engines/mohawk/resource.cpp4
-rw-r--r--engines/mohawk/resource.h20
-rw-r--r--engines/mohawk/resource_cache.cpp4
-rw-r--r--engines/mohawk/riven.cpp35
-rw-r--r--engines/mohawk/riven.h18
-rw-r--r--engines/mohawk/riven_card.cpp150
-rw-r--r--engines/mohawk/riven_card.h3
-rw-r--r--engines/mohawk/riven_graphics.cpp40
-rw-r--r--engines/mohawk/riven_graphics.h10
-rw-r--r--engines/mohawk/riven_inventory.h2
-rw-r--r--engines/mohawk/riven_saveload.cpp69
-rw-r--r--engines/mohawk/riven_saveload.h9
-rw-r--r--engines/mohawk/riven_scripts.cpp18
-rw-r--r--engines/mohawk/riven_sound.h2
-rw-r--r--engines/mohawk/riven_stacks/jspit.cpp2
-rw-r--r--engines/mohawk/riven_stacks/pspit.cpp15
-rw-r--r--engines/mohawk/riven_video.h2
-rw-r--r--engines/mohawk/sound.cpp96
-rw-r--r--engines/mohawk/sound.h11
-rw-r--r--engines/mohawk/video.cpp6
-rw-r--r--engines/mohawk/video.h2
-rw-r--r--engines/mohawk/view.cpp68
-rw-r--r--engines/mortevielle/mortevielle.h1
-rw-r--r--engines/mortevielle/saveload.cpp22
-rw-r--r--engines/mortevielle/saveload.h3
-rw-r--r--engines/neverhood/detection.cpp4
-rw-r--r--engines/neverhood/menumodule.cpp2
-rw-r--r--engines/neverhood/neverhood.h2
-rw-r--r--engines/neverhood/saveload.cpp10
-rw-r--r--engines/obsolete.cpp10
-rw-r--r--engines/obsolete.h2
-rw-r--r--engines/pegasus/items/biochips/pegasuschip.h2
-rw-r--r--engines/plumbers/console.cpp2
-rw-r--r--engines/plumbers/console.h5
-rw-r--r--engines/plumbers/plumbers.cpp16
-rw-r--r--engines/plumbers/plumbers.h5
-rw-r--r--engines/prince/archive.cpp12
-rw-r--r--engines/prince/cursor.cpp99
-rw-r--r--engines/prince/decompress.cpp254
-rw-r--r--engines/prince/detection.cpp38
-rw-r--r--engines/prince/draw.cpp765
-rw-r--r--engines/prince/hero.cpp2
-rw-r--r--engines/prince/inventory.cpp709
-rw-r--r--engines/prince/mob.cpp158
-rw-r--r--engines/prince/module.mk7
-rw-r--r--engines/prince/music.cpp236
-rw-r--r--engines/prince/music.h (renamed from engines/prince/sound.h)4
-rw-r--r--engines/prince/object.cpp3
-rw-r--r--engines/prince/option_text.h19
-rw-r--r--engines/prince/prince.cpp3696
-rw-r--r--engines/prince/prince.h20
-rw-r--r--engines/prince/pscr.cpp3
-rw-r--r--engines/prince/resource.cpp371
-rw-r--r--engines/prince/resource.h103
-rw-r--r--engines/prince/saveload.cpp67
-rw-r--r--engines/prince/script.cpp37
-rw-r--r--engines/prince/sound.cpp264
-rw-r--r--engines/prince/walk.cpp1610
-rw-r--r--engines/queen/detection.cpp49
-rw-r--r--engines/queen/music.cpp5
-rw-r--r--engines/saga/detection.cpp8
-rw-r--r--engines/saga/events.cpp2
-rw-r--r--engines/saga/interface.cpp4
-rw-r--r--engines/saga/isomap.cpp100
-rw-r--r--engines/saga/isomap.h14
-rw-r--r--engines/saga/puzzle.cpp22
-rw-r--r--engines/saga/resource_hrs.cpp1
-rw-r--r--engines/saga/resource_res.cpp2
-rw-r--r--engines/sci/detection.cpp23
-rw-r--r--engines/sci/engine/kgraphics.cpp1
-rw-r--r--engines/sci/engine/kpathing.cpp2
-rw-r--r--engines/sci/event.cpp2
-rw-r--r--engines/sci/graphics/animate.cpp5
-rw-r--r--engines/sci/graphics/celobj32.h3
-rw-r--r--engines/sci/graphics/palette.cpp59
-rw-r--r--engines/sci/graphics/palette.h3
-rw-r--r--engines/sci/sound/drivers/midi.cpp26
-rw-r--r--engines/scumm/camera.cpp15
-rw-r--r--engines/scumm/configure.engine2
-rw-r--r--engines/scumm/detection.cpp37
-rw-r--r--engines/scumm/dialogs.h10
-rw-r--r--engines/scumm/he/moonbase/ai_main.cpp12
-rw-r--r--engines/scumm/imuse/imuse.cpp7
-rw-r--r--engines/scumm/imuse_digi/dimuse_track.h2
-rw-r--r--engines/scumm/input.cpp2
-rw-r--r--engines/scumm/object.cpp18
-rw-r--r--engines/scumm/players/player_ad.cpp1
-rw-r--r--engines/scumm/players/player_nes.cpp6
-rw-r--r--engines/scumm/players/player_towns.cpp3
-rw-r--r--engines/scumm/saveload.cpp4
-rw-r--r--engines/scumm/script_v2.cpp7
-rw-r--r--engines/scumm/scumm.cpp4
-rw-r--r--engines/sherlock/detection.cpp7
-rw-r--r--engines/sherlock/image_file.cpp20
-rw-r--r--engines/sherlock/music.cpp4
-rw-r--r--engines/sherlock/objects.h2
-rw-r--r--engines/sherlock/resources.cpp17
-rw-r--r--engines/sherlock/saveload.cpp22
-rw-r--r--engines/sherlock/saveload.h2
-rw-r--r--engines/sherlock/scalpel/scalpel.cpp4
-rw-r--r--engines/sherlock/sherlock.cpp4
-rw-r--r--engines/sherlock/tattoo/tattoo_people.cpp2
-rw-r--r--engines/sky/detection.cpp33
-rw-r--r--engines/sludge/backdrop.cpp30
-rw-r--r--engines/sludge/bg_effects.cpp8
-rw-r--r--engines/sludge/builtin.cpp706
-rw-r--r--engines/sludge/builtin.h2
-rw-r--r--engines/sludge/csludge.h2
-rw-r--r--engines/sludge/cursors.cpp23
-rw-r--r--engines/sludge/cursors.h2
-rw-r--r--engines/sludge/detection.cpp22
-rw-r--r--engines/sludge/event.cpp26
-rw-r--r--engines/sludge/event.h2
-rw-r--r--engines/sludge/fileset.cpp27
-rw-r--r--engines/sludge/fileset.h8
-rw-r--r--engines/sludge/floor.cpp296
-rw-r--r--engines/sludge/floor.h41
-rw-r--r--engines/sludge/fonttext.cpp16
-rw-r--r--engines/sludge/fonttext.h9
-rw-r--r--engines/sludge/freeze.cpp22
-rw-r--r--engines/sludge/freeze.h10
-rw-r--r--engines/sludge/function.cpp788
-rw-r--r--engines/sludge/function.h73
-rw-r--r--engines/sludge/functionlist.h338
-rw-r--r--engines/sludge/graphics.cpp11
-rw-r--r--engines/sludge/graphics.h24
-rw-r--r--engines/sludge/loadsave.cpp351
-rw-r--r--engines/sludge/loadsave.h15
-rw-r--r--engines/sludge/main_loop.cpp10
-rw-r--r--engines/sludge/module.mk1
-rw-r--r--engines/sludge/moreio.cpp11
-rw-r--r--engines/sludge/moreio.h2
-rw-r--r--engines/sludge/movie.cpp3
-rw-r--r--engines/sludge/newfatal.cpp79
-rw-r--r--engines/sludge/newfatal.h42
-rw-r--r--engines/sludge/people.cpp804
-rw-r--r--engines/sludge/people.h165
-rw-r--r--engines/sludge/region.cpp167
-rw-r--r--engines/sludge/region.h50
-rw-r--r--engines/sludge/savedata.cpp158
-rw-r--r--engines/sludge/savedata.h22
-rw-r--r--engines/sludge/sludge.cpp21
-rw-r--r--engines/sludge/sludge.h11
-rw-r--r--engines/sludge/sludger.cpp795
-rw-r--r--engines/sludge/sludger.h42
-rw-r--r--engines/sludge/sound.cpp2
-rw-r--r--engines/sludge/speech.cpp67
-rw-r--r--engines/sludge/speech.h6
-rw-r--r--engines/sludge/sprites.h29
-rw-r--r--engines/sludge/statusba.cpp18
-rw-r--r--engines/sludge/thumbnail.cpp23
-rw-r--r--engines/sludge/timing.cpp54
-rw-r--r--engines/sludge/timing.h24
-rw-r--r--engines/sludge/transition.cpp19
-rw-r--r--engines/sludge/variable.cpp511
-rw-r--r--engines/sludge/variable.h107
-rw-r--r--engines/supernova/detection.cpp25
-rw-r--r--engines/supernova/graphics.cpp25
-rw-r--r--engines/supernova/graphics.h6
-rw-r--r--engines/supernova/imageid.h654
-rw-r--r--engines/supernova/module.mk7
-rw-r--r--engines/supernova/msn_def.h292
-rw-r--r--engines/supernova/resman.cpp395
-rw-r--r--engines/supernova/resman.h77
-rw-r--r--engines/supernova/rooms.cpp403
-rw-r--r--engines/supernova/rooms.h45
-rw-r--r--engines/supernova/screen.cpp636
-rw-r--r--engines/supernova/screen.h197
-rw-r--r--engines/supernova/screenstatic.cpp328
-rw-r--r--engines/supernova/sound.cpp65
-rw-r--r--engines/supernova/sound.h80
-rw-r--r--engines/supernova/state.cpp371
-rw-r--r--engines/supernova/state.h37
-rw-r--r--engines/supernova/supernova.cpp858
-rw-r--r--engines/supernova/supernova.h174
-rw-r--r--engines/sword1/detection.cpp80
-rw-r--r--engines/sword2/sword2.cpp35
-rw-r--r--engines/sword25/gfx/graphicengine.cpp10
-rw-r--r--engines/sword25/sfx/soundengine.cpp2
-rw-r--r--engines/sword25/util/lua/llex.cpp6
-rw-r--r--engines/sword25/util/lua/lstrlib.cpp6
-rw-r--r--engines/teenagent/detection.cpp7
-rw-r--r--engines/testbed/graphics.cpp43
-rw-r--r--engines/tinsel/cursor.cpp4
-rw-r--r--engines/tinsel/detection.cpp21
-rw-r--r--engines/tinsel/dialogs.cpp5
-rw-r--r--engines/tinsel/multiobj.cpp9
-rw-r--r--engines/tinsel/pcode.cpp4
-rw-r--r--engines/titanic/continue_save_dialog.cpp2
-rw-r--r--engines/titanic/core/game_object.cpp1
-rw-r--r--engines/titanic/core/list.h4
-rw-r--r--engines/titanic/core/project_item.cpp25
-rw-r--r--engines/titanic/core/project_item.h2
-rw-r--r--engines/titanic/debugger.cpp2
-rw-r--r--engines/titanic/detection.cpp10
-rw-r--r--engines/titanic/game/bomb.cpp4
-rw-r--r--engines/titanic/game/chicken_dispensor.cpp2
-rw-r--r--engines/titanic/npcs/deskbot.cpp2
-rw-r--r--engines/titanic/pet_control/pet_load_save.cpp5
-rw-r--r--engines/titanic/sound/music_room_handler.cpp2
-rw-r--r--engines/titanic/sound/music_room_instrument.cpp2
-rw-r--r--engines/titanic/sound/music_song.cpp4
-rw-r--r--engines/titanic/star_control/base_stars.cpp2
-rw-r--r--engines/titanic/star_control/camera_auto_mover.cpp4
-rw-r--r--engines/titanic/star_control/camera_auto_mover.h6
-rw-r--r--engines/titanic/star_control/frect.h2
-rw-r--r--engines/titanic/star_control/marked_auto_mover.h2
-rw-r--r--engines/titanic/star_control/star_camera.h2
-rw-r--r--engines/titanic/star_control/star_closeup.cpp12
-rw-r--r--engines/titanic/star_control/star_control.cpp2
-rw-r--r--engines/titanic/star_control/star_crosshairs.h8
-rw-r--r--engines/titanic/star_control/star_field.h6
-rw-r--r--engines/titanic/star_control/star_view.h6
-rw-r--r--engines/titanic/star_control/unmarked_camera_mover.cpp2
-rw-r--r--engines/titanic/star_control/viewport.cpp2
-rw-r--r--engines/titanic/star_control/viewport.h14
-rw-r--r--engines/titanic/support/avi_surface.cpp2
-rw-r--r--engines/titanic/support/simple_file.cpp2
-rw-r--r--engines/titanic/support/simple_file.h2
-rw-r--r--engines/titanic/titanic.cpp8
-rw-r--r--engines/titanic/true_talk/doorbot_script.cpp4
-rw-r--r--engines/titanic/true_talk/tt_parser.cpp4
-rw-r--r--engines/titanic/true_talk/tt_talker.h2
-rw-r--r--engines/titanic/true_talk/tt_vocab.cpp1170
-rw-r--r--engines/toltecs/detection.cpp4
-rw-r--r--engines/toltecs/menu.cpp2
-rw-r--r--engines/toltecs/saveload.cpp10
-rw-r--r--engines/toltecs/toltecs.h2
-rw-r--r--engines/tony/gfxcore.cpp8
-rw-r--r--engines/tony/loc.cpp2
-rw-r--r--engines/tony/mpal/lzo.cpp12
-rw-r--r--engines/tony/sound.cpp6
-rw-r--r--engines/toon/detection.cpp8
-rw-r--r--engines/toon/flux.cpp3
-rw-r--r--engines/toon/hotspot.cpp16
-rw-r--r--engines/toon/hotspot.h8
-rw-r--r--engines/toon/script_func.cpp8
-rw-r--r--engines/toon/toon.cpp24
-rw-r--r--engines/touche/detection.cpp11
-rw-r--r--engines/touche/touche.cpp3
-rw-r--r--engines/touche/touche.h1
-rw-r--r--engines/tsage/blue_force/blueforce_scenes9.cpp8
-rw-r--r--engines/tsage/blue_force/blueforce_scenes9.h4
-rw-r--r--engines/tsage/detection.cpp9
-rw-r--r--engines/tsage/saveload.cpp15
-rw-r--r--engines/tsage/saveload.h2
-rw-r--r--engines/tucker/detection.cpp11
-rw-r--r--engines/tucker/locations.cpp28
-rw-r--r--engines/tucker/resource.cpp80
-rw-r--r--engines/tucker/saveload.cpp86
-rw-r--r--engines/tucker/sequences.cpp124
-rw-r--r--engines/tucker/tucker.cpp301
-rw-r--r--engines/tucker/tucker.h115
-rw-r--r--engines/voyeur/detection.cpp3
-rw-r--r--engines/voyeur/files_threads.cpp2
-rw-r--r--engines/voyeur/voyeur.cpp11
-rw-r--r--engines/voyeur/voyeur.h2
-rw-r--r--engines/wintermute/base/base_engine.h18
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.cpp2
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.h2
-rw-r--r--engines/wintermute/base/particles/part_emitter.cpp6
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.cpp6
-rw-r--r--engines/wintermute/configure.engine2
-rw-r--r--engines/wintermute/debugger/error.h36
-rw-r--r--engines/wintermute/detection.cpp9
-rw-r--r--engines/wintermute/detection_tables.h9
-rw-r--r--engines/wintermute/game_description.h17
-rw-r--r--engines/wintermute/wintermute.cpp21
-rw-r--r--engines/wintermute/wintermute.h9
-rw-r--r--engines/xeen/POTFILES1
-rw-r--r--engines/xeen/character.cpp196
-rw-r--r--engines/xeen/character.h63
-rw-r--r--engines/xeen/combat.cpp348
-rw-r--r--engines/xeen/combat.h32
-rw-r--r--engines/xeen/configure.engine2
-rw-r--r--engines/xeen/debugger.cpp31
-rw-r--r--engines/xeen/debugger.h12
-rw-r--r--engines/xeen/detection.cpp55
-rw-r--r--engines/xeen/detection_tables.h28
-rw-r--r--engines/xeen/dialogs/credits_screen.cpp4
-rw-r--r--engines/xeen/dialogs/dialogs.cpp83
-rw-r--r--engines/xeen/dialogs/dialogs.h34
-rw-r--r--engines/xeen/dialogs/dialogs_char_info.cpp33
-rw-r--r--engines/xeen/dialogs/dialogs_control_panel.cpp14
-rw-r--r--engines/xeen/dialogs/dialogs_copy_protection.cpp100
-rw-r--r--engines/xeen/dialogs/dialogs_copy_protection.h64
-rw-r--r--engines/xeen/dialogs/dialogs_create_char.cpp11
-rw-r--r--engines/xeen/dialogs/dialogs_dismiss.cpp4
-rw-r--r--engines/xeen/dialogs/dialogs_input.cpp63
-rw-r--r--engines/xeen/dialogs/dialogs_input.h6
-rw-r--r--engines/xeen/dialogs/dialogs_items.cpp366
-rw-r--r--engines/xeen/dialogs/dialogs_items.h41
-rw-r--r--engines/xeen/dialogs/dialogs_message.cpp2
-rw-r--r--engines/xeen/dialogs/dialogs_party.cpp6
-rw-r--r--engines/xeen/dialogs/dialogs_query.cpp9
-rw-r--r--engines/xeen/dialogs/dialogs_quests.cpp98
-rw-r--r--engines/xeen/dialogs/dialogs_spells.cpp403
-rw-r--r--engines/xeen/dialogs/dialogs_spells.h37
-rw-r--r--engines/xeen/events.cpp68
-rw-r--r--engines/xeen/events.h65
-rw-r--r--engines/xeen/files.cpp20
-rw-r--r--engines/xeen/files.h11
-rw-r--r--engines/xeen/font.cpp7
-rw-r--r--engines/xeen/interface.cpp215
-rw-r--r--engines/xeen/interface.h11
-rw-r--r--engines/xeen/interface_minimap.cpp10
-rw-r--r--engines/xeen/interface_scene.cpp122
-rw-r--r--engines/xeen/interface_scene.h25
-rw-r--r--engines/xeen/item.cpp255
-rw-r--r--engines/xeen/item.h98
-rw-r--r--engines/xeen/locations.cpp535
-rw-r--r--engines/xeen/locations.h8
-rw-r--r--engines/xeen/map.cpp118
-rw-r--r--engines/xeen/map.h36
-rw-r--r--engines/xeen/module.mk3
-rw-r--r--engines/xeen/party.cpp347
-rw-r--r--engines/xeen/party.h22
-rw-r--r--engines/xeen/patcher.cpp101
-rw-r--r--engines/xeen/patcher.h (renamed from engines/xeen/worldofxeen/worldofxeen_resources.h)39
-rw-r--r--engines/xeen/resources.cpp31
-rw-r--r--engines/xeen/resources.h29
-rw-r--r--engines/xeen/saves.cpp70
-rw-r--r--engines/xeen/saves.h2
-rw-r--r--engines/xeen/screen.cpp2
-rw-r--r--engines/xeen/scripts.cpp548
-rw-r--r--engines/xeen/scripts.h16
-rw-r--r--engines/xeen/sound.cpp83
-rw-r--r--engines/xeen/sound.h8
-rw-r--r--engines/xeen/sound_driver.cpp19
-rw-r--r--engines/xeen/sound_driver.h11
-rw-r--r--engines/xeen/spells.cpp88
-rw-r--r--engines/xeen/spells.h2
-rw-r--r--engines/xeen/sprites.cpp17
-rw-r--r--engines/xeen/subtitles.cpp2
-rw-r--r--engines/xeen/subtitles.h2
-rw-r--r--engines/xeen/swordsofxeen/swordsofxeen.cpp40
-rw-r--r--engines/xeen/swordsofxeen/swordsofxeen.h5
-rw-r--r--engines/xeen/window.cpp14
-rw-r--r--engines/xeen/worldofxeen/clouds_cutscenes.cpp16
-rw-r--r--engines/xeen/worldofxeen/darkside_cutscenes.cpp22
-rw-r--r--engines/xeen/worldofxeen/worldofxeen.cpp23
-rw-r--r--engines/xeen/worldofxeen/worldofxeen_cutscenes.cpp20
-rw-r--r--engines/xeen/worldofxeen/worldofxeen_menu.cpp88
-rw-r--r--engines/xeen/worldofxeen/worldofxeen_menu.h20
-rw-r--r--engines/xeen/worldofxeen/worldofxeen_resources.cpp62
-rw-r--r--engines/xeen/xeen.cpp37
-rw-r--r--engines/xeen/xeen.h36
-rw-r--r--engines/zvision/detection.cpp10
-rw-r--r--engines/zvision/detection_tables.h2
-rw-r--r--engines/zvision/file/save_manager.cpp41
-rw-r--r--engines/zvision/file/save_manager.h9
-rw-r--r--graphics/VectorRenderer.cpp2
-rw-r--r--graphics/VectorRenderer.h2
-rw-r--r--graphics/VectorRendererSpec.cpp64
-rw-r--r--graphics/VectorRendererSpec.h3
-rw-r--r--graphics/fonts/bdf.h4
-rw-r--r--graphics/nine_patch.cpp2
-rw-r--r--graphics/primitives.cpp62
-rw-r--r--graphics/scaler.cpp14
-rw-r--r--graphics/scaler/intern.h12
-rw-r--r--graphics/scaler/scalebit.cpp42
-rw-r--r--graphics/sjis.cpp22
-rw-r--r--graphics/thumbnail.cpp28
-rw-r--r--graphics/thumbnail.h2
-rw-r--r--gui/EventRecorder.cpp4
-rw-r--r--gui/ThemeEngine.cpp498
-rw-r--r--gui/ThemeEngine.h110
-rw-r--r--gui/Tooltip.cpp3
-rw-r--r--gui/Tooltip.h14
-rw-r--r--gui/about.cpp4
-rw-r--r--gui/about.h14
-rw-r--r--gui/console.cpp55
-rw-r--r--gui/console.h55
-rw-r--r--gui/credits.h7
-rw-r--r--gui/debugger.cpp8
-rw-r--r--gui/dialog.cpp2
-rw-r--r--gui/editgamedialog.cpp20
-rw-r--r--gui/editgamedialog.h4
-rw-r--r--gui/launcher.cpp72
-rw-r--r--gui/launcher.h2
-rw-r--r--gui/massadd.cpp50
-rw-r--r--gui/massadd.h5
-rw-r--r--gui/module.mk1
-rw-r--r--gui/object.cpp4
-rw-r--r--gui/object.h5
-rw-r--r--gui/options.h6
-rw-r--r--gui/predictivedialog.cpp6
-rw-r--r--gui/recorderdialog.cpp4
-rw-r--r--gui/themes/translations.datbin746444 -> 750409 bytes
-rw-r--r--gui/unknown-game-dialog.cpp220
-rw-r--r--gui/unknown-game-dialog.h59
-rw-r--r--gui/widget.cpp180
-rw-r--r--gui/widget.h8
-rw-r--r--gui/widgets/editable.cpp15
-rw-r--r--gui/widgets/edittext.cpp8
-rw-r--r--gui/widgets/list.cpp17
-rw-r--r--gui/widgets/popup.cpp19
-rw-r--r--gui/widgets/scrollbar.cpp6
-rw-r--r--gui/widgets/scrollcontainer.cpp8
-rw-r--r--gui/widgets/scrollcontainer.h2
-rw-r--r--gui/widgets/tab.cpp9
-rw-r--r--gui/widgets/tab.h18
-rw-r--r--image/codecs/cinepak.cpp21
-rw-r--r--image/codecs/cinepak.h1
-rw-r--r--image/codecs/indeo/indeo.cpp36
-rw-r--r--image/codecs/indeo3.cpp36
-rw-r--r--po/POTFILES2
-rw-r--r--po/be_BY.po311
-rw-r--r--po/ca_ES.po302
-rw-r--r--po/cs_CZ.po309
-rw-r--r--po/da_DK.po309
-rw-r--r--po/de_DE.po442
-rw-r--r--po/el.po310
-rw-r--r--po/es_ES.po311
-rw-r--r--po/eu.po300
-rw-r--r--po/fi_FI.po312
-rw-r--r--po/fr_FR.po349
-rw-r--r--po/gl_ES.po309
-rw-r--r--po/hu_HU.po308
-rw-r--r--po/it_IT.po317
-rw-r--r--po/nb_NO.po303
-rw-r--r--po/nl_NL.po317
-rw-r--r--po/nn_NO.po307
-rw-r--r--po/pl_PL.po305
-rw-r--r--po/pt_BR.po298
-rw-r--r--po/pt_PT.po301
-rw-r--r--po/ru_RU.po311
-rw-r--r--po/scummvm.pot289
-rw-r--r--po/sv_SE.po358
-rw-r--r--po/uk_UA.po307
-rw-r--r--po/zh-Latn_CN.po301
-rw-r--r--video/bink_decoder.cpp2
-rw-r--r--video/flic_decoder.cpp7
-rw-r--r--video/flic_decoder.h1
951 files changed, 48874 insertions, 21365 deletions
diff --git a/.gitignore b/.gitignore
index c19710fd13..261e2a5213 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,11 +25,16 @@ lib*.a
/*,e1f
/scummvm-ps3.pkg
/*.ipk
+/map.txt
+*.elf
+/*.nds
/.project
/.cproject
/.settings
/.autotools
/Icon.*
+/scummvm-conf.cpp
+/tmp_*.cpp
/build
/staging
@@ -53,6 +58,7 @@ lib*.a
/backends/platform/ds/arm7/build
/backends/platform/ds/arm7/source/libcartreset/*.bak
/backends/platform/ds/arm7/source/libcartreset/*.d
+/backends/platform/ds/arm9/data/*.h
/backends/platform/ds/arm9/scummvm-?
/backends/platform/maemo/scummvm
@@ -123,18 +129,22 @@ project.xcworkspace
/devtools/convbdf
/devtools/md5table
/devtools/make-scumm-fontdata
+/devtools/create_access/create_access
+/devtools/create_cryo/create_cryo_dat
/devtools/create_drascula/create_drascula
/devtools/create_hugo/create_hugo
/devtools/create_kyradat/create_kyradat
/devtools/create_lure/create_lure
-/devtools/create_mads/create_mads
/devtools/create_mortdat/create_mortdat
/devtools/create_neverhood/create_neverhood
/devtools/create_project/create_project
+/devtools/create_supernova/create_supernova
/devtools/create_teenagent/create_teenagent
+/devtools/create_titanic/create_titanic
/devtools/create_tony/create_tony
/devtools/create_toon/create_toon
/devtools/create_translations/create_translations
+/devtools/create_xeen/create_xeen
/devtools/extract_mort/extract_mort
/devtools/qtable/qtable
/devtools/skycpt/skycpt
diff --git a/AUTHORS b/AUTHORS
index 2181ef5cc8..79f1c50d67 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -292,6 +292,11 @@ ScummVM Team
Einar Johan T. Somaaen
Tobia Tesan
+ Xeen:
+ Paul Gilbert
+ David Goldsmith - (analysis)
+ Matt Taylor - (analysis)
+
Z-Vision:
Adrian Astley
Filippos Karapetis
diff --git a/NEWS b/NEWS
index d5db58ef53..104418274b 100644
--- a/NEWS
+++ b/NEWS
@@ -7,7 +7,12 @@ For a more comprehensive changelog of the latest experimental code, see:
- Fixed incorrect cursor movement when it's controlled using the keyboard.
- Updated the Roland MT-32 emulation code to Munt 2.3.0.
+ Full Pipe:
+ - Fixed playtime not being restored when loading a savegame.
+ - Fixed a bug that leads to enormous memory consumption in scene 22.
+
MOHAWK:
+ - Fixed clicking through the books in the library in Myst 1.0.
- Fixed video playback if videos are skipped in Riven.
- Added support for keyboard shortcuts for loading and saving as documented in the game manual.
@@ -20,16 +25,28 @@ For a more comprehensive changelog of the latest experimental code, see:
- Improved Audio quality in Humongous Entertainment games by using the Miles AdLib driver.
- Fixed possible stack overflows in The Dig and Full Throttle.
+ Tinsel:
+ - Fix loading Discworld 1 savegames from the launcher where Rincewind had a held item
+ - Script patch for hang in Discworld 1 GRA using items on Temple big hammer
+ - In Discworld 1, Held items being released that were never in the Luggage or Rincewind's inventory
+ will now be automatically dropped into the Luggage rather than being lost
+
+ Titanic:
+ - Fixed bug in entering floor numbers numerically that could crash the game
+
Tucker:
- Fixed multiple graphic issues in Bud Tucker in Double Trouble.
- Fixed multiple issues with font and subtitle rendering.
- Fixed dentist music in mall being played incorrectly.
+ - Fixed wrong sound effects being played.
- Fixed a bug that made the bubbles in the Plugs Shop not always visible.
- Fixed a missing animation when Ego and Billie are on the boat.
- Fixed a bug that caused a dead end in the second museum scene.
- Bud is no longer able to walk outside the walkable area when visiting the club.
+ - Bud is also no longer able to walk through closed doors.
- Added mouse wheel support for inventory scrolling.
- Allow skipping of speech.
+ - Improved savegame handling and add support for autosaves.
ZVISION:
- Fixed graphical glitch in Zork: Grand Inquisitor.
@@ -593,16 +610,16 @@ For a more comprehensive changelog of the latest experimental code, see:
- Added FluidSynth settings dialog, mainly for reverb and chorus settings.
- Fixed crash on certain Smacker movies.
- Cine:
+ Cine:
- Improved audio support for Amiga and AtariST versions of Future Wars.
Now music fades out slowly instead of stopping immediately. Sound
effects are now properly panned, when requested by the game.
- CGE:
+ CGE:
- Soltys contains a puzzle requiring the ALT key to be pressed while clicking
on an object. This puzzle has been disabled on devices not using this key.
- Drascula:
+ Drascula:
- Resolved multiple UI issues with the original save/load screen.
- Added advanced savegame functionality, including savegame timestamps and
thumbnails and the ability to load and delete savegames from the launcher.
@@ -612,7 +629,7 @@ For a more comprehensive changelog of the latest experimental code, see:
save screen, if the user has selected to use the ScummVM save/load
dialogs.
- Dreamweb:
+ Dreamweb:
- Now that the game is freeware, there is a small extra help text showing
the available commands in the in-game terminals when the player uses the
'help' command. Previously, players needed to consult the manual for the
@@ -620,18 +637,18 @@ For a more comprehensive changelog of the latest experimental code, see:
protection, this extra line can be toggled by the ScummVM copy protection
command line option.
- Groovie:
+ Groovie:
- Simplified the movie speed options, and added a custom option for The 7th
Guest. Movie options are now "normal" and "fast", with the latter changing
the movie speed in T7G to match the faster movie speed of the iOS version.
The game entry might need to be readded in the launcher for the new setting
to appear.
- SAGA:
+ SAGA:
- Added music support for the Macintosh version of I Have No Mouth and, I
Must Scream.
- SCUMM:
+ SCUMM:
- Implemented Monkey Island 2 Macintosh's audio driver. Now we properly
support its sample based audio output. The same output is also used for
the m68k Macintosh version of Indiana Jones and the Fate of Atlantis.
@@ -975,7 +992,7 @@ For a more comprehensive changelog of the latest experimental code, see:
- Fixed 16bit mouse cursors on HE games.
1.2.1 (2010-12-19)
- General
+ General:
- Added Hungarian translation.
- Added Brazilian Portuguese translation.
diff --git a/README b/README
index c777c64933..700811828d 100644
--- a/README
+++ b/README
@@ -3,7 +3,7 @@ ScummVM README
For more information, compatibility lists, details on donating, the latest
release, progress reports and more, please visit the ScummVM home page
-at: <http://www.scummvm.org/>
+at: <https://www.scummvm.org/>
Table of Contents:
@@ -33,22 +33,23 @@ Table of Contents:
* 3.12 Inherit the Earth: Quest for the Orb notes
* 3.13 Maniac Mansion Apple II/NES notes
* 3.14 Mickey's Space Adventure notes
- * 3.15 Myst notes
- * 3.16 Nippon Safes Inc. Amiga notes
- * 3.17 Quest for Glory notes
- * 3.18 Riven notes
- * 3.19 Simon the Sorcerer notes
- * 3.20 Starship Titanic notes
- * 3.21 The Curse of Monkey Island notes
- * 3.22 The Feeble Files notes
- * 3.23 The Legend of Kyrandia notes
- * 3.24 Troll's Tale notes
- * 3.25 Winnie the Pooh notes
- * 3.26 Sierra AGI games: Predictive Input Dialog notes
- * 3.27 Sierra SCI games: Simultaneous speech and subtitles
- * 3.28 Zork games notes
- * 3.29 Commodore64 games notes
- * 3.30 Macintosh games notes
+ * 3.15 Might and Magic Xeen games notes
+ * 3.16 Myst notes
+ * 3.17 Nippon Safes Inc. Amiga notes
+ * 3.18 Quest for Glory notes
+ * 3.19 Riven notes
+ * 3.20 Simon the Sorcerer notes
+ * 3.21 Starship Titanic notes
+ * 3.22 The Curse of Monkey Island notes
+ * 3.23 The Feeble Files notes
+ * 3.24 The Legend of Kyrandia notes
+ * 3.25 Troll's Tale notes
+ * 3.26 Winnie the Pooh notes
+ * 3.27 Sierra AGI games: Predictive Input Dialog notes
+ * 3.28 Sierra SCI games: Simultaneous speech and subtitles
+ * 3.29 Zork games notes
+ * 3.30 Commodore64 games notes
+ * 3.31 Macintosh games notes
4.0) Supported Platforms
5.0) Running ScummVM
* 5.1 Command Line Options
@@ -66,7 +67,7 @@ Table of Contents:
* 7.3 MT-32 emulation
* 7.4 MIDI emulation
* 7.5 Native MIDI support
- * 7.5.1 Using MIDI options to customize Native MIDI output
+ * * 7.5.1 Using MIDI options to customize Native MIDI output
* 7.6 UNIX native, ALSA and dmedia sequencer support
* * 7.6.1 ALSA sequencer [UNIX ONLY]
* * 7.6.2 IRIX dmedia sequencer [UNIX ONLY]
@@ -143,7 +144,7 @@ patch!
For the impatient among you, here is how to get ScummVM running in five
simple steps.
-1. Download ScummVM from <http://www.scummvm.org/downloads.php> and
+1. Download ScummVM from <https://www.scummvm.org/downloads/> and
install it.
2. Create a directory on your hard drive and copy the game datafiles
@@ -174,7 +175,7 @@ subdirectories for supported games.
---- ------
We've compiled a list of F.A.Q. at:
- <http://www.scummvm.org/faq/>
+ <https://www.scummvm.org/faq/>
2.0) Contact:
@@ -194,7 +195,7 @@ reproducible, and still occurs in the latest git/Daily build version.
Also check the known problems list (below) and the compatibility list
on our website for that game, to ensure the issue is not already known:
- <http://scummvm.org/compatibility/>
+ <https://www.scummvm.org/compatibility/>
Please do not report bugs for games that are not listed as being
completeable in the 'Supported Games' section, or compatibility list. We
@@ -222,7 +223,7 @@ At the moment the following games have been reported to work, and should
be playable to the end:
A more detailed compatibility list of the supported games can be found here:
- <http://www.scummvm.org/compatibility/>)
+ <https://www.scummvm.org/compatibility/>
LucasArts (SCUMM) Games:
Maniac Mansion [maniac]
@@ -544,13 +545,17 @@ ScummVM will skip copy protection in the following games:
-- bypassed with kind permission from Wyrmkeep Entertainment,
since it was bypassed in all CD releases of the game.
* Loom (EGA DOS)
+ * Lure of the Temptress
* Maniac Mansion
+ * Might and Magic: World of Xeen
* Monkey Island 2: LeChuck's Revenge
+ * Rex Nebular and The Cosmic Gender Bender
* Simon the Sorcerer 1 (Floppy version)
* Simon the Sorcerer 2 (Floppy version)
-- bypassed with kind permission from Adventure Soft,
since it was bypassed in all CD releases of the game.
* The Secret of Monkey Island (VGA)
+ * Voyeur
* Waxworks
* Zak McKracken and the Alien Mindbenders
@@ -730,7 +735,7 @@ Some re-releases of the games, as well as the PlayStation version, do
not have Smacker videos. Revolution Software has kindly allowed us to
provide re-encoded cutscenes for download on our website:
- <http://www.scummvm.org/downloads.php>
+ <https://www.scummvm.org/downloads/>
These cutscenes are provided in DXA format with FLAC audio. Their
quality is equal to the original games due to the use of lossless
@@ -920,15 +925,50 @@ game's screen to change location, similar to many adventure games, which
is simpler and more straightforward than moving around using the menu.
-3.15) Myst game notes:
+3.15 Might and Magic Xeen games notes:
+--------------------------------------
+To properly play the World of Xeen CD Talkie using original discs,
+use LAME or some other encoder to rip the cd audio tracks to files,
+either mp3 or ogg. Whichever you choose, the tracks of the first CD
+should be named from track02 to track31, whereas the second CD's
+audio tracks should be encoded and renamed as track32 through to track60.
+
+For the GOG Might and Magic 4-5 installation, install the game to your
+computer, and do the following steps:
+* The game1.inst (CUE) and game1.gog (BIN) file from the game folder is a
+CD image. Use software like Virtual CloneDrive to mount it as a drive.
+Linux and MacOS users can use bchunk to convert it to an ISO.
+* Copy all the .cc files from the subfolder in the mounted drive to a new
+empty game folder that you create for the game.
+* Copy all the music/*.ogg files from the GOG installation to your game
+folder. You'll then need to rename all of them from xeen??.ogg to track??.ogg
+* You should then be able to point ScummVM to this new game folder, and the
+CD talkie version should be detected.
+
+Savegames from either Clouds or Darkside of Xeen games can be transferred
+across to World of Xeen (that combines both games) simply by setting up
+and detecting World of Xeen (either by manually combining the two games
+or using the GOG World of Xeen installer), and then renaming the savegames
+to use the World of Xeen savegame format, by default 'worldofxeen.*'
+
+The Xeen engine also offers two custom options in the Engine tab for the
+games in the ScummVM launcher. They are:
+* To change the threshold armor breaks at for characters from -10HP to -80HP
+* To show values for inventory items, even outside of the blacksmith,
+allowing the relative strength/value of armor and weapons to be compared.
+
+3.16) Myst game notes:
----- ----------------
Left Click: Move/action
Space: Pause the game
Esc: Skip cutscene
F5: Menu
+Myst will autosave to slot 0 if no save or an autosave is present in
+slot 0.
-3.16) Nippon Safes Inc. Amiga notes:
+
+3.17) Nippon Safes Inc. Amiga notes:
----- ------------------------------
For this game, you will need disk0, , global.table, pointer and
it (en, fr, ge for the international version).
@@ -937,7 +977,7 @@ In addition, you will need to rename disk image 2 to disk1,
disk image 3 to disk2, disk image 4 to disk3 and disk image 5 to disk4.
-3.17) Quest for Glory notes:
+3.18) Quest for Glory notes:
----- ----------------------
It is possible to import characters, beginning with Quest for Glory II,
from past games to future games and continue from the stats earned
@@ -961,7 +1001,7 @@ file won't get listed on the import screen.
Example: qfg2-thief.sav
-3.18) Riven game notes:
+3.19) Riven game notes:
----- -----------------
Left Click: Move/action
Arrow Keys: Movement
@@ -973,15 +1013,18 @@ F5: Menu
Ctrl-o: Load game
Ctrl-s: Save game
+Riven will autosave to slot 0 if no save or an autosave is present in
+slot 0.
+
-3.19) Simon the Sorcerer games notes:
+3.20) Simon the Sorcerer games notes:
----- -------------------------------
If you have the dual version of Simon the Sorcerer 1 or 2 on CD, you
will find the Windows version in the main directory of the CD and the
DOS version in the DOS directory of the CD.
-3.20) Starship Titanic game notes:
+3.21) Starship Titanic game notes:
----------------------------------
Basic Movements:
Left Click: Move action
@@ -1024,7 +1067,7 @@ Ctrl + C: Open up the developer's cheat room
Ctrl + D: Open up the ScummVM Debugger
-3.21) The Curse of Monkey Island notes:
+3.22) The Curse of Monkey Island notes:
----- ---------------------------------
For this game, you will need the comi.la0, comi.la1 and comi.la2 files.
The comi.la0 file can be found on either CD, but since they are
@@ -1036,7 +1079,7 @@ two CDs. Some of the files appear on both CDs, but again they're
identical.
-3.22) The Feeble Files notes:
+3.23) The Feeble Files notes:
----- -----------------------
Amiga/Macintosh:
You need to install a small pack of cutscenes that are missing in both
@@ -1044,7 +1087,7 @@ of these versions of The Feeble Files.
It's called "The Feeble Files - Omni TV and epilogue cutscenes for the
Amiga and Macintosh versions" and you can get it here:
- <http://www.scummvm.org/games/#feeble>
+ <https://www.scummvm.org/games/#feeble>
Windows:
If you have the Windows version of The Feeble Files, there are several
@@ -1063,7 +1106,7 @@ Rename voices.wav on CD3 to voices3.wav
Rename voices.wav on CD4 to voices4.wav
-3.23) The Legend of Kyrandia notes:
+3.24) The Legend of Kyrandia notes:
----- -----------------------------
To run The Legend of Kyrandia under ScummVM you need the 'kyra.dat'
file. The file should always be included in official ScummVM packages.
@@ -1074,14 +1117,14 @@ thus you only need to grab it in case ScummVM complains about the file
being missing.
-3.24) Troll's Tale notes:
+3.25) Troll's Tale notes:
----- -------------------
The original game came in a PC booter disk, therefore it is necessary to
dump the contents of that disk in an image file and name it "troll.img"
to be able to play the game under ScummVM.
-3.25) Winnie the Pooh notes:
+3.26) Winnie the Pooh notes:
----- ----------------------
It is possible to import saved games from the original interpreter of the
game into ScummVM.
@@ -1096,7 +1139,7 @@ game's screen to change location, similar to many adventure games, which
is simpler and more straightforward than moving around using the menu.
-3.26) Sierra AGI games: Predictive Input Dialog:
+3.27) Sierra AGI games: Predictive Input Dialog:
----- ------------------------------------------
The Predictive Input Dialog is a ScummVM aid for running AGI engine
games (which notoriously require command line input) on devices with
@@ -1150,7 +1193,7 @@ naturally mapping the functionality to the numeric keypad. Also, the
dialog's buttons can be navigated with the arrow and the enter keys.
-3.27) Sierra SCI games: Simultaneous speech and subtitles:
+3.28) Sierra SCI games: Simultaneous speech and subtitles:
----- ----------------------------------------------------
Certain CD versions of Sierra SCI games had both speech and text
resources. Some have an option to toggle between the two, but there are
@@ -1240,7 +1283,7 @@ Torin's Passage CD:
to zero.
-3.28) Zork games notes:
+3.29) Zork games notes:
----- -----------------
To run the supported Zork games (Zork Nemesis: The Forbidden Lands
and Zork: Grand Inquisitor) you need to copy some (extra) data to its
@@ -1258,7 +1301,7 @@ Alternatively, download the GNU FreeFont TTF package
ttf files from the sfd directory into your ScummVM extras directory,
though at the time of writing these fonts cause some text rendering issues.
Download the subtitles patch
-<http://www.thezorklibrary.com/installguides/znpatch.zip> and unzip
+<https://www.thezorklibrary.com/installguides/znpatch.zip> and unzip
the addon directory into the game root directory
GoG version
@@ -1292,7 +1335,7 @@ Zork: Grand Inquisitor
All versions
Download the Liberation(tm) fonts package
-<https://fedorahosted.org/releases/l/i/liberation-fonts/liberation-fonts-ttf-2.00.1.tar.gz>
+<https://releases.pagure.org/liberation-fonts/liberation-fonts-ttf-2.00.1.tar.gz>
and unpack all the ttf files into your ScummVM extras directory.
Alternatively, download the GNU FreeFont TTF package
<https://ftp.gnu.org/gnu/freefont/freefont-ttf.zip> and unzip all the
@@ -1317,7 +1360,7 @@ subtitle.zfs
From CD1, copy the zassets1 directory into the game root directory
From CD2, copy the zassets2 directory into the game root directory
It's recommended to apply patch 1.2
-<http://www.thezorklibrary.com/installguides/Zpatch.exe>, but you may
+<https://www.thezorklibrary.com/installguides/Zpatch.exe>, but you may
have to install the game normally for that, as the patch has its own installer.
DVD version
@@ -1337,7 +1380,7 @@ Copy the zassetsc directory into the game root directory
Copy the zassetse directory into the game root directory
-3.29) Commodore64 games notes:
+3.30) Commodore64 games notes:
----- ------------------------
Both Maniac Mansion and Zak McKracken run but Maniac Mansion is not yet
playable. Simply name the D64 disks "maniac1.d64" and "maniac2.d64"
@@ -1351,7 +1394,7 @@ to Commodore64. We recommend using the much simpler approach described
in the previous paragraph.
-3.30) Macintosh games notes:
+3.31) Macintosh games notes:
----- ----------------------
All LucasArts SCUMM based adventures, except COMI, also exist in versions
for the Macintosh. ScummVM can use most (all?) of them, however, in some
@@ -1460,19 +1503,20 @@ arguments -- see the next section.
-h, --help Display a brief help text and exit
-z, --list-games Display list of supported games and exit
-t, --list-targets Display list of configured targets and exit
- --list-saves=TARGET Display a list of saved games for the game (TARGET) specified
+ --list-saves Display a list of saved games for the target specified
+ with --game=TARGET, or all targets if none is specified
-a, --add Add all games from current or specified directory.
If --game=ID is passed only the game with id ID is
added. See also --detect.
- Use --path=PATH before -a, --add to specify a directory.
+ Use --path=PATH to specify a directory.
--detect Display a list of games with their ID from current or
specified directory without adding it to the config.
- Use --path=PATH before --detect to specify a directory.
+ Use --path=PATH to specify a directory.
--game=ID In combination with --add or --detect only adds or attempts to
detect the game with id ID.
--auto-detect Display a list of games from current or specified directory
- and start the first one. Use --path=PATH before --auto-detect
- to specify a directory.
+ and start the first one. Use --path=PATH to specify
+ a directory.
--recursive In combination with --add or --detect recurse down all
subdirectories
--console Enable the console window (default: enabled) (Windows only)
@@ -1520,7 +1564,7 @@ arguments -- see the next section.
--native-mt32 True Roland MT-32 (disable GM emulation)
--enable-gs Enable Roland GS mode for MIDI playback
--output-rate=RATE Select output sample rate in Hz (e.g. 22050)
- --opl-driver=DRIVER Select AdLib (OPL) emulator (db, mame)
+ --opl-driver=DRIVER Select AdLib (OPL) emulator (db, mame, nuked)
--aspect-ratio Enable aspect ratio correction
--render-mode=MODE Enable additional render modes (hercGreen, hercAmber,
cga, ega, vga, amiga, fmtowns, pc9821, pc9801, 2gs,
@@ -1947,11 +1991,24 @@ saved games from the old default location, to the new default location.
6.1) Autosaves:
---- ----------
-For some games (namely "Beneath a Steel Sky", "Flight of the Amazon
-Queen", all AGI games, and all SCUMM games), ScummVM will by default
-automatically save the current state every five minutes (adjustable via
-the "autosave_period" config setting). For the AGI and SCUMM engines, it
-will save in Slot 0. For the SCUMM engine, this saved game can then be
+For some games ScummVM will by default automatically save the current state
+every five minutes (adjustable via the "autosave_period" config setting).
+The default autosave slot for many engines is slot 0.
+
+The games/engines listed below have autosave support.
+
+AGI games
+Beneath a Steel Sky
+Bud Tucker in Double Trouble
+COMPOSER games
+Flight of the Amazon Queen
+Myst
+Riven
+SCUMM games
+The Legend of Kyrandia I (slot 999)
+ZVISION games
+
+For the SCUMM engine, this saved game can then be
loaded again via Ctrl-0, or the F5 menu.
@@ -2006,9 +2063,10 @@ Where 'xxx' is exact the saved game slot (i.e., 001) under ScummVM
--list-saves:
This switch may be used to display a list of the current saved games
- of the specified target game and their corresponding save slots.
+ of the specified target game and their corresponding save slots. If no
+ target is specified, it lists saved games for all known target.
- Usage: --list-saves=[TARGET], where [TARGET] is the target game.
+ Usage: --list-saves --game=[TARGET], where [TARGET] is the target game.
Engines which currently support --list-saves are:
@@ -2630,6 +2688,10 @@ The following keywords are recognized:
cdrom number Number of CD-ROM unit to use for audio. If
negative, don't even try to access the CD-ROM.
joystick_num number Number of joystick device to use for input
+ controller_map_db string A custom controller mapping file to load to
+ complete default database (SDL backend only).
+ Otherwise, file gamecontrollerdb.txt will be
+ loaded from extrapath.
music_driver string The music engine to use.
opl_driver string The AdLib (OPL) emulator to use.
output_rate number The output sample rate to use, in Hz. Sensible
@@ -2852,12 +2914,12 @@ compressed sound. For compressed save states, zlib is required.
Some parts of ScummVM, particularly scalers, have highly optimized
versions written in assembler. If you wish to use this option, you will
-need to install nasm assembler (see <http://www.nasm.us/>). Note that
+need to install nasm assembler (see <https://www.nasm.us/>). Note that
we currently only have x86 MMX optimized versions, and they will not
compile on other processors.
-On Win9x/NT/XP, you can define USE_WINDBG and attach WinDbg to browse
-debug messages (see <https://technet.microsoft.com/en-us/sysinternals/debugview.aspx>).
+On Windows, you can define USE_WINDBG and attach WinDbg to browse
+debug messages (see <https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/index>).
Windows:
@@ -2948,11 +3010,11 @@ debug messages (see <https://technet.microsoft.com/en-us/sysinternals/debugview.
----- -------
Please refer to our extensive Credits list at:
- <http://www.scummvm.org/credits>
+ <https://www.scummvm.org/credits/>
------------------------------------------------------------------------
Good Luck and Happy Adventuring!
The ScummVM team.
-<http://www.scummvm.org/>
+<https://www.scummvm.org/>
------------------------------------------------------------------------
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index a43b08c422..3a003c80d9 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -25,6 +25,7 @@
#include "audio/mixer.h"
#include "audio/softsynth/opl/dosbox.h"
#include "audio/softsynth/opl/mame.h"
+#include "audio/softsynth/opl/nuked.h"
#include "common/config-manager.h"
#include "common/system.h"
@@ -42,13 +43,21 @@ namespace ALSA {
} // End of namespace ALSA
#endif // USE_ALSA
+#ifdef ENABLE_OPL2LPT
+namespace OPL2LPT {
+ OPL *create();
+} // End of namespace OPL2LPT
+#endif // ENABLE_OPL2LPT
+
// Config implementation
enum OplEmulator {
kAuto = 0,
kMame = 1,
kDOSBox = 2,
- kALSA = 3
+ kALSA = 3,
+ kNuked = 4,
+ kOPL2LPT = 5
};
OPL::OPL() {
@@ -63,9 +72,15 @@ const Config::EmulatorDescription Config::_drivers[] = {
#ifndef DISABLE_DOSBOX_OPL
{ "db", _s("DOSBox OPL emulator"), kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },
#endif
+#ifndef DISABLE_NUKED_OPL
+ { "nuked", _s("Nuked OPL emulator"), kNuked, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },
+#endif
#ifdef USE_ALSA
{ "alsa", _s("ALSA Direct FM"), kALSA, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },
#endif
+#ifdef ENABLE_OPL2LPT
+ { "opl2lpt", _s("OPL2LPT"), kOPL2LPT, kFlagOpl2 },
+#endif
{ 0, 0, 0, 0 }
};
@@ -178,11 +193,25 @@ OPL *Config::create(DriverId driver, OplType type) {
return new DOSBox::OPL(type);
#endif
+#ifndef DISABLE_NUKED_OPL
+ case kNuked:
+ return new NUKED::OPL(type);
+#endif
+
#ifdef USE_ALSA
case kALSA:
return ALSA::create(type);
#endif
+#ifdef ENABLE_OPL2LPT
+ case kOPL2LPT:
+ if (type == kOpl2)
+ return OPL2LPT::create();
+ else
+ warning("OPL2LPT only supports OPL2");
+ return 0;
+#endif
+
default:
warning("Unsupported OPL emulator %d", driver);
// TODO: Maybe we should add some dummy emulator too, which just outputs
diff --git a/audio/mixer.cpp b/audio/mixer.cpp
index 16cf5640eb..274f8e9de6 100644
--- a/audio/mixer.cpp
+++ b/audio/mixer.cpp
@@ -471,10 +471,7 @@ void MixerImpl::setVolumeForSoundType(SoundType type, int volume) {
assert(0 <= (int)type && (int)type < ARRAYSIZE(_soundTypeSettings));
// Check range
- if (volume > kMaxMixerVolume)
- volume = kMaxMixerVolume;
- else if (volume < 0)
- volume = 0;
+ volume = CLIP<int>(volume, 0, kMaxMixerVolume);
// TODO: Maybe we should do logarithmic (not linear) volume
// scaling? See also Player_V2::setMasterVolume
diff --git a/audio/module.mk b/audio/module.mk
index 0d95ecc6f1..49584aba90 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -60,11 +60,23 @@ MODULE_OBJS := \
softsynth/sid.o \
softsynth/wave6581.o
+ifndef DISABLE_NUKED_OPL
+MODULE_OBJS += \
+ softsynth/opl/nuked.o
+endif
+
+
+
ifdef USE_ALSA
MODULE_OBJS += \
alsa_opl.o
endif
+ifdef ENABLE_OPL2LPT
+MODULE_OBJS += \
+ opl2lpt.o
+endif
+
ifndef USE_ARM_SOUND_ASM
MODULE_OBJS += \
rate.o
diff --git a/audio/opl2lpt.cpp b/audio/opl2lpt.cpp
new file mode 100644
index 0000000000..fc5a4ef465
--- /dev/null
+++ b/audio/opl2lpt.cpp
@@ -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.
+ *
+ */
+
+/* OPL implementation for OPL2LPT through libieee1284.
+ */
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "common/scummsys.h"
+
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/str.h"
+#include "common/textconsole.h"
+#include "audio/fmopl.h"
+
+#include <unistd.h>
+#include <ieee1284.h>
+
+namespace OPL {
+namespace OPL2LPT {
+
+class OPL : public ::OPL::RealOPL {
+private:
+ struct parport *_pport;
+ int index;
+ static const uint8 ctrlBytes[];
+
+public:
+ OPL();
+ ~OPL();
+
+ bool init();
+ void reset();
+
+ void write(int a, int v);
+ byte read(int a);
+
+ void writeReg(int r, int v);
+};
+
+const uint8 OPL::ctrlBytes[] = {
+ (C1284_NSELECTIN | C1284_NSTROBE | C1284_NINIT) ^ C1284_INVERTED,
+ (C1284_NSELECTIN | C1284_NSTROBE) ^ C1284_INVERTED,
+ (C1284_NSELECTIN | C1284_NSTROBE | C1284_NINIT) ^ C1284_INVERTED,
+
+ (C1284_NSELECTIN | C1284_NINIT) ^ C1284_INVERTED,
+ C1284_NSELECTIN ^ C1284_INVERTED,
+ (C1284_NSELECTIN | C1284_NINIT) ^ C1284_INVERTED
+};
+
+OPL::OPL() : _pport(nullptr) {
+}
+
+OPL::~OPL() {
+ if (_pport) {
+ stop();
+ reset();
+ ieee1284_close(_pport);
+ }
+}
+
+bool OPL::init() {
+ struct parport_list parports = {};
+ const Common::String parportName = ConfMan.get("opl2lpt_parport");
+
+ // Look for available parallel ports
+ if (ieee1284_find_ports(&parports, 0) != E1284_OK) {
+ return false;
+ }
+ for (int i = 0; i < parports.portc; i++) {
+ if (parportName == "null" ||
+ parportName == parports.portv[i]->name) {
+ int caps = CAP1284_RAW;
+ _pport = parports.portv[i];
+ if (ieee1284_open(_pport, F1284_EXCL, &caps) != E1284_OK) {
+ warning("cannot open parallel port %s", _pport->name);
+ }
+ if (ieee1284_claim(_pport) != E1284_OK) {
+ warning("cannot claim parallel port %s", _pport->name);
+ ieee1284_close(_pport);
+ continue;
+ }
+ reset();
+ // Safe to free ports here, opened ports are refcounted.
+ ieee1284_free_ports(&parports);
+ return true;
+ }
+ }
+ _pport = nullptr;
+ ieee1284_free_ports(&parports);
+ return false;
+}
+
+void OPL::reset() {
+ for(int i = 0; i < 256; i ++) {
+ writeReg(i, 0);
+ }
+ index = 0;
+}
+
+void OPL::write(int port, int val) {
+ if (port & 1) {
+ writeReg(index, val);
+ } else {
+ index = val;
+ }
+}
+
+byte OPL::read(int port) {
+ // No read support for the OPL2LPT
+ return 0;
+}
+
+void OPL::writeReg(int r, int v) {
+ r &= 0xff;
+ v &= 0xff;
+ ieee1284_write_data(_pport, r);
+ ieee1284_write_control(_pport, ctrlBytes[0]);
+ ieee1284_write_control(_pport, ctrlBytes[1]);
+ ieee1284_write_control(_pport, ctrlBytes[2]);
+ usleep(4); // 3.3 us
+
+ ieee1284_write_data(_pport, v);
+ ieee1284_write_control(_pport, ctrlBytes[3]);
+ ieee1284_write_control(_pport, ctrlBytes[4]);
+ ieee1284_write_control(_pport, ctrlBytes[5]);
+ usleep(23);
+}
+
+OPL *create() {
+ return new OPL();
+}
+
+} // End of namespace OPL2LPT
+} // End of namespace OPL
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 46b1a6406d..c02b047153 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -572,7 +572,7 @@ void TownsMidiOutputChannel::keyOff() {
void TownsMidiOutputChannel::keyOnSetFreq(uint16 frq) {
uint16 note = (frq << 1) >> 8;
- frq = (_freqMSB[note] << 11) | _freqLSB[note] ;
+ frq = (_freqMSB[note] << 11) | _freqLSB[note];
out(0xa4, frq >> 8);
out(0xa0, frq & 0xff);
//out(0x28, 0x00);
diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp
index eb08582da0..cba95422fc 100644
--- a/audio/softsynth/opl/mame.cpp
+++ b/audio/softsynth/opl/mame.cpp
@@ -29,6 +29,10 @@
#include <stdarg.h>
#include <math.h>
+#if defined(__DS__)
+#include "dsmain.h"
+#endif
+
#include "mame.h"
#include "audio/mixer.h"
@@ -40,10 +44,6 @@
#include "common/config-manager.h"
#endif
-#if defined(__DS__)
-#include "dsmain.h"
-#endif
-
namespace OPL {
namespace MAME {
diff --git a/audio/softsynth/opl/nuked.cpp b/audio/softsynth/opl/nuked.cpp
new file mode 100644
index 0000000000..273cbdfa18
--- /dev/null
+++ b/audio/softsynth/opl/nuked.cpp
@@ -0,0 +1,1487 @@
+//
+// Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT)
+//
+// 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.
+//
+//
+// Nuked OPL3 emulator.
+// Thanks:
+// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
+// Feedback and Rhythm part calculation information.
+// forums.submarine.org.uk(carbon14, opl3):
+// Tremolo and phase generator calculation information.
+// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
+// OPL2 ROMs.
+// siliconpr0n.org(John McMaster, digshadow):
+// YMF262 and VRC VII decaps and die shots.
+//
+// version: 1.8
+//
+
+#include <stdlib.h>
+#include <string.h>
+#include "audio/mixer.h"
+#include "common/system.h"
+#include "common/scummsys.h"
+#include "nuked.h"
+
+#ifndef DISABLE_NUKED_OPL
+
+namespace OPL {
+namespace NUKED {
+
+#define RSM_FRAC 10
+
+// Channel types
+
+enum {
+ ch_2op = 0,
+ ch_4op = 1,
+ ch_4op2 = 2,
+ ch_drum = 3
+};
+
+// Envelope key types
+
+enum {
+ egk_norm = 0x01,
+ egk_drum = 0x02
+};
+
+
+//
+// logsin table
+//
+
+static const Bit16u logsinrom[256] = {
+ 0x859, 0x6c3, 0x607, 0x58b, 0x52e, 0x4e4, 0x4a6, 0x471,
+ 0x443, 0x41a, 0x3f5, 0x3d3, 0x3b5, 0x398, 0x37e, 0x365,
+ 0x34e, 0x339, 0x324, 0x311, 0x2ff, 0x2ed, 0x2dc, 0x2cd,
+ 0x2bd, 0x2af, 0x2a0, 0x293, 0x286, 0x279, 0x26d, 0x261,
+ 0x256, 0x24b, 0x240, 0x236, 0x22c, 0x222, 0x218, 0x20f,
+ 0x206, 0x1fd, 0x1f5, 0x1ec, 0x1e4, 0x1dc, 0x1d4, 0x1cd,
+ 0x1c5, 0x1be, 0x1b7, 0x1b0, 0x1a9, 0x1a2, 0x19b, 0x195,
+ 0x18f, 0x188, 0x182, 0x17c, 0x177, 0x171, 0x16b, 0x166,
+ 0x160, 0x15b, 0x155, 0x150, 0x14b, 0x146, 0x141, 0x13c,
+ 0x137, 0x133, 0x12e, 0x129, 0x125, 0x121, 0x11c, 0x118,
+ 0x114, 0x10f, 0x10b, 0x107, 0x103, 0x0ff, 0x0fb, 0x0f8,
+ 0x0f4, 0x0f0, 0x0ec, 0x0e9, 0x0e5, 0x0e2, 0x0de, 0x0db,
+ 0x0d7, 0x0d4, 0x0d1, 0x0cd, 0x0ca, 0x0c7, 0x0c4, 0x0c1,
+ 0x0be, 0x0bb, 0x0b8, 0x0b5, 0x0b2, 0x0af, 0x0ac, 0x0a9,
+ 0x0a7, 0x0a4, 0x0a1, 0x09f, 0x09c, 0x099, 0x097, 0x094,
+ 0x092, 0x08f, 0x08d, 0x08a, 0x088, 0x086, 0x083, 0x081,
+ 0x07f, 0x07d, 0x07a, 0x078, 0x076, 0x074, 0x072, 0x070,
+ 0x06e, 0x06c, 0x06a, 0x068, 0x066, 0x064, 0x062, 0x060,
+ 0x05e, 0x05c, 0x05b, 0x059, 0x057, 0x055, 0x053, 0x052,
+ 0x050, 0x04e, 0x04d, 0x04b, 0x04a, 0x048, 0x046, 0x045,
+ 0x043, 0x042, 0x040, 0x03f, 0x03e, 0x03c, 0x03b, 0x039,
+ 0x038, 0x037, 0x035, 0x034, 0x033, 0x031, 0x030, 0x02f,
+ 0x02e, 0x02d, 0x02b, 0x02a, 0x029, 0x028, 0x027, 0x026,
+ 0x025, 0x024, 0x023, 0x022, 0x021, 0x020, 0x01f, 0x01e,
+ 0x01d, 0x01c, 0x01b, 0x01a, 0x019, 0x018, 0x017, 0x017,
+ 0x016, 0x015, 0x014, 0x014, 0x013, 0x012, 0x011, 0x011,
+ 0x010, 0x00f, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c, 0x00c,
+ 0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x008, 0x008, 0x007,
+ 0x007, 0x007, 0x006, 0x006, 0x005, 0x005, 0x005, 0x004,
+ 0x004, 0x004, 0x003, 0x003, 0x003, 0x002, 0x002, 0x002,
+ 0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000
+};
+
+//
+// exp table
+//
+
+static const Bit16u exprom[256] = {
+ 0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4,
+ 0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9,
+ 0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f,
+ 0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756,
+ 0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e,
+ 0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706,
+ 0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0,
+ 0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba,
+ 0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695,
+ 0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671,
+ 0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e,
+ 0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b,
+ 0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609,
+ 0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8,
+ 0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8,
+ 0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8,
+ 0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589,
+ 0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b,
+ 0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d,
+ 0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530,
+ 0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514,
+ 0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8,
+ 0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc,
+ 0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2,
+ 0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8,
+ 0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e,
+ 0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475,
+ 0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d,
+ 0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445,
+ 0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d,
+ 0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416,
+ 0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400
+};
+
+//
+// freq mult table multiplied by 2
+//
+// 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 12, 15, 15
+//
+
+static const Bit8u mt[16] = {
+ 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 24, 24, 30, 30
+};
+
+//
+// ksl table
+//
+
+static const Bit8u kslrom[16] = {
+ 0, 32, 40, 45, 48, 51, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64
+};
+
+static const Bit8u kslshift[4] = {
+ 8, 1, 2, 0
+};
+
+//
+// envelope generator constants
+//
+
+static const Bit8u eg_incstep[4][4] = {
+ { 0, 0, 0, 0 },
+ { 1, 0, 0, 0 },
+ { 1, 0, 1, 0 },
+ { 1, 1, 1, 0 }
+};
+
+//
+// address decoding
+//
+
+static const Bit8s ad_slot[0x20] = {
+ 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1,
+ 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static const Bit8u ch_slot[18] = {
+ 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32
+};
+
+//
+// Envelope generator
+//
+
+typedef Bit16s(*envelope_sinfunc)(Bit16u phase, Bit16u envelope);
+typedef void(*envelope_genfunc)(opl3_slot *slott);
+
+static Bit16s OPL3_EnvelopeCalcExp(Bit32u level)
+{
+ if (level > 0x1fff)
+ {
+ level = 0x1fff;
+ }
+ return (exprom[level & 0xff] << 1) >> (level >> 8);
+}
+
+static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope)
+{
+ Bit16u out = 0;
+ Bit16u neg = 0;
+ phase &= 0x3ff;
+ if (phase & 0x200)
+ {
+ neg = 0xffff;
+ }
+ if (phase & 0x100)
+ {
+ out = logsinrom[(phase & 0xff) ^ 0xff];
+ }
+ else
+ {
+ out = logsinrom[phase & 0xff];
+ }
+ return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg;
+}
+
+static Bit16s OPL3_EnvelopeCalcSin1(Bit16u phase, Bit16u envelope)
+{
+ Bit16u out = 0;
+ phase &= 0x3ff;
+ if (phase & 0x200)
+ {
+ out = 0x1000;
+ }
+ else if (phase & 0x100)
+ {
+ out = logsinrom[(phase & 0xff) ^ 0xff];
+ }
+ else
+ {
+ out = logsinrom[phase & 0xff];
+ }
+ return OPL3_EnvelopeCalcExp(out + (envelope << 3));
+}
+
+static Bit16s OPL3_EnvelopeCalcSin2(Bit16u phase, Bit16u envelope)
+{
+ Bit16u out = 0;
+ phase &= 0x3ff;
+ if (phase & 0x100)
+ {
+ out = logsinrom[(phase & 0xff) ^ 0xff];
+ }
+ else
+ {
+ out = logsinrom[phase & 0xff];
+ }
+ return OPL3_EnvelopeCalcExp(out + (envelope << 3));
+}
+
+static Bit16s OPL3_EnvelopeCalcSin3(Bit16u phase, Bit16u envelope)
+{
+ Bit16u out = 0;
+ phase &= 0x3ff;
+ if (phase & 0x100)
+ {
+ out = 0x1000;
+ }
+ else
+ {
+ out = logsinrom[phase & 0xff];
+ }
+ return OPL3_EnvelopeCalcExp(out + (envelope << 3));
+}
+
+static Bit16s OPL3_EnvelopeCalcSin4(Bit16u phase, Bit16u envelope)
+{
+ Bit16u out = 0;
+ Bit16u neg = 0;
+ phase &= 0x3ff;
+ if ((phase & 0x300) == 0x100)
+ {
+ neg = 0xffff;
+ }
+ if (phase & 0x200)
+ {
+ out = 0x1000;
+ }
+ else if (phase & 0x80)
+ {
+ out = logsinrom[((phase ^ 0xff) << 1) & 0xff];
+ }
+ else
+ {
+ out = logsinrom[(phase << 1) & 0xff];
+ }
+ return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg;
+}
+
+static Bit16s OPL3_EnvelopeCalcSin5(Bit16u phase, Bit16u envelope)
+{
+ Bit16u out = 0;
+ phase &= 0x3ff;
+ if (phase & 0x200)
+ {
+ out = 0x1000;
+ }
+ else if (phase & 0x80)
+ {
+ out = logsinrom[((phase ^ 0xff) << 1) & 0xff];
+ }
+ else
+ {
+ out = logsinrom[(phase << 1) & 0xff];
+ }
+ return OPL3_EnvelopeCalcExp(out + (envelope << 3));
+}
+
+static Bit16s OPL3_EnvelopeCalcSin6(Bit16u phase, Bit16u envelope)
+{
+ Bit16u neg = 0;
+ phase &= 0x3ff;
+ if (phase & 0x200)
+ {
+ neg = 0xffff;
+ }
+ return OPL3_EnvelopeCalcExp(envelope << 3) ^ neg;
+}
+
+static Bit16s OPL3_EnvelopeCalcSin7(Bit16u phase, Bit16u envelope)
+{
+ Bit16u out = 0;
+ Bit16u neg = 0;
+ phase &= 0x3ff;
+ if (phase & 0x200)
+ {
+ neg = 0xffff;
+ phase = (phase & 0x1ff) ^ 0x1ff;
+ }
+ out = phase << 3;
+ return OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg;
+}
+
+static const envelope_sinfunc envelope_sin[8] = {
+ OPL3_EnvelopeCalcSin0,
+ OPL3_EnvelopeCalcSin1,
+ OPL3_EnvelopeCalcSin2,
+ OPL3_EnvelopeCalcSin3,
+ OPL3_EnvelopeCalcSin4,
+ OPL3_EnvelopeCalcSin5,
+ OPL3_EnvelopeCalcSin6,
+ OPL3_EnvelopeCalcSin7
+};
+
+enum envelope_gen_num
+{
+ envelope_gen_num_attack = 0,
+ envelope_gen_num_decay = 1,
+ envelope_gen_num_sustain = 2,
+ envelope_gen_num_release = 3
+};
+
+static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot)
+{
+ Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2)
+ - ((0x08 - slot->channel->block) << 5);
+ if (ksl < 0)
+ {
+ ksl = 0;
+ }
+ slot->eg_ksl = (Bit8u)ksl;
+}
+
+static void OPL3_EnvelopeCalc(opl3_slot *slot)
+{
+ Bit8u nonzero;
+ Bit8u rate;
+ Bit8u rate_hi;
+ Bit8u rate_lo;
+ Bit8u reg_rate = 0;
+ Bit8u ks;
+ Bit8u eg_shift, shift;
+ Bit16u eg_rout;
+ Bit16s eg_inc;
+ Bit8u eg_off;
+ Bit8u reset = 0;
+ slot->eg_out = slot->eg_rout + (slot->reg_tl << 2)
+ + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem;
+ if (slot->key && slot->eg_gen == envelope_gen_num_release)
+ {
+ reset = 1;
+ reg_rate = slot->reg_ar;
+ }
+ else
+ {
+ switch (slot->eg_gen)
+ {
+ case envelope_gen_num_attack:
+ reg_rate = slot->reg_ar;
+ break;
+ case envelope_gen_num_decay:
+ reg_rate = slot->reg_dr;
+ break;
+ case envelope_gen_num_sustain:
+ if (!slot->reg_type)
+ {
+ reg_rate = slot->reg_rr;
+ }
+ break;
+ case envelope_gen_num_release:
+ reg_rate = slot->reg_rr;
+ break;
+ }
+ }
+ slot->pg_reset = reset;
+ ks = slot->channel->ksv >> ((slot->reg_ksr ^ 1) << 1);
+ nonzero = (reg_rate != 0);
+ rate = ks + (reg_rate << 2);
+ rate_hi = rate >> 2;
+ rate_lo = rate & 0x03;
+ if (rate_hi & 0x10)
+ {
+ rate_hi = 0x0f;
+ }
+ eg_shift = rate_hi + slot->chip->eg_add;
+ shift = 0;
+ if (nonzero)
+ {
+ if (rate_hi < 12)
+ {
+ if (slot->chip->eg_state)
+ {
+ switch (eg_shift)
+ {
+ case 12:
+ shift = 1;
+ break;
+ case 13:
+ shift = (rate_lo >> 1) & 0x01;
+ break;
+ case 14:
+ shift = rate_lo & 0x01;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->timer & 0x03];
+ if (shift & 0x04)
+ {
+ shift = 0x03;
+ }
+ if (!shift)
+ {
+ shift = slot->chip->eg_state;
+ }
+ }
+ }
+ eg_rout = slot->eg_rout;
+ eg_inc = 0;
+ eg_off = 0;
+ // Instant attack
+ if (reset && rate_hi == 0x0f)
+ {
+ eg_rout = 0x00;
+ }
+ // Envelope off
+ if ((slot->eg_rout & 0x1f8) == 0x1f8)
+ {
+ eg_off = 1;
+ }
+ if (slot->eg_gen != envelope_gen_num_attack && !reset && eg_off)
+ {
+ eg_rout = 0x1ff;
+ }
+ switch (slot->eg_gen)
+ {
+ case envelope_gen_num_attack:
+ if (!slot->eg_rout)
+ {
+ slot->eg_gen = envelope_gen_num_decay;
+ }
+ else if (slot->key && shift > 0 && rate_hi != 0x0f)
+ {
+ eg_inc = ((~slot->eg_rout) << shift) >> 4;
+ }
+ break;
+ case envelope_gen_num_decay:
+ if ((slot->eg_rout >> 4) == slot->reg_sl)
+ {
+ slot->eg_gen = envelope_gen_num_sustain;
+ }
+ else if (!eg_off && !reset && shift > 0)
+ {
+ eg_inc = 1 << (shift - 1);
+ }
+ break;
+ case envelope_gen_num_sustain:
+ case envelope_gen_num_release:
+ if (!eg_off && !reset && shift > 0)
+ {
+ eg_inc = 1 << (shift - 1);
+ }
+ break;
+ }
+ slot->eg_rout = (eg_rout + eg_inc) & 0x1ff;
+ // Key off
+ if (reset)
+ {
+ slot->eg_gen = envelope_gen_num_attack;
+ }
+ if (!slot->key)
+ {
+ slot->eg_gen = envelope_gen_num_release;
+ }
+}
+
+static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type)
+{
+ slot->key |= type;
+}
+
+static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type)
+{
+ slot->key &= ~type;
+}
+
+//
+// Phase Generator
+//
+
+static void OPL3_PhaseGenerate(opl3_slot *slot)
+{
+ opl3_chip *chip;
+ Bit16u f_num;
+ Bit32u basefreq;
+ Bit8u rm_xor, n_bit;
+ Bit32u noise;
+ Bit16u phase;
+
+ chip = slot->chip;
+ f_num = slot->channel->f_num;
+ if (slot->reg_vib)
+ {
+ Bit8s range;
+ Bit8u vibpos;
+
+ range = (f_num >> 7) & 7;
+ vibpos = slot->chip->vibpos;
+
+ if (!(vibpos & 3))
+ {
+ range = 0;
+ }
+ else if (vibpos & 1)
+ {
+ range >>= 1;
+ }
+ range >>= slot->chip->vibshift;
+
+ if (vibpos & 4)
+ {
+ range = -range;
+ }
+ f_num += range;
+ }
+ basefreq = (f_num << slot->channel->block) >> 1;
+ phase = (Bit16u)(slot->pg_phase >> 9);
+ if (slot->pg_reset)
+ {
+ slot->pg_phase = 0;
+ }
+ slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1;
+ // Rhythm mode
+ noise = chip->noise;
+ slot->pg_phase_out = phase;
+ if (slot->slot_num == 13) // hh
+ {
+ chip->rm_hh_bit2 = (phase >> 2) & 1;
+ chip->rm_hh_bit3 = (phase >> 3) & 1;
+ chip->rm_hh_bit7 = (phase >> 7) & 1;
+ chip->rm_hh_bit8 = (phase >> 8) & 1;
+ }
+ if (slot->slot_num == 17 && (chip->rhy & 0x20)) // tc
+ {
+ chip->rm_tc_bit3 = (phase >> 3) & 1;
+ chip->rm_tc_bit5 = (phase >> 5) & 1;
+ }
+ if (chip->rhy & 0x20)
+ {
+ rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7)
+ | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5)
+ | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5);
+ switch (slot->slot_num)
+ {
+ case 13: // hh
+ slot->pg_phase_out = rm_xor << 9;
+ if (rm_xor ^ (noise & 1))
+ {
+ slot->pg_phase_out |= 0xd0;
+ }
+ else
+ {
+ slot->pg_phase_out |= 0x34;
+ }
+ break;
+ case 16: // sd
+ slot->pg_phase_out = (chip->rm_hh_bit8 << 9)
+ | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8);
+ break;
+ case 17: // tc
+ slot->pg_phase_out = (rm_xor << 9) | 0x80;
+ break;
+ default:
+ break;
+ }
+ }
+ n_bit = ((noise >> 14) ^ noise) & 0x01;
+ chip->noise = (noise >> 1) | (n_bit << 22);
+}
+
+//
+// Slot
+//
+
+static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data)
+{
+ if ((data >> 7) & 0x01)
+ {
+ slot->trem = &slot->chip->tremolo;
+ }
+ else
+ {
+ slot->trem = (Bit8u*)&slot->chip->zeromod;
+ }
+ slot->reg_vib = (data >> 6) & 0x01;
+ slot->reg_type = (data >> 5) & 0x01;
+ slot->reg_ksr = (data >> 4) & 0x01;
+ slot->reg_mult = data & 0x0f;
+}
+
+static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data)
+{
+ slot->reg_ksl = (data >> 6) & 0x03;
+ slot->reg_tl = data & 0x3f;
+ OPL3_EnvelopeUpdateKSL(slot);
+}
+
+static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data)
+{
+ slot->reg_ar = (data >> 4) & 0x0f;
+ slot->reg_dr = data & 0x0f;
+}
+
+static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data)
+{
+ slot->reg_sl = (data >> 4) & 0x0f;
+ if (slot->reg_sl == 0x0f)
+ {
+ slot->reg_sl = 0x1f;
+ }
+ slot->reg_rr = data & 0x0f;
+}
+
+static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data)
+{
+ slot->reg_wf = data & 0x07;
+ if (slot->chip->newm == 0x00)
+ {
+ slot->reg_wf &= 0x03;
+ }
+}
+
+static void OPL3_SlotGenerate(opl3_slot *slot)
+{
+ slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out);
+}
+
+static void OPL3_SlotCalcFB(opl3_slot *slot)
+{
+ if (slot->channel->fb != 0x00)
+ {
+ slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->channel->fb);
+ }
+ else
+ {
+ slot->fbmod = 0;
+ }
+ slot->prout = slot->out;
+}
+
+//
+// Channel
+//
+
+static void OPL3_ChannelSetupAlg(opl3_channel *channel);
+
+static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data)
+{
+ opl3_channel *channel6;
+ opl3_channel *channel7;
+ opl3_channel *channel8;
+ Bit8u chnum;
+
+ chip->rhy = data & 0x3f;
+ if (chip->rhy & 0x20)
+ {
+ channel6 = &chip->channel[6];
+ channel7 = &chip->channel[7];
+ channel8 = &chip->channel[8];
+ channel6->out[0] = &channel6->slots[1]->out;
+ channel6->out[1] = &channel6->slots[1]->out;
+ channel6->out[2] = &chip->zeromod;
+ channel6->out[3] = &chip->zeromod;
+ channel7->out[0] = &channel7->slots[0]->out;
+ channel7->out[1] = &channel7->slots[0]->out;
+ channel7->out[2] = &channel7->slots[1]->out;
+ channel7->out[3] = &channel7->slots[1]->out;
+ channel8->out[0] = &channel8->slots[0]->out;
+ channel8->out[1] = &channel8->slots[0]->out;
+ channel8->out[2] = &channel8->slots[1]->out;
+ channel8->out[3] = &channel8->slots[1]->out;
+ for (chnum = 6; chnum < 9; chnum++)
+ {
+ chip->channel[chnum].chtype = ch_drum;
+ }
+ OPL3_ChannelSetupAlg(channel6);
+ OPL3_ChannelSetupAlg(channel7);
+ OPL3_ChannelSetupAlg(channel8);
+ //hh
+ if (chip->rhy & 0x01)
+ {
+ OPL3_EnvelopeKeyOn(channel7->slots[0], egk_drum);
+ }
+ else
+ {
+ OPL3_EnvelopeKeyOff(channel7->slots[0], egk_drum);
+ }
+ //tc
+ if (chip->rhy & 0x02)
+ {
+ OPL3_EnvelopeKeyOn(channel8->slots[1], egk_drum);
+ }
+ else
+ {
+ OPL3_EnvelopeKeyOff(channel8->slots[1], egk_drum);
+ }
+ //tom
+ if (chip->rhy & 0x04)
+ {
+ OPL3_EnvelopeKeyOn(channel8->slots[0], egk_drum);
+ }
+ else
+ {
+ OPL3_EnvelopeKeyOff(channel8->slots[0], egk_drum);
+ }
+ //sd
+ if (chip->rhy & 0x08)
+ {
+ OPL3_EnvelopeKeyOn(channel7->slots[1], egk_drum);
+ }
+ else
+ {
+ OPL3_EnvelopeKeyOff(channel7->slots[1], egk_drum);
+ }
+ //bd
+ if (chip->rhy & 0x10)
+ {
+ OPL3_EnvelopeKeyOn(channel6->slots[0], egk_drum);
+ OPL3_EnvelopeKeyOn(channel6->slots[1], egk_drum);
+ }
+ else
+ {
+ OPL3_EnvelopeKeyOff(channel6->slots[0], egk_drum);
+ OPL3_EnvelopeKeyOff(channel6->slots[1], egk_drum);
+ }
+ }
+ else
+ {
+ for (chnum = 6; chnum < 9; chnum++)
+ {
+ chip->channel[chnum].chtype = ch_2op;
+ OPL3_ChannelSetupAlg(&chip->channel[chnum]);
+ OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[0], egk_drum);
+ OPL3_EnvelopeKeyOff(chip->channel[chnum].slots[1], egk_drum);
+ }
+ }
+}
+
+static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data)
+{
+ if (channel->chip->newm && channel->chtype == ch_4op2)
+ {
+ return;
+ }
+ channel->f_num = (channel->f_num & 0x300) | data;
+ channel->ksv = (channel->block << 1)
+ | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01);
+ OPL3_EnvelopeUpdateKSL(channel->slots[0]);
+ OPL3_EnvelopeUpdateKSL(channel->slots[1]);
+ if (channel->chip->newm && channel->chtype == ch_4op)
+ {
+ channel->pair->f_num = channel->f_num;
+ channel->pair->ksv = channel->ksv;
+ OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]);
+ OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]);
+ }
+}
+
+static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data)
+{
+ if (channel->chip->newm && channel->chtype == ch_4op2)
+ {
+ return;
+ }
+ channel->f_num = (channel->f_num & 0xff) | ((data & 0x03) << 8);
+ channel->block = (data >> 2) & 0x07;
+ channel->ksv = (channel->block << 1)
+ | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01);
+ OPL3_EnvelopeUpdateKSL(channel->slots[0]);
+ OPL3_EnvelopeUpdateKSL(channel->slots[1]);
+ if (channel->chip->newm && channel->chtype == ch_4op)
+ {
+ channel->pair->f_num = channel->f_num;
+ channel->pair->block = channel->block;
+ channel->pair->ksv = channel->ksv;
+ OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]);
+ OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]);
+ }
+}
+
+static void OPL3_ChannelSetupAlg(opl3_channel *channel)
+{
+ if (channel->chtype == ch_drum)
+ {
+ if (channel->ch_num == 7 || channel->ch_num == 8)
+ {
+ channel->slots[0]->mod = &channel->chip->zeromod;
+ channel->slots[1]->mod = &channel->chip->zeromod;
+ return;
+ }
+ switch (channel->alg & 0x01)
+ {
+ case 0x00:
+ channel->slots[0]->mod = &channel->slots[0]->fbmod;
+ channel->slots[1]->mod = &channel->slots[0]->out;
+ break;
+ case 0x01:
+ channel->slots[0]->mod = &channel->slots[0]->fbmod;
+ channel->slots[1]->mod = &channel->chip->zeromod;
+ break;
+ }
+ return;
+ }
+ if (channel->alg & 0x08)
+ {
+ return;
+ }
+ if (channel->alg & 0x04)
+ {
+ channel->pair->out[0] = &channel->chip->zeromod;
+ channel->pair->out[1] = &channel->chip->zeromod;
+ channel->pair->out[2] = &channel->chip->zeromod;
+ channel->pair->out[3] = &channel->chip->zeromod;
+ switch (channel->alg & 0x03)
+ {
+ case 0x00:
+ channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod;
+ channel->pair->slots[1]->mod = &channel->pair->slots[0]->out;
+ channel->slots[0]->mod = &channel->pair->slots[1]->out;
+ channel->slots[1]->mod = &channel->slots[0]->out;
+ channel->out[0] = &channel->slots[1]->out;
+ channel->out[1] = &channel->chip->zeromod;
+ channel->out[2] = &channel->chip->zeromod;
+ channel->out[3] = &channel->chip->zeromod;
+ break;
+ case 0x01:
+ channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod;
+ channel->pair->slots[1]->mod = &channel->pair->slots[0]->out;
+ channel->slots[0]->mod = &channel->chip->zeromod;
+ channel->slots[1]->mod = &channel->slots[0]->out;
+ channel->out[0] = &channel->pair->slots[1]->out;
+ channel->out[1] = &channel->slots[1]->out;
+ channel->out[2] = &channel->chip->zeromod;
+ channel->out[3] = &channel->chip->zeromod;
+ break;
+ case 0x02:
+ channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod;
+ channel->pair->slots[1]->mod = &channel->chip->zeromod;
+ channel->slots[0]->mod = &channel->pair->slots[1]->out;
+ channel->slots[1]->mod = &channel->slots[0]->out;
+ channel->out[0] = &channel->pair->slots[0]->out;
+ channel->out[1] = &channel->slots[1]->out;
+ channel->out[2] = &channel->chip->zeromod;
+ channel->out[3] = &channel->chip->zeromod;
+ break;
+ case 0x03:
+ channel->pair->slots[0]->mod = &channel->pair->slots[0]->fbmod;
+ channel->pair->slots[1]->mod = &channel->chip->zeromod;
+ channel->slots[0]->mod = &channel->pair->slots[1]->out;
+ channel->slots[1]->mod = &channel->chip->zeromod;
+ channel->out[0] = &channel->pair->slots[0]->out;
+ channel->out[1] = &channel->slots[0]->out;
+ channel->out[2] = &channel->slots[1]->out;
+ channel->out[3] = &channel->chip->zeromod;
+ break;
+ }
+ }
+ else
+ {
+ switch (channel->alg & 0x01)
+ {
+ case 0x00:
+ channel->slots[0]->mod = &channel->slots[0]->fbmod;
+ channel->slots[1]->mod = &channel->slots[0]->out;
+ channel->out[0] = &channel->slots[1]->out;
+ channel->out[1] = &channel->chip->zeromod;
+ channel->out[2] = &channel->chip->zeromod;
+ channel->out[3] = &channel->chip->zeromod;
+ break;
+ case 0x01:
+ channel->slots[0]->mod = &channel->slots[0]->fbmod;
+ channel->slots[1]->mod = &channel->chip->zeromod;
+ channel->out[0] = &channel->slots[0]->out;
+ channel->out[1] = &channel->slots[1]->out;
+ channel->out[2] = &channel->chip->zeromod;
+ channel->out[3] = &channel->chip->zeromod;
+ break;
+ }
+ }
+}
+
+static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data)
+{
+ channel->fb = (data & 0x0e) >> 1;
+ channel->con = data & 0x01;
+ channel->alg = channel->con;
+ if (channel->chip->newm)
+ {
+ if (channel->chtype == ch_4op)
+ {
+ channel->pair->alg = 0x04 | (channel->con << 1) | (channel->pair->con);
+ channel->alg = 0x08;
+ OPL3_ChannelSetupAlg(channel->pair);
+ }
+ else if (channel->chtype == ch_4op2)
+ {
+ channel->alg = 0x04 | (channel->pair->con << 1) | (channel->con);
+ channel->pair->alg = 0x08;
+ OPL3_ChannelSetupAlg(channel);
+ }
+ else
+ {
+ OPL3_ChannelSetupAlg(channel);
+ }
+ }
+ else
+ {
+ OPL3_ChannelSetupAlg(channel);
+ }
+ if (channel->chip->newm)
+ {
+ channel->cha = ((data >> 4) & 0x01) ? ~0 : 0;
+ channel->chb = ((data >> 5) & 0x01) ? ~0 : 0;
+ }
+ else
+ {
+ channel->cha = channel->chb = (Bit16u)~0;
+ }
+}
+
+static void OPL3_ChannelKeyOn(opl3_channel *channel)
+{
+ if (channel->chip->newm)
+ {
+ if (channel->chtype == ch_4op)
+ {
+ OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm);
+ OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm);
+ OPL3_EnvelopeKeyOn(channel->pair->slots[0], egk_norm);
+ OPL3_EnvelopeKeyOn(channel->pair->slots[1], egk_norm);
+ }
+ else if (channel->chtype == ch_2op || channel->chtype == ch_drum)
+ {
+ OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm);
+ OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm);
+ }
+ }
+ else
+ {
+ OPL3_EnvelopeKeyOn(channel->slots[0], egk_norm);
+ OPL3_EnvelopeKeyOn(channel->slots[1], egk_norm);
+ }
+}
+
+static void OPL3_ChannelKeyOff(opl3_channel *channel)
+{
+ if (channel->chip->newm)
+ {
+ if (channel->chtype == ch_4op)
+ {
+ OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm);
+ OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm);
+ OPL3_EnvelopeKeyOff(channel->pair->slots[0], egk_norm);
+ OPL3_EnvelopeKeyOff(channel->pair->slots[1], egk_norm);
+ }
+ else if (channel->chtype == ch_2op || channel->chtype == ch_drum)
+ {
+ OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm);
+ OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm);
+ }
+ }
+ else
+ {
+ OPL3_EnvelopeKeyOff(channel->slots[0], egk_norm);
+ OPL3_EnvelopeKeyOff(channel->slots[1], egk_norm);
+ }
+}
+
+static void OPL3_ChannelSet4Op(opl3_chip *chip, Bit8u data)
+{
+ Bit8u bit;
+ Bit8u chnum;
+ for (bit = 0; bit < 6; bit++)
+ {
+ chnum = bit;
+ if (bit >= 3)
+ {
+ chnum += 9 - 3;
+ }
+ if ((data >> bit) & 0x01)
+ {
+ chip->channel[chnum].chtype = ch_4op;
+ chip->channel[chnum + 3].chtype = ch_4op2;
+ }
+ else
+ {
+ chip->channel[chnum].chtype = ch_2op;
+ chip->channel[chnum + 3].chtype = ch_2op;
+ }
+ }
+}
+
+static Bit16s OPL3_ClipSample(Bit32s sample)
+{
+ if (sample > 32767)
+ {
+ sample = 32767;
+ }
+ else if (sample < -32768)
+ {
+ sample = -32768;
+ }
+ return (Bit16s)sample;
+}
+
+void OPL3_Generate(opl3_chip *chip, Bit16s *buf)
+{
+ Bit8u ii;
+ Bit8u jj;
+ Bit16s accm;
+ Bit8u shift = 0;
+
+ buf[1] = OPL3_ClipSample(chip->mixbuff[1]);
+
+ for (ii = 0; ii < 15; ii++)
+ {
+ OPL3_SlotCalcFB(&chip->slot[ii]);
+ OPL3_EnvelopeCalc(&chip->slot[ii]);
+ OPL3_PhaseGenerate(&chip->slot[ii]);
+ OPL3_SlotGenerate(&chip->slot[ii]);
+ }
+
+ chip->mixbuff[0] = 0;
+ for (ii = 0; ii < 18; ii++)
+ {
+ accm = 0;
+ for (jj = 0; jj < 4; jj++)
+ {
+ accm += *chip->channel[ii].out[jj];
+ }
+ chip->mixbuff[0] += (Bit16s)(accm & chip->channel[ii].cha);
+ }
+
+ for (ii = 15; ii < 18; ii++)
+ {
+ OPL3_SlotCalcFB(&chip->slot[ii]);
+ OPL3_EnvelopeCalc(&chip->slot[ii]);
+ OPL3_PhaseGenerate(&chip->slot[ii]);
+ OPL3_SlotGenerate(&chip->slot[ii]);
+ }
+
+ buf[0] = OPL3_ClipSample(chip->mixbuff[0]);
+
+ for (ii = 18; ii < 33; ii++)
+ {
+ OPL3_SlotCalcFB(&chip->slot[ii]);
+ OPL3_EnvelopeCalc(&chip->slot[ii]);
+ OPL3_PhaseGenerate(&chip->slot[ii]);
+ OPL3_SlotGenerate(&chip->slot[ii]);
+ }
+
+ chip->mixbuff[1] = 0;
+ for (ii = 0; ii < 18; ii++)
+ {
+ accm = 0;
+ for (jj = 0; jj < 4; jj++)
+ {
+ accm += *chip->channel[ii].out[jj];
+ }
+ chip->mixbuff[1] += (Bit16s)(accm & chip->channel[ii].chb);
+ }
+
+ for (ii = 33; ii < 36; ii++)
+ {
+ OPL3_SlotCalcFB(&chip->slot[ii]);
+ OPL3_EnvelopeCalc(&chip->slot[ii]);
+ OPL3_PhaseGenerate(&chip->slot[ii]);
+ OPL3_SlotGenerate(&chip->slot[ii]);
+ }
+
+ if ((chip->timer & 0x3f) == 0x3f)
+ {
+ chip->tremolopos = (chip->tremolopos + 1) % 210;
+ }
+ if (chip->tremolopos < 105)
+ {
+ chip->tremolo = chip->tremolopos >> chip->tremoloshift;
+ }
+ else
+ {
+ chip->tremolo = (210 - chip->tremolopos) >> chip->tremoloshift;
+ }
+
+ if ((chip->timer & 0x3ff) == 0x3ff)
+ {
+ chip->vibpos = (chip->vibpos + 1) & 7;
+ }
+
+ chip->timer++;
+
+ chip->eg_add = 0;
+ if (chip->eg_timer)
+ {
+ while (shift < 36 && ((chip->eg_timer >> shift) & 1) == 0)
+ {
+ shift++;
+ }
+ if (shift > 12)
+ {
+ chip->eg_add = 0;
+ }
+ else
+ {
+ chip->eg_add = shift + 1;
+ }
+ }
+
+ if (chip->eg_timerrem || chip->eg_state)
+ {
+ if (chip->eg_timer == 0xfffffffffULL)
+ {
+ chip->eg_timer = 0;
+ chip->eg_timerrem = 1;
+ }
+ else
+ {
+ chip->eg_timer++;
+ chip->eg_timerrem = 0;
+ }
+ }
+
+ chip->eg_state ^= 1;
+
+ while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt)
+ {
+ if (!(chip->writebuf[chip->writebuf_cur].reg & 0x200))
+ {
+ break;
+ }
+ chip->writebuf[chip->writebuf_cur].reg &= 0x1ff;
+ OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg,
+ chip->writebuf[chip->writebuf_cur].data);
+ chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE;
+ }
+ chip->writebuf_samplecnt++;
+}
+
+void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf)
+{
+ while (chip->samplecnt >= chip->rateratio)
+ {
+ chip->oldsamples[0] = chip->samples[0];
+ chip->oldsamples[1] = chip->samples[1];
+ OPL3_Generate(chip, chip->samples);
+ chip->samplecnt -= chip->rateratio;
+ }
+ buf[0] = (Bit16s)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt)
+ + chip->samples[0] * chip->samplecnt) / chip->rateratio);
+ buf[1] = (Bit16s)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt)
+ + chip->samples[1] * chip->samplecnt) / chip->rateratio);
+ chip->samplecnt += 1 << RSM_FRAC;
+}
+
+void OPL3_Reset(opl3_chip *chip, Bit32u samplerate)
+{
+ Bit8u slotnum;
+ Bit8u channum;
+
+ memset(chip, 0, sizeof(opl3_chip));
+ for (slotnum = 0; slotnum < 36; slotnum++)
+ {
+ chip->slot[slotnum].chip = chip;
+ chip->slot[slotnum].mod = &chip->zeromod;
+ chip->slot[slotnum].eg_rout = 0x1ff;
+ chip->slot[slotnum].eg_out = 0x1ff;
+ chip->slot[slotnum].eg_gen = envelope_gen_num_release;
+ chip->slot[slotnum].trem = (Bit8u*)&chip->zeromod;
+ chip->slot[slotnum].slot_num = slotnum;
+ }
+ for (channum = 0; channum < 18; channum++)
+ {
+ chip->channel[channum].slots[0] = &chip->slot[ch_slot[channum]];
+ chip->channel[channum].slots[1] = &chip->slot[ch_slot[channum] + 3];
+ chip->slot[ch_slot[channum]].channel = &chip->channel[channum];
+ chip->slot[ch_slot[channum] + 3].channel = &chip->channel[channum];
+ if ((channum % 9) < 3)
+ {
+ chip->channel[channum].pair = &chip->channel[channum + 3];
+ }
+ else if ((channum % 9) < 6)
+ {
+ chip->channel[channum].pair = &chip->channel[channum - 3];
+ }
+ chip->channel[channum].chip = chip;
+ chip->channel[channum].out[0] = &chip->zeromod;
+ chip->channel[channum].out[1] = &chip->zeromod;
+ chip->channel[channum].out[2] = &chip->zeromod;
+ chip->channel[channum].out[3] = &chip->zeromod;
+ chip->channel[channum].chtype = ch_2op;
+ chip->channel[channum].cha = 0xffff;
+ chip->channel[channum].chb = 0xffff;
+ chip->channel[channum].ch_num = channum;
+ OPL3_ChannelSetupAlg(&chip->channel[channum]);
+ }
+ chip->noise = 1;
+ chip->rateratio = (samplerate << RSM_FRAC) / 49716;
+ chip->tremoloshift = 4;
+ chip->vibshift = 1;
+}
+
+void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v)
+{
+ Bit8u high = (reg >> 8) & 0x01;
+ Bit8u regm = reg & 0xff;
+ switch (regm & 0xf0)
+ {
+ case 0x00:
+ if (high)
+ {
+ switch (regm & 0x0f)
+ {
+ case 0x04:
+ OPL3_ChannelSet4Op(chip, v);
+ break;
+ case 0x05:
+ chip->newm = v & 0x01;
+ break;
+ }
+ }
+ else
+ {
+ switch (regm & 0x0f)
+ {
+ case 0x08:
+ chip->nts = (v >> 6) & 0x01;
+ break;
+ }
+ }
+ break;
+ case 0x20:
+ case 0x30:
+ if (ad_slot[regm & 0x1f] >= 0)
+ {
+ OPL3_SlotWrite20(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+ }
+ break;
+ case 0x40:
+ case 0x50:
+ if (ad_slot[regm & 0x1f] >= 0)
+ {
+ OPL3_SlotWrite40(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+ }
+ break;
+ case 0x60:
+ case 0x70:
+ if (ad_slot[regm & 0x1f] >= 0)
+ {
+ OPL3_SlotWrite60(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+ }
+ break;
+ case 0x80:
+ case 0x90:
+ if (ad_slot[regm & 0x1f] >= 0)
+ {
+ OPL3_SlotWrite80(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+ }
+ break;
+ case 0xe0:
+ case 0xf0:
+ if (ad_slot[regm & 0x1f] >= 0)
+ {
+ OPL3_SlotWriteE0(&chip->slot[18 * high + ad_slot[regm & 0x1f]], v);
+ }
+ break;
+ case 0xa0:
+ if ((regm & 0x0f) < 9)
+ {
+ OPL3_ChannelWriteA0(&chip->channel[9 * high + (regm & 0x0f)], v);
+ }
+ break;
+ case 0xb0:
+ if (regm == 0xbd && !high)
+ {
+ chip->tremoloshift = (((v >> 7) ^ 1) << 1) + 2;
+ chip->vibshift = ((v >> 6) & 0x01) ^ 1;
+ OPL3_ChannelUpdateRhythm(chip, v);
+ }
+ else if ((regm & 0x0f) < 9)
+ {
+ OPL3_ChannelWriteB0(&chip->channel[9 * high + (regm & 0x0f)], v);
+ if (v & 0x20)
+ {
+ OPL3_ChannelKeyOn(&chip->channel[9 * high + (regm & 0x0f)]);
+ }
+ else
+ {
+ OPL3_ChannelKeyOff(&chip->channel[9 * high + (regm & 0x0f)]);
+ }
+ }
+ break;
+ case 0xc0:
+ if ((regm & 0x0f) < 9)
+ {
+ OPL3_ChannelWriteC0(&chip->channel[9 * high + (regm & 0x0f)], v);
+ }
+ break;
+ }
+}
+
+void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v)
+{
+ Bit64u time1, time2;
+
+ if (chip->writebuf[chip->writebuf_last].reg & 0x200)
+ {
+ OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff,
+ chip->writebuf[chip->writebuf_last].data);
+
+ chip->writebuf_cur = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE;
+ chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time;
+ }
+
+ chip->writebuf[chip->writebuf_last].reg = reg | 0x200;
+ chip->writebuf[chip->writebuf_last].data = v;
+ time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY;
+ time2 = chip->writebuf_samplecnt;
+
+ if (time1 < time2)
+ {
+ time1 = time2;
+ }
+
+ chip->writebuf[chip->writebuf_last].time = time1;
+ chip->writebuf_lasttime = time1;
+ chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE;
+}
+
+void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples)
+{
+ Bit32u i;
+
+ for(i = 0; i < numsamples; i++)
+ {
+ OPL3_GenerateResampled(chip, sndptr);
+ sndptr += 2;
+ }
+}
+
+OPL::OPL(Config::OplType type) : _type(type), _rate(0) {
+}
+
+OPL::~OPL() {
+ stop();
+}
+
+bool OPL::init() {
+ _rate = g_system->getMixer()->getOutputRate();
+ OPL3_Reset(&chip, _rate);
+
+ if (_type == Config::kDualOpl2) {
+ OPL3_WriteReg(&chip, 0x105, 0x01);
+ }
+
+ return true;
+}
+
+void OPL::reset() {
+ OPL3_Reset(&chip, _rate);
+}
+
+void OPL::write(int port, int val) {
+ if (port & 1) {
+ switch (_type) {
+ case Config::kOpl2:
+ case Config::kOpl3:
+ OPL3_WriteRegBuffered(&chip, (Bit16u)address[0], (Bit8u)val);
+ break;
+ case Config::kDualOpl2:
+ // Not a 0x??8 port, then write to a specific port
+ if (!(port & 0x8)) {
+ byte index = (port & 2) >> 1;
+ dualWrite(index, address[index], val);
+ }
+ else {
+ //Write to both ports
+ dualWrite(0, address[0], val);
+ dualWrite(1, address[1], val);
+ }
+ break;
+ }
+ } else {
+ switch (_type) {
+ case Config::kOpl2:
+ address[0] = val & 0xff;
+ break;
+ case Config::kDualOpl2:
+ // Not a 0x?88 port, when write to a specific side
+ if (!(port & 0x8)) {
+ byte index = (port & 2) >> 1;
+ address[index] = val & 0xff;
+ }
+ else {
+ address[0] = val & 0xff;
+ address[1] = val & 0xff;
+ }
+ break;
+ case Config::kOpl3:
+ address[0] = (val & 0xff) | ((port << 7) & 0x100);
+ break;
+ }
+ }
+}
+
+
+void OPL::writeReg(int r, int v) {
+ OPL3_WriteRegBuffered(&chip, (Bit16u)r, (Bit8u)v);
+}
+
+void OPL::dualWrite(uint8 index, uint8 reg, uint8 val) {
+ // Make sure you don't use opl3 features
+ // Don't allow write to disable opl3
+ if (reg == 5)
+ return;
+
+ // Only allow 4 waveforms
+ if (reg >= 0xE0 && reg <= 0xE8)
+ val &= 3;
+
+ // Enabling panning
+ if (reg >= 0xC0 && reg <= 0xC8) {
+ val &= 15;
+ val |= index ? 0xA0 : 0x50;
+ }
+
+ uint32 fullReg = reg + (index ? 0x100 : 0);
+ OPL3_WriteRegBuffered(&chip, (Bit16u)fullReg, (Bit8u)val);
+}
+
+byte OPL::read(int port) {
+ return 0;
+}
+
+void OPL::generateSamples(int16*buffer, int length) {
+ OPL3_GenerateStream(&chip, (Bit16s*)buffer, (Bit16u)length / 2);
+}
+
+}
+}
+
+#endif // !DISABLE_NUKED_OPL
diff --git a/audio/softsynth/opl/nuked.h b/audio/softsynth/opl/nuked.h
new file mode 100644
index 0000000000..6cddbe8686
--- /dev/null
+++ b/audio/softsynth/opl/nuked.h
@@ -0,0 +1,188 @@
+//
+// Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT)
+//
+// 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.
+//
+//
+// Nuked OPL3 emulator.
+// Thanks:
+// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
+// Feedback and Rhythm part calculation information.
+// forums.submarine.org.uk(carbon14, opl3):
+// Tremolo and phase generator calculation information.
+// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
+// OPL2 ROMs.
+// siliconpr0n.org(John McMaster, digshadow):
+// YMF262 and VRC VII decaps and die shots.
+//
+// version: 1.8
+//
+
+#ifndef AUDIO_SOFTSYNTH_OPL_NUKED_H
+#define AUDIO_SOFTSYNTH_OPL_NUKED_H
+
+#include "common/scummsys.h"
+#include "audio/fmopl.h"
+
+#ifndef DISABLE_NUKED_OPL
+
+#define OPL_WRITEBUF_SIZE 1024
+#define OPL_WRITEBUF_DELAY 2
+
+namespace OPL {
+namespace NUKED {
+
+typedef uint Bitu;
+typedef int Bits;
+typedef uint64 Bit64u;
+typedef int64 Bit64s;
+typedef uint32 Bit32u;
+typedef int32 Bit32s;
+typedef uint16 Bit16u;
+typedef int16 Bit16s;
+typedef uint8 Bit8u;
+typedef int8 Bit8s;
+
+typedef struct _opl3_slot opl3_slot;
+typedef struct _opl3_channel opl3_channel;
+typedef struct _opl3_chip opl3_chip;
+
+struct _opl3_slot {
+ opl3_channel *channel;
+ opl3_chip *chip;
+ Bit16s out;
+ Bit16s fbmod;
+ Bit16s *mod;
+ Bit16s prout;
+ Bit16s eg_rout;
+ Bit16s eg_out;
+ Bit8u eg_inc;
+ Bit8u eg_gen;
+ Bit8u eg_rate;
+ Bit8u eg_ksl;
+ Bit8u *trem;
+ Bit8u reg_vib;
+ Bit8u reg_type;
+ Bit8u reg_ksr;
+ Bit8u reg_mult;
+ Bit8u reg_ksl;
+ Bit8u reg_tl;
+ Bit8u reg_ar;
+ Bit8u reg_dr;
+ Bit8u reg_sl;
+ Bit8u reg_rr;
+ Bit8u reg_wf;
+ Bit8u key;
+ Bit32u pg_reset;
+ Bit32u pg_phase;
+ Bit16u pg_phase_out;
+ Bit8u slot_num;
+};
+
+struct _opl3_channel {
+ opl3_slot *slots[2];
+ opl3_channel *pair;
+ opl3_chip *chip;
+ Bit16s *out[4];
+ Bit8u chtype;
+ Bit16u f_num;
+ Bit8u block;
+ Bit8u fb;
+ Bit8u con;
+ Bit8u alg;
+ Bit8u ksv;
+ Bit16u cha, chb;
+ Bit8u ch_num;
+};
+
+typedef struct _opl3_writebuf {
+ Bit64u time;
+ Bit16u reg;
+ Bit8u data;
+} opl3_writebuf;
+
+struct _opl3_chip {
+ opl3_channel channel[18];
+ opl3_slot slot[36];
+ Bit16u timer;
+ Bit64u eg_timer;
+ Bit8u eg_timerrem;
+ Bit8u eg_state;
+ Bit8u eg_add;
+ Bit8u newm;
+ Bit8u nts;
+ Bit8u rhy;
+ Bit8u vibpos;
+ Bit8u vibshift;
+ Bit8u tremolo;
+ Bit8u tremolopos;
+ Bit8u tremoloshift;
+ Bit32u noise;
+ Bit16s zeromod;
+ Bit32s mixbuff[2];
+ Bit8u rm_hh_bit2;
+ Bit8u rm_hh_bit3;
+ Bit8u rm_hh_bit7;
+ Bit8u rm_hh_bit8;
+ Bit8u rm_tc_bit3;
+ Bit8u rm_tc_bit5;
+ //OPL3L
+ Bit32s rateratio;
+ Bit32s samplecnt;
+ Bit16s oldsamples[2];
+ Bit16s samples[2];
+
+ Bit64u writebuf_samplecnt;
+ Bit32u writebuf_cur;
+ Bit32u writebuf_last;
+ Bit64u writebuf_lasttime;
+ opl3_writebuf writebuf[OPL_WRITEBUF_SIZE];
+};
+
+void OPL3_Generate(opl3_chip *chip, Bit16s *buf);
+void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf);
+void OPL3_Reset(opl3_chip *chip, Bit32u samplerate);
+void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v);
+void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v);
+void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples);
+
+class OPL : public ::OPL::EmulatedOPL {
+private:
+ Config::OplType _type;
+ uint _rate;
+ opl3_chip chip;
+ uint address[2];
+ void dualWrite(uint8 index, uint8 reg, uint8 val);
+
+public:
+ OPL(Config::OplType type);
+ ~OPL();
+
+ bool init();
+ void reset();
+
+ void write(int a, int v);
+ byte read(int a);
+
+ void writeReg(int r, int v);
+
+ bool isStereo() const { return true; }
+
+protected:
+ void generateSamples(int16 *buffer, int length);
+};
+
+}
+}
+
+#endif // !DISABLE_NUKED_OPL
+
+#endif
diff --git a/backends/audiocd/audiocd.h b/backends/audiocd/audiocd.h
index b3674f2570..1a31cd7b20 100644
--- a/backends/audiocd/audiocd.h
+++ b/backends/audiocd/audiocd.h
@@ -23,6 +23,7 @@
#ifndef BACKENDS_AUDIOCD_ABSTRACT_H
#define BACKENDS_AUDIOCD_ABSTRACT_H
+#include "audio/mixer.h"
#include "common/scummsys.h"
#include "common/noncopyable.h"
@@ -65,10 +66,12 @@ public:
* @param startFrame the frame at which playback should start (75 frames = 1 second).
* @param duration the number of frames to play.
* @param onlyEmulate determines if the track should be emulated only
+ * @param soundType What sound type to play as. By default, it's as music
* @note The @c onlyEmulate parameter is deprecated.
* @return @c true if the track started playing, @c false otherwise
*/
- virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false) = 0;
+ virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false,
+ Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType) = 0;
/**
* Get if audio is being played.
diff --git a/backends/audiocd/default/default-audiocd.cpp b/backends/audiocd/default/default-audiocd.cpp
index c2ce7cedcc..003060c9a6 100644
--- a/backends/audiocd/default/default-audiocd.cpp
+++ b/backends/audiocd/default/default-audiocd.cpp
@@ -54,7 +54,8 @@ void DefaultAudioCDManager::close() {
stop();
}
-bool DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate) {
+bool DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate,
+ Audio::Mixer::SoundType soundType) {
stop();
if (numLoops != 0 || startFrame != 0) {
@@ -84,7 +85,7 @@ bool DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int du
repetitions. Finally, -1 means infinitely many
*/
_emulating = true;
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle,
+ _mixer->playStream(soundType, &_handle,
Audio::makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops), -1, _cd.volume, _cd.balance);
return true;
}
diff --git a/backends/audiocd/default/default-audiocd.h b/backends/audiocd/default/default-audiocd.h
index e3fbb4b5a1..3c12560faa 100644
--- a/backends/audiocd/default/default-audiocd.h
+++ b/backends/audiocd/default/default-audiocd.h
@@ -40,7 +40,8 @@ public:
virtual bool open();
virtual void close();
- virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false);
+ virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false,
+ Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType);
virtual void stop();
virtual bool isPlaying() const;
virtual void setVolume(byte volume);
diff --git a/backends/audiocd/win32/win32-audiocd.cpp b/backends/audiocd/win32/win32-audiocd.cpp
index b3cde308b9..6eff1ef0b3 100644
--- a/backends/audiocd/win32/win32-audiocd.cpp
+++ b/backends/audiocd/win32/win32-audiocd.cpp
@@ -149,13 +149,14 @@ public:
Win32AudioCDManager();
~Win32AudioCDManager();
- bool open();
- void close();
- bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false);
+ virtual bool open();
+ virtual void close();
+ virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false,
+ Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType);
protected:
- bool openCD(int drive);
- bool openCD(const Common::String &drive);
+ virtual bool openCD(int drive);
+ virtual bool openCD(const Common::String &drive);
private:
bool loadTOC();
@@ -254,9 +255,10 @@ void Win32AudioCDManager::close() {
_tocEntries.clear();
}
-bool Win32AudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate) {
+bool Win32AudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate,
+ Audio::Mixer::SoundType soundType) {
// Prefer emulation
- if (DefaultAudioCDManager::play(track, numLoops, startFrame, duration, onlyEmulate))
+ if (DefaultAudioCDManager::play(track, numLoops, startFrame, duration, onlyEmulate, soundType))
return true;
// If we're set to only emulate, or have no CD drive, return here
@@ -289,7 +291,7 @@ bool Win32AudioCDManager::play(int track, int numLoops, int startFrame, int dura
_emulating = true;
_mixer->playStream(
- Audio::Mixer::kMusicSoundType,
+ soundType,
&_handle,
Audio::makeLoopingAudioStream(audioStream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops),
-1,
diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h
index df6ebd2f14..9a85fca52a 100644
--- a/backends/events/default/default-events.h
+++ b/backends/events/default/default-events.h
@@ -49,7 +49,7 @@ class DefaultEventManager : public Common::EventManager, Common::EventObserver {
Common::ArtificialEventSource _artificialEventSource;
Common::Queue<Common::Event> _eventQueue;
- bool notifyEvent(const Common::Event &ev) {
+ bool notifyEvent(const Common::Event &ev) override {
_eventQueue.push(ev);
return true;
}
@@ -76,17 +76,17 @@ public:
DefaultEventManager(Common::EventSource *boss);
~DefaultEventManager();
- virtual void init();
- virtual bool pollEvent(Common::Event &event);
- virtual void pushEvent(const Common::Event &event);
+ virtual void init() override;
+ virtual bool pollEvent(Common::Event &event) override;
+ virtual void pushEvent(const Common::Event &event) override;
virtual void purgeMouseEvents() override;
- virtual Common::Point getMousePos() const { return _mousePos; }
- virtual int getButtonState() const { return _buttonState; }
- virtual int getModifierState() const { return _modifierState; }
- virtual int shouldQuit() const { return _shouldQuit; }
- virtual int shouldRTL() const { return _shouldRTL; }
- virtual void resetRTL() { _shouldRTL = false; }
+ virtual Common::Point getMousePos() const override { return _mousePos; }
+ virtual int getButtonState() const override { return _buttonState; }
+ virtual int getModifierState() const override { return _modifierState; }
+ virtual int shouldQuit() const override { return _shouldQuit; }
+ virtual int shouldRTL() const override { return _shouldRTL; }
+ virtual void resetRTL() override { _shouldRTL = false; }
#ifdef FORCE_RTL
virtual void resetQuit() { _shouldQuit = false; }
#endif
diff --git a/backends/events/psp2sdl/psp2sdl-events.cpp b/backends/events/psp2sdl/psp2sdl-events.cpp
index 5b0b6074fb..a342fa836b 100644
--- a/backends/events/psp2sdl/psp2sdl-events.cpp
+++ b/backends/events/psp2sdl/psp2sdl-events.cpp
@@ -44,6 +44,17 @@ PSP2EventSource::PSP2EventSource() {
}
_multiFingerDragging[port] = DRAG_NONE;
}
+
+ for (int port = 0; port < SCE_TOUCH_PORT_MAX_NUM; port++) {
+ for (int i = 0; i < 2; i++) {
+ _simulatedClickStartTime[port][i] = 0;
+ }
+ }
+}
+
+bool PSP2EventSource::pollEvent(Common::Event &event) {
+ finishSimulatedMouseClicks();
+ return SdlEventSource::pollEvent(event);
}
void PSP2EventSource::preprocessEvents(SDL_Event *event) {
@@ -107,6 +118,8 @@ void PSP2EventSource::preprocessFingerDown(SDL_Event *event) {
if (_finger[port][i].id == -1) {
_finger[port][i].id = id;
_finger[port][i].timeLastDown = event->tfinger.timestamp;
+ _finger[port][i].lastDownX = event->tfinger.x;
+ _finger[port][i].lastDownY = event->tfinger.y;
_finger[port][i].lastX = x;
_finger[port][i].lastY = y;
break;
@@ -137,28 +150,31 @@ void PSP2EventSource::preprocessFingerUp(SDL_Event *event) {
if (!_multiFingerDragging[port]) {
if ((event->tfinger.timestamp - _finger[port][i].timeLastDown) <= MAX_TAP_TIME) {
// short (<MAX_TAP_TIME ms) tap is interpreted as right/left mouse click depending on # fingers already down
- if (numFingersDown == 2 || numFingersDown == 1) {
- Uint8 simulatedButton = 0;
- if (numFingersDown == 2) {
- simulatedButton = SDL_BUTTON_RIGHT;
- } else if (numFingersDown == 1) {
- simulatedButton = SDL_BUTTON_LEFT;
- if (port == 0 && !ConfMan.getBool("frontpanel_touchpad_mode")) {
- convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
+ // but only if the finger hasn't moved since it was pressed down by more than MAX_TAP_MOTION_DISTANCE pixels
+ float xrel = ((event->tfinger.x * 960.0) - (_finger[port][i].lastDownX * 960.0));
+ float yrel = ((event->tfinger.y * 544.0) - (_finger[port][i].lastDownY * 544.0));
+ float maxRSquared = (float) (MAX_TAP_MOTION_DISTANCE * MAX_TAP_MOTION_DISTANCE);
+ if ((xrel * xrel + yrel * yrel) < maxRSquared) {
+ if (numFingersDown == 2 || numFingersDown == 1) {
+ Uint8 simulatedButton = 0;
+ if (numFingersDown == 2) {
+ simulatedButton = SDL_BUTTON_RIGHT;
+ // need to raise the button later
+ _simulatedClickStartTime[port][1] = event->tfinger.timestamp;
+ } else if (numFingersDown == 1) {
+ simulatedButton = SDL_BUTTON_LEFT;
+ // need to raise the button later
+ _simulatedClickStartTime[port][0] = event->tfinger.timestamp;
+ if (port == 0 && !ConfMan.getBool("frontpanel_touchpad_mode")) {
+ convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
+ }
}
- }
- event->type = SDL_MOUSEBUTTONDOWN;
- event->button.button = simulatedButton;
- event->button.x = x;
- event->button.y = y;
-
- SDL_Event ev;
- ev.type = SDL_MOUSEBUTTONUP;
- ev.button.button = simulatedButton;
- ev.button.x = x;
- ev.button.y = y;
- SDL_PushEvent(&ev);
+ event->type = SDL_MOUSEBUTTONDOWN;
+ event->button.button = simulatedButton;
+ event->button.x = x;
+ event->button.y = y;
+ }
}
}
} else if (numFingersDown == 1) {
@@ -349,6 +365,9 @@ void PSP2EventSource::convertTouchXYToGameXY(float touchX, float touchY, int *ga
int screenH = _km.y_max;
int screenW = _km.x_max;
+ int windowH = g_system->getHeight();
+ int windowW = g_system->getWidth();
+
bool fullscreen = ConfMan.getBool("fullscreen");
bool aspectRatioCorrection = ConfMan.getBool("aspect_ratio");
@@ -359,13 +378,13 @@ void PSP2EventSource::convertTouchXYToGameXY(float touchX, float touchY, int *ga
float sx, sy;
float ratio = (float)screenW / (float)screenH;
- if (aspectRatioCorrection) {
+ if (aspectRatioCorrection && (windowH == 200 || windowH == 400)) {
ratio = 4.0 / 3.0;
}
if (fullscreen || screenH >= dispH) {
h = dispH;
- if (aspectRatioCorrection) {
+ if (aspectRatioCorrection && (windowH == 200 || windowH == 400)) {
ratio = ratio * 1.1;
}
w = h * ratio;
@@ -379,7 +398,7 @@ void PSP2EventSource::convertTouchXYToGameXY(float touchX, float touchY, int *ga
h = screenH;
w = screenW;
}
- if (aspectRatioCorrection) {
+ if (aspectRatioCorrection && (windowH == 200 || windowH == 400)) {
// stretch the height only if it fits, otherwise make the width smaller
if (((float)w * (1.0 / ratio)) <= (float)dispH) {
h = w * (1.0 / ratio);
@@ -413,4 +432,30 @@ void PSP2EventSource::convertTouchXYToGameXY(float touchX, float touchY, int *ga
*gameY = _km.y_max;
}
}
+
+void PSP2EventSource::finishSimulatedMouseClicks() {
+ for (int port = 0; port < SCE_TOUCH_PORT_MAX_NUM; port++) {
+ for (int i = 0; i < 2; i++) {
+ if (_simulatedClickStartTime[port][i] != 0) {
+ Uint32 currentTime = SDL_GetTicks();
+ if (currentTime - _simulatedClickStartTime[port][i] >= SIMULATED_CLICK_DURATION) {
+ int simulatedButton;
+ if (i == 0) {
+ simulatedButton = SDL_BUTTON_LEFT;
+ } else {
+ simulatedButton = SDL_BUTTON_RIGHT;
+ }
+ SDL_Event ev;
+ ev.type = SDL_MOUSEBUTTONUP;
+ ev.button.button = simulatedButton;
+ ev.button.x = _km.x / MULTIPLIER;
+ ev.button.y = _km.y / MULTIPLIER;
+ SDL_PushEvent(&ev);
+
+ _simulatedClickStartTime[port][i] = 0;
+ }
+ }
+ }
+ }
+}
#endif
diff --git a/backends/events/psp2sdl/psp2sdl-events.h b/backends/events/psp2sdl/psp2sdl-events.h
index 2f27208f61..1d5fdf9d50 100644
--- a/backends/events/psp2sdl/psp2sdl-events.h
+++ b/backends/events/psp2sdl/psp2sdl-events.h
@@ -32,6 +32,7 @@
class PSP2EventSource : public SdlEventSource {
public:
PSP2EventSource();
+ bool pollEvent(Common::Event &event) override;
protected:
void preprocessEvents(SDL_Event *event) override;
private:
@@ -39,6 +40,8 @@ private:
enum {
MAX_NUM_FINGERS = 3, // number of fingers to track per panel
MAX_TAP_TIME = 250, // taps longer than this will not result in mouse click events
+ MAX_TAP_MOTION_DISTANCE = 10, // max distance finger motion in Vita screen pixels to be considered a tap
+ SIMULATED_CLICK_DURATION = 50, // time in ms how long simulated mouse clicks should be
}; // track three fingers per panel
typedef struct {
@@ -46,6 +49,8 @@ private:
Uint32 timeLastDown;
int lastX; // last known screen coordinates
int lastY; // last known screen coordinates
+ float lastDownX; // SDL touch coordinates when last pressed down
+ float lastDownY; // SDL touch coordinates when last pressed down
} Touch;
Touch _finger[SCE_TOUCH_PORT_MAX_NUM][MAX_NUM_FINGERS]; // keep track of finger status
@@ -58,10 +63,13 @@ private:
DraggingType _multiFingerDragging[SCE_TOUCH_PORT_MAX_NUM]; // keep track whether we are currently drag-and-dropping
+ unsigned int _simulatedClickStartTime[SCE_TOUCH_PORT_MAX_NUM][2]; // initiation time of last simulated left or right click (zero if no click)
+
void preprocessFingerDown(SDL_Event *event);
void preprocessFingerUp(SDL_Event *event);
void preprocessFingerMotion(SDL_Event *event);
void convertTouchXYToGameXY(float touchX, float touchY, int *gameX, int *gameY);
+ void finishSimulatedMouseClicks(void);
};
#endif /* BACKEND_EVENTS_PSP2_H */
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index a3c0087b94..6c4774554c 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -29,6 +29,7 @@
#include "backends/graphics/graphics.h"
#include "common/config-manager.h"
#include "common/textconsole.h"
+#include "common/fs.h"
// FIXME move joystick defines out and replace with confile file options
// we should really allow users to map any key to a joystick button
@@ -43,8 +44,14 @@
#define JOY_BUT_PERIOD 1
#define JOY_BUT_SPACE 4
#define JOY_BUT_F5 5
+#ifdef ENABLE_VKEYBD
+#define JOY_BUT_VKEYBOARD 7
+#endif
+
#if SDL_VERSION_ATLEAST(2, 0, 0)
+#define GAMECONTROLLERDB_FILE "gamecontrollerdb.txt"
+
static uint32 convUTF8ToUTF32(const char *src) {
uint32 utf32 = 0;
@@ -63,6 +70,32 @@ static uint32 convUTF8ToUTF32(const char *src) {
return utf32;
}
+
+void SdlEventSource::loadGameControllerMappingFile() {
+ bool loaded = false;
+ if (ConfMan.hasKey("controller_map_db")) {
+ Common::FSNode file = Common::FSNode(ConfMan.get("controller_map_db"));
+ if (file.exists()) {
+ if (SDL_GameControllerAddMappingsFromFile(file.getPath().c_str()) < 0)
+ error("File %s not valid: %s", file.getPath().c_str(), SDL_GetError());
+ else {
+ loaded = true;
+ debug("Game controller DB file loaded: %s", file.getPath().c_str());
+ }
+ } else
+ warning("Game controller DB file not found: %s", file.getPath().c_str());
+ }
+ if (!loaded && ConfMan.hasKey("extrapath")) {
+ Common::FSNode dir = Common::FSNode(ConfMan.get("extrapath"));
+ Common::FSNode file = dir.getChild(GAMECONTROLLERDB_FILE);
+ if (file.exists()) {
+ if (SDL_GameControllerAddMappingsFromFile(file.getPath().c_str()) < 0)
+ error("File %s not valid: %s", file.getPath().c_str(), SDL_GetError());
+ else
+ debug("Game controller DB file loaded: %s", file.getPath().c_str());
+ }
+ }
+}
#endif
SdlEventSource::SdlEventSource()
@@ -85,6 +118,7 @@ SdlEventSource::SdlEventSource()
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1) {
error("Could not initialize SDL: %s", SDL_GetError());
}
+ loadGameControllerMappingFile();
#endif
openJoystick(joystick_num);
@@ -164,100 +198,103 @@ bool SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) {
return true;
}
-bool SdlEventSource::handleKbdMouse(Common::Event &event) {
- // returns true if an event is generated
- // Skip recording of these events
+void SdlEventSource::updateKbdMouse() {
uint32 curTime = g_system->getMillis(true);
+ if (curTime < _km.last_time + _km.delay_time) {
+ return;
+ }
- if (curTime >= _km.last_time + _km.delay_time) {
-
- int16 oldKmX = _km.x;
- int16 oldKmY = _km.y;
+ _km.last_time = curTime;
+ if (_km.x_down_count == 1) {
+ _km.x_down_time = curTime;
+ _km.x_down_count = 2;
+ }
+ if (_km.y_down_count == 1) {
+ _km.y_down_time = curTime;
+ _km.y_down_count = 2;
+ }
- _km.last_time = curTime;
- if (_km.x_down_count == 1) {
- _km.x_down_time = curTime;
- _km.x_down_count = 2;
+ if (_km.x_vel || _km.y_vel) {
+ if (_km.x_down_count) {
+ if (curTime > _km.x_down_time + 300) {
+ if (_km.x_vel > 0)
+ _km.x_vel += MULTIPLIER;
+ else
+ _km.x_vel -= MULTIPLIER;
+ } else if (curTime > _km.x_down_time + 200) {
+ if (_km.x_vel > 0)
+ _km.x_vel = 5 * MULTIPLIER;
+ else
+ _km.x_vel = -5 * MULTIPLIER;
+ }
}
- if (_km.y_down_count == 1) {
- _km.y_down_time = curTime;
- _km.y_down_count = 2;
+ if (_km.y_down_count) {
+ if (curTime > _km.y_down_time + 300) {
+ if (_km.y_vel > 0)
+ _km.y_vel += MULTIPLIER;
+ else
+ _km.y_vel -= MULTIPLIER;
+ } else if (curTime > _km.y_down_time + 200) {
+ if (_km.y_vel > 0)
+ _km.y_vel = 5 * MULTIPLIER;
+ else
+ _km.y_vel = -5 * MULTIPLIER;
+ }
}
- if (_km.x_vel || _km.y_vel) {
- if (_km.x_down_count) {
- if (curTime > _km.x_down_time + 300) {
- if (_km.x_vel > 0)
- _km.x_vel += MULTIPLIER;
- else
- _km.x_vel -= MULTIPLIER;
- } else if (curTime > _km.x_down_time + 200) {
- if (_km.x_vel > 0)
- _km.x_vel = 5 * MULTIPLIER;
- else
- _km.x_vel = -5 * MULTIPLIER;
- }
- }
- if (_km.y_down_count) {
- if (curTime > _km.y_down_time + 300) {
- if (_km.y_vel > 0)
- _km.y_vel += MULTIPLIER;
- else
- _km.y_vel -= MULTIPLIER;
- } else if (curTime > _km.y_down_time + 200) {
- if (_km.y_vel > 0)
- _km.y_vel = 5 * MULTIPLIER;
- else
- _km.y_vel = -5 * MULTIPLIER;
- }
- }
+ int16 speedFactor = computeJoystickMouseSpeedFactor();
+
+ // - The modifier key makes the mouse movement slower
+ // - The extra factor "delay/speedFactor" ensures velocities
+ // are independent of the kbdMouse update rate
+ // - all velocities were originally chosen
+ // at a delay of 25, so that is the reference used here
+ // - note: operator order is important to avoid overflow
+ if (_km.modifier) {
+ _km.x += ((_km.x_vel / 10) * ((int16)_km.delay_time)) / speedFactor;
+ _km.y += ((_km.y_vel / 10) * ((int16)_km.delay_time)) / speedFactor;
+ } else {
+ _km.x += (_km.x_vel * ((int16)_km.delay_time)) / speedFactor;
+ _km.y += (_km.y_vel * ((int16)_km.delay_time)) / speedFactor;
+ }
- int16 speedFactor = computeJoystickMouseSpeedFactor();
-
- // - The modifier key makes the mouse movement slower
- // - The extra factor "delay/speedFactor" ensures velocities
- // are independent of the kbdMouse update rate
- // - all velocities were originally chosen
- // at a delay of 25, so that is the reference used here
- // - note: operator order is important to avoid overflow
- if (_km.modifier) {
- _km.x += ((_km.x_vel / 10) * ((int16)_km.delay_time)) / speedFactor;
- _km.y += ((_km.y_vel / 10) * ((int16)_km.delay_time)) / speedFactor;
- } else {
- _km.x += (_km.x_vel * ((int16)_km.delay_time)) / speedFactor;
- _km.y += (_km.y_vel * ((int16)_km.delay_time)) / speedFactor;
- }
+ if (_km.x < 0) {
+ _km.x = 0;
+ _km.x_vel = -1 * MULTIPLIER;
+ _km.x_down_count = 1;
+ } else if (_km.x > _km.x_max * MULTIPLIER) {
+ _km.x = _km.x_max * MULTIPLIER;
+ _km.x_vel = 1 * MULTIPLIER;
+ _km.x_down_count = 1;
+ }
- if (_km.x < 0) {
- _km.x = 0;
- _km.x_vel = -1 * MULTIPLIER;
- _km.x_down_count = 1;
- } else if (_km.x > _km.x_max * MULTIPLIER) {
- _km.x = _km.x_max * MULTIPLIER;
- _km.x_vel = 1 * MULTIPLIER;
- _km.x_down_count = 1;
- }
+ if (_km.y < 0) {
+ _km.y = 0;
+ _km.y_vel = -1 * MULTIPLIER;
+ _km.y_down_count = 1;
+ } else if (_km.y > _km.y_max * MULTIPLIER) {
+ _km.y = _km.y_max * MULTIPLIER;
+ _km.y_vel = 1 * MULTIPLIER;
+ _km.y_down_count = 1;
+ }
+ }
+}
- if (_km.y < 0) {
- _km.y = 0;
- _km.y_vel = -1 * MULTIPLIER;
- _km.y_down_count = 1;
- } else if (_km.y > _km.y_max * MULTIPLIER) {
- _km.y = _km.y_max * MULTIPLIER;
- _km.y_vel = 1 * MULTIPLIER;
- _km.y_down_count = 1;
- }
+bool SdlEventSource::handleKbdMouse(Common::Event &event) {
+ int16 oldKmX = _km.x;
+ int16 oldKmY = _km.y;
- if (_graphicsManager) {
- _graphicsManager->getWindow()->warpMouseInWindow((Uint16)(_km.x / MULTIPLIER), (Uint16)(_km.y / MULTIPLIER));
- }
+ updateKbdMouse();
- if (_km.x != oldKmX || _km.y != oldKmY) {
- event.type = Common::EVENT_MOUSEMOVE;
- return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
- }
+ if (_km.x != oldKmX || _km.y != oldKmY) {
+ if (_graphicsManager) {
+ _graphicsManager->getWindow()->warpMouseInWindow((Uint16)(_km.x / MULTIPLIER), (Uint16)(_km.y / MULTIPLIER));
}
+
+ event.type = Common::EVENT_MOUSEMOVE;
+ return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
}
+
return false;
}
@@ -873,6 +910,11 @@ bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
event.kbd.keycode = Common::KEYCODE_F5;
event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0);
break;
+#ifdef ENABLE_VKEYBD
+ case JOY_BUT_VKEYBOARD: // Toggles virtual keyboard
+ event.type = Common::EVENT_VIRTUAL_KEYBOARD;
+ break;
+#endif
}
return true;
}
@@ -904,6 +946,11 @@ bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
event.kbd.keycode = Common::KEYCODE_F5;
event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0);
break;
+#ifdef ENABLE_VKEYBD
+ case JOY_BUT_VKEYBOARD: // Toggles virtual keyboard
+ // Handled in key down
+ break;
+#endif
}
return true;
}
diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h
index c4c2ab406d..b26d4cc6bd 100644
--- a/backends/events/sdl/sdl-events.h
+++ b/backends/events/sdl/sdl-events.h
@@ -94,6 +94,11 @@ protected:
SdlGraphicsManager *_graphicsManager;
/**
+ * Search for a game controller db file and load it.
+ */
+ void loadGameControllerMappingFile();
+
+ /**
* Open the SDL joystick with the specified index
*
* After this function completes successfully, SDL sends events for the device.
@@ -135,6 +140,7 @@ protected:
virtual bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event);
virtual bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event);
virtual bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event);
+ virtual void updateKbdMouse();
virtual bool handleKbdMouse(Common::Event &event);
#if SDL_VERSION_ATLEAST(2, 0, 0)
diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp
index 09ba3a1c83..134193a65b 100644
--- a/backends/fs/amigaos4/amigaos4-fs.cpp
+++ b/backends/fs/amigaos4/amigaos4-fs.cpp
@@ -266,7 +266,7 @@ bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
if (context) {
struct ExamineData * pExd = NULL; // NB: No need to free the value after usage, everything will be dealt with by the DirContext release
- AmigaOSFilesystemNode *entry ;
+ AmigaOSFilesystemNode *entry;
while ( (pExd = IDOS->ExamineDir(context)) ) {
if ( (EXD_IS_FILE(pExd) && ( Common::FSNode::kListFilesOnly == mode ))
|| (EXD_IS_DIRECTORY(pExd) && ( Common::FSNode::kListDirectoriesOnly == mode ))
diff --git a/backends/fs/ds/ds-fs-factory.cpp b/backends/fs/ds/ds-fs-factory.cpp
index 98c522f1d6..3ec4a40bd8 100644
--- a/backends/fs/ds/ds-fs-factory.cpp
+++ b/backends/fs/ds/ds-fs-factory.cpp
@@ -24,9 +24,9 @@
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
#if defined(__DS__)
+#include "dsmain.h" //for the isGBAMPAvailable() function
#include "backends/fs/ds/ds-fs-factory.h"
#include "backends/fs/ds/ds-fs.h"
-#include "dsmain.h" //for the isGBAMPAvailable() function
namespace Common {
DECLARE_SINGLETON(DSFilesystemFactory);
diff --git a/backends/fs/ds/ds-fs.cpp b/backends/fs/ds/ds-fs.cpp
index 035178dbb4..1df54a983d 100644
--- a/backends/fs/ds/ds-fs.cpp
+++ b/backends/fs/ds/ds-fs.cpp
@@ -23,12 +23,12 @@
// Disable symbol overrides for FILE as that is used in FLAC headers
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
+#include "dsmain.h"
#include "common/str.h"
#include "common/util.h"
//#include <NDS/ARM9/console.h> //basic print funcionality
#include "backends/fs/ds/ds-fs.h"
#include "backends/fs/stdiostream.h"
-#include "dsmain.h"
#include "fat/gba_nds_fat.h"
#include "common/bufferedstream.h"
diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp
index 3f90fc1a19..01c2751857 100644
--- a/backends/fs/posix/posix-fs.cpp
+++ b/backends/fs/posix/posix-fs.cpp
@@ -62,6 +62,16 @@ void POSIXFilesystemNode::setFlags() {
POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p) {
assert(p.size() > 0);
+#ifdef PSP2
+ if (p == "/") {
+ _isDirectory = true;
+ _isValid = false;
+ _path = p;
+ _displayName = p;
+ return;
+ }
+#endif
+
// Expand "~/" to the value of the HOME env variable
if (p.hasPrefix("~/")) {
const char *home = getenv("HOME");
@@ -152,6 +162,15 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
return true;
}
#endif
+#ifdef PSP2
+ if (_path == "/") {
+ POSIXFilesystemNode *entry1 = new POSIXFilesystemNode("ux0:");
+ myList.push_back(entry1);
+ POSIXFilesystemNode *entry2 = new POSIXFilesystemNode("uma0:");
+ myList.push_back(entry2);
+ return true;
+ }
+#endif
DIR *dirp = opendir(_path.c_str());
struct dirent *dp;
@@ -230,6 +249,10 @@ AbstractFSNode *POSIXFilesystemNode::getParent() const {
// This is a root directory of a drive
return makeNode("/"); // return a virtual root for a list of drives
#endif
+#ifdef PSP2
+ if (_path.hasSuffix(":"))
+ return makeNode("/");
+#endif
const char *start = _path.c_str();
const char *end = start + _path.size();
diff --git a/backends/fs/psp2/psp2-fs-factory.cpp b/backends/fs/psp2/psp2-fs-factory.cpp
index 68d91122b8..946eb10649 100644
--- a/backends/fs/psp2/psp2-fs-factory.cpp
+++ b/backends/fs/psp2/psp2-fs-factory.cpp
@@ -32,7 +32,7 @@
#include "backends/fs/psp2/psp2-fs-factory.h"
AbstractFSNode *PSP2FilesystemFactory::makeRootFileNode() const {
- return new POSIXFilesystemNode("ux0:");
+ return new POSIXFilesystemNode("/");
}
AbstractFSNode *PSP2FilesystemFactory::makeCurrentDirectoryFileNode() const {
diff --git a/backends/graphics/psp2sdl/psp2sdl-graphics.cpp b/backends/graphics/psp2sdl/psp2sdl-graphics.cpp
index 1947f8f751..5e6afc2a57 100644
--- a/backends/graphics/psp2sdl/psp2sdl-graphics.cpp
+++ b/backends/graphics/psp2sdl/psp2sdl-graphics.cpp
@@ -238,7 +238,7 @@ void PSP2SdlGraphicsManager::setAspectRatioCorrection(bool enable) {
SDL_Surface *PSP2SdlGraphicsManager::SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) {
SDL_Surface *screen = SurfaceSdlGraphicsManager::SDL_SetVideoMode(width, height, bpp, flags);
-
+
if (screen != nullptr) {
vita2d_set_vblank_wait(true);
_vitatex_hwscreen = vita2d_create_empty_texture_format(width, height, SCE_GXM_TEXTURE_FORMAT_R5G6B5);
@@ -264,7 +264,7 @@ void PSP2SdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrects,
float sx, sy;
float ratio = (float)screenW / (float)screenH;
- if (aspectRatioCorrection) {
+ if (aspectRatioCorrection && (screenH == 200 || screenH == 400)) {
ratio = 4.0 / 3.0;
}
@@ -281,7 +281,7 @@ void PSP2SdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrects,
h = screenH;
w = screenW;
}
- if (aspectRatioCorrection) {
+ if (aspectRatioCorrection && (screenH == 200 || screenH == 400)) {
// stretch the height only if it fits, otherwise make the width smaller
if (((float)w * (1.0 / ratio)) <= (float)dispH) {
h = w * (1.0 / ratio);
diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h
index 5f89d2d233..8a0bddf5be 100644
--- a/backends/graphics/windowed.h
+++ b/backends/graphics/windowed.h
@@ -201,7 +201,7 @@ protected:
* @param x The new X position of the mouse in virtual screen coordinates.
* @param y The new Y position of the mouse in virtual screen coordinates.
*/
- void warpMouse(const int x, const int y) {
+ void warpMouse(const int x, const int y) override {
// Check active coordinate instead of window coordinate to avoid warping
// the mouse if it is still within the same virtual pixel
const Common::Point virtualCursor = convertWindowToVirtual(_cursorX, _cursorY);
diff --git a/backends/midi/dmedia.cpp b/backends/midi/dmedia.cpp
index eac2d34b58..475172c81f 100644
--- a/backends/midi/dmedia.cpp
+++ b/backends/midi/dmedia.cpp
@@ -166,7 +166,8 @@ void MidiDriver_DMEDIA::send(uint32 b) {
if (mdSend(_midiPort, &event, 1) != 1) {
warning("failed sending MIDI event (dump follows...)");
warning("MIDI Event (len=%u):", event.msglen);
- for (int i = 0; i < event.msglen; i++) warning("%02x ", (int)event.msg[i]);
+ for (int i = 0; i < event.msglen; i++)
+ warning("%02x ", (int)event.msg[i]);
}
}
@@ -186,7 +187,8 @@ void MidiDriver_DMEDIA::sysEx (const byte *msg, uint16 length) {
if (mdSend(_midiPort, &event, 1) != 1) {
fprintf(stderr, "failed sending MIDI SYSEX event (dump follows...)\n");
- for (int i = 0; i < event.msglen; i++) warning("%02x ", (int)event.msg[i]);
+ for (int i = 0; i < event.msglen; i++)
+ warning("%02x ", (int)event.msg[i]);
}
}
diff --git a/backends/modular-backend.h b/backends/modular-backend.h
index 982dbbfb02..fa34f2921f 100644
--- a/backends/modular-backend.h
+++ b/backends/modular-backend.h
@@ -52,9 +52,9 @@ public:
/** @name Features */
//@{
- virtual bool hasFeature(Feature f);
- virtual void setFeatureState(Feature f, bool enable);
- virtual bool getFeatureState(Feature f);
+ virtual bool hasFeature(Feature f) override;
+ virtual void setFeatureState(Feature f, bool enable) override;
+ virtual bool getFeatureState(Feature f) override;
//@}
@@ -62,76 +62,76 @@ public:
//@{
virtual GraphicsManager *getGraphicsManager();
- virtual const GraphicsMode *getSupportedGraphicsModes() const;
- virtual int getDefaultGraphicsMode() const;
- virtual bool setGraphicsMode(int mode);
- virtual int getGraphicsMode() const;
- virtual const GraphicsMode *getSupportedShaders() const;
- virtual int getShader() const;
- virtual bool setShader(int id);
- virtual void resetGraphicsScale();
+ virtual const GraphicsMode *getSupportedGraphicsModes() const override;
+ virtual int getDefaultGraphicsMode() const override;
+ virtual bool setGraphicsMode(int mode) override;
+ virtual int getGraphicsMode() const override;
+ virtual const GraphicsMode *getSupportedShaders() const override;
+ virtual int getShader() const override;
+ virtual bool setShader(int id) override;
+ virtual void resetGraphicsScale() override;
#ifdef USE_RGB_COLOR
- virtual Graphics::PixelFormat getScreenFormat() const;
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
+ virtual Graphics::PixelFormat getScreenFormat() const override;
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
#endif
- virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL);
+ virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) override;
virtual void initSizeHint(const Graphics::ModeList &modes) override;
- virtual int getScreenChangeID() const;
-
- virtual void beginGFXTransaction();
- virtual OSystem::TransactionError endGFXTransaction();
-
- virtual int16 getHeight();
- virtual int16 getWidth();
- virtual PaletteManager *getPaletteManager();
- virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h);
- virtual Graphics::Surface *lockScreen();
- virtual void unlockScreen();
- virtual void fillScreen(uint32 col);
- virtual void updateScreen();
- virtual void setShakePos(int shakeOffset);
- virtual void setFocusRectangle(const Common::Rect& rect);
- virtual void clearFocusRectangle();
-
- virtual void showOverlay();
- virtual void hideOverlay();
- virtual Graphics::PixelFormat getOverlayFormat() const;
- virtual void clearOverlay();
- virtual void grabOverlay(void *buf, int pitch);
- virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h);
- virtual int16 getOverlayHeight();
- virtual int16 getOverlayWidth();
-
- virtual bool showMouse(bool visible);
- virtual void warpMouse(int x, int y);
- virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL);
- virtual void setCursorPalette(const byte *colors, uint start, uint num);
+ virtual int getScreenChangeID() const override;
+
+ virtual void beginGFXTransaction() override;
+ virtual OSystem::TransactionError endGFXTransaction() override;
+
+ virtual int16 getHeight() override;
+ virtual int16 getWidth() override;
+ virtual PaletteManager *getPaletteManager() override;
+ virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
+ virtual Graphics::Surface *lockScreen() override;
+ virtual void unlockScreen() override;
+ virtual void fillScreen(uint32 col) override;
+ virtual void updateScreen() override;
+ virtual void setShakePos(int shakeOffset) override;
+ virtual void setFocusRectangle(const Common::Rect& rect) override;
+ virtual void clearFocusRectangle() override;
+
+ virtual void showOverlay() override;
+ virtual void hideOverlay() override;
+ virtual Graphics::PixelFormat getOverlayFormat() const override;
+ virtual void clearOverlay() override;
+ virtual void grabOverlay(void *buf, int pitch) override;
+ virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
+ virtual int16 getOverlayHeight() override;
+ virtual int16 getOverlayWidth() override;
+
+ virtual bool showMouse(bool visible) override;
+ virtual void warpMouse(int x, int y) override;
+ virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) override;
+ virtual void setCursorPalette(const byte *colors, uint start, uint num) override;
//@}
/** @name Mutex handling */
//@{
- virtual MutexRef createMutex();
- virtual void lockMutex(MutexRef mutex);
- virtual void unlockMutex(MutexRef mutex);
- virtual void deleteMutex(MutexRef mutex);
+ virtual MutexRef createMutex() override;
+ virtual void lockMutex(MutexRef mutex) override;
+ virtual void unlockMutex(MutexRef mutex) override;
+ virtual void deleteMutex(MutexRef mutex) override;
//@}
/** @name Sound */
//@{
- virtual Audio::Mixer *getMixer();
+ virtual Audio::Mixer *getMixer() override;
//@}
/** @name Miscellaneous */
//@{
- virtual void quit();
- virtual void displayMessageOnOSD(const char *msg);
- virtual void displayActivityIconOnOSD(const Graphics::Surface *icon);
+ virtual void quit() override;
+ virtual void displayMessageOnOSD(const char *msg) override;
+ virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
//@}
diff --git a/backends/platform/androidsdl/androidsdl-sdl.cpp b/backends/platform/androidsdl/androidsdl-sdl.cpp
index 697acca4d6..2ed644ecb2 100644
--- a/backends/platform/androidsdl/androidsdl-sdl.cpp
+++ b/backends/platform/androidsdl/androidsdl-sdl.cpp
@@ -44,18 +44,18 @@ void OSystem_ANDROIDSDL::initBackend() {
if (!ConfMan.hasKey("gfx_mode"))
ConfMan.set("gfx_mode", "2x");
-
+
if (!ConfMan.hasKey("swap_menu_and_back_buttons"))
ConfMan.setBool("swap_menu_and_back_buttons", true);
else
swapMenuAndBackButtons(ConfMan.getBool("swap_menu_and_back_buttons"));
-
+
if (!ConfMan.hasKey("touchpad_mouse_mode")) {
const bool enable = SDL_ANDROID_GetMouseEmulationMode();
ConfMan.setBool("touchpad_mouse_mode", enable);
} else
touchpadMode(ConfMan.getBool("touchpad_mouse_mode"));
-
+
if (!ConfMan.hasKey("onscreen_control")) {
const bool enable = SDL_ANDROID_GetScreenKeyboardShown();
ConfMan.setBool("onscreen_control", enable);
@@ -115,7 +115,7 @@ void OSystem_ANDROIDSDL::setFeatureState(Feature f, bool enable) {
swapMenuAndBackButtons(enable);
break;
}
-
+
OSystem_POSIX::setFeatureState(f, enable);
}
diff --git a/backends/platform/dc/dc-fs.cpp b/backends/platform/dc/dc-fs.cpp
index 1cc7b56710..a4d2675080 100644
--- a/backends/platform/dc/dc-fs.cpp
+++ b/backends/platform/dc/dc-fs.cpp
@@ -167,5 +167,5 @@ AbstractFSNode *OSystem_Dreamcast::makeCurrentDirectoryFileNode() const {
AbstractFSNode *OSystem_Dreamcast::makeFileNodePath(const Common::String &path) const {
AbstractFSNode *node = RoninCDFileNode::makeFileNodePath(path);
- return (node? node : new RoninCDNonexistingNode(path));
+ return (node ? node : new RoninCDNonexistingNode(path));
}
diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp
index 6717ca494b..914d683334 100644
--- a/backends/platform/dc/selector.cpp
+++ b/backends/platform/dc/selector.cpp
@@ -155,11 +155,7 @@ static Game the_game;
static bool isIcon(const Common::FSNode &entry)
{
- int l = entry.getDisplayName().size();
- if (l>4 && !strcasecmp(entry.getDisplayName().c_str()+l-4, ".ICO"))
- return true;
- else
- return false;
+ return entry.getDisplayName().hasSuffixIgnoreCase(".ICO");
}
static bool loadIcon(Game &game, Dir *dirs, int num_dirs)
@@ -203,7 +199,7 @@ static bool uniqueGame(const char *base, const char *dir,
this is a workaround for the detector bug in toon... */
sameOrSubdir(dir, games->dir) &&
/*!strcmp(dir, games->dir) &&*/
- !stricmp(base, games->filename_base) &&
+ !scumm_stricmp(base, games->filename_base) &&
lang == games->language &&
plf == games->platform)
return false;
@@ -275,21 +271,22 @@ static int findGames(Game *games, int max, bool use_ini)
}
if (!use_ini) {
- GameList candidates = EngineMan.detectGames(files);
+ DetectionResults detectionResults = EngineMan.detectGames(files);
+ DetectedGames candidates = detectionResults.listRecognizedGames();
- for (GameList::const_iterator ge = candidates.begin();
+ for (DetectedGames::const_iterator ge = candidates.begin();
ge != candidates.end(); ++ge)
if (curr_game < max) {
- strcpy(games[curr_game].filename_base, ge->gameid().c_str());
+ strcpy(games[curr_game].filename_base, ge->gameId.c_str());
strcpy(games[curr_game].dir, dirs[curr_dir-1].name);
- games[curr_game].language = ge->language();
- games[curr_game].platform = ge->platform();
+ games[curr_game].language = ge->language;
+ games[curr_game].platform = ge->platform;
if (uniqueGame(games[curr_game].filename_base,
games[curr_game].dir,
games[curr_game].language,
games[curr_game].platform, games, curr_game)) {
- strcpy(games[curr_game].text, ge->description().c_str());
+ strcpy(games[curr_game].text, ge->description.c_str());
#if 0
printf("Registered game <%s> (l:%d p:%d) in <%s> <%s> because of <%s> <*>\n",
games[curr_game].text,
diff --git a/backends/platform/ds/arm7/source/main.cpp b/backends/platform/ds/arm7/source/main.cpp
index c4a22b8f68..617a1edc87 100644
--- a/backends/platform/ds/arm7/source/main.cpp
+++ b/backends/platform/ds/arm7/source/main.cpp
@@ -26,7 +26,7 @@
// -- modified by Darkain and others
//////////////////////////////////////////////////////////////////////
-//#define USE_LIBCARTRESET
+// #define USE_LIBCARTRESET
#include <nds.h>
@@ -37,7 +37,7 @@
#include <system.h>
#include <stdlib.h>
#include <string.h>
-#include <registers_alt.h> // Needed for SOUND_CR
+#include <registers_alt.h> // Needed for SOUND_CR
#include <NDS/scummvm_ipc.h>
//////////////////////////////////////////////////////////////////////
#ifdef USE_DEBUGGER
@@ -54,8 +54,8 @@
#define SCREEN_HEIGHT 192
s32 TOUCH_WIDTH = TOUCH_CAL_X2 - TOUCH_CAL_X1;
s32 TOUCH_HEIGHT = TOUCH_CAL_Y2 - TOUCH_CAL_Y1;
-s32 TOUCH_OFFSET_X = ( ((SCREEN_WIDTH -60) * TOUCH_CAL_X1) / TOUCH_WIDTH ) - 28;
-s32 TOUCH_OFFSET_Y = ( ((SCREEN_HEIGHT-60) * TOUCH_CAL_Y1) / TOUCH_HEIGHT ) - 28;
+s32 TOUCH_OFFSET_X = ( ((SCREEN_WIDTH - 60) * TOUCH_CAL_X1) / TOUCH_WIDTH ) - 28;
+s32 TOUCH_OFFSET_Y = ( ((SCREEN_HEIGHT - 60) * TOUCH_CAL_Y1) / TOUCH_HEIGHT ) - 28;
vu8 *soundData;
@@ -71,163 +71,157 @@ int temp;
int adpcmBufferNum = 0;
// those are pixel positions of the two points you click when calibrating
-#define TOUCH_CNTRL_X1 (*(vu8 *)0x027FFCDC)
-#define TOUCH_CNTRL_Y1 (*(vu8 *)0x027FFCDD)
-#define TOUCH_CNTRL_X2 (*(vu8 *)0x027FFCE2)
-#define TOUCH_CNTRL_Y2 (*(vu8 *)0x027FFCE3)
-
-
-//////////////////////////////////////////////////////////////////////
+#define TOUCH_CNTRL_X1 (*(vu8 *)0x027FFCDC)
+#define TOUCH_CNTRL_Y1 (*(vu8 *)0x027FFCDD)
+#define TOUCH_CNTRL_X2 (*(vu8 *)0x027FFCE2)
+#define TOUCH_CNTRL_Y2 (*(vu8 *)0x027FFCE3)
/*
-void startSound(int sampleRate, const void *data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) {
- SCHANNEL_TIMER(channel) = SOUND_FREQ(sampleRate);
- SCHANNEL_SOURCE(channel) = (uint32)data;
- SCHANNEL_LENGTH(channel) = bytes;
- SCHANNEL_CR(channel) = SOUND_ENABLE | SOUND_ONE_SHOT | SOUND_VOL(vol) | SOUND_PAN(pan) | (format==1?SOUND_8BIT:SOUND_16BIT);
+void startSound(int sampleRate, const void *data, uint32 bytes, u8 channel = 0, u8 vol = 0x7F, u8 pan = 63, u8 format = 0) {
+ SCHANNEL_TIMER(channel) = SOUND_FREQ(sampleRate);
+ SCHANNEL_SOURCE(channel) = (uint32)data;
+ SCHANNEL_LENGTH(channel) = bytes;
+ SCHANNEL_CR(channel) = SOUND_ENABLE | SOUND_ONE_SHOT | SOUND_VOL(vol) | SOUND_PAN(pan) | (format==1?SOUND_8BIT:SOUND_16BIT);
}
-
s8 getFreeSoundChannel() {
- for (int i=0; i<16; i++) {
- if ( (SCHANNEL_CR(i) & SOUND_ENABLE) == 0 ) return i;
- }
- return -1;
+ for (int i = 0; i < 16; i++) {
+ if ( (SCHANNEL_CR(i) & SOUND_ENABLE) == 0 )
+ return i;
+ }
+ return -1;
}
*/
-
s8 getFreeSoundChannel() {
-// return 0;
- for (int i=0; i<16; i++) {
- if ( (SCHANNEL_CR(i) & SCHANNEL_ENABLE) == 0 ) return i;
- }
- return -1;
+ // return 0;
+ for (int i = 0; i < 16; i++) {
+ if ( (SCHANNEL_CR(i) & SCHANNEL_ENABLE) == 0 )
+ return i;
+ }
+ return -1;
}
-void startSound(int sampleRate, const void *data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) {
-// REG_IME = IME_DISABLE;
+void startSound(int sampleRate, const void *data, uint32 bytes, u8 channel = 0, u8 vol = 0x7F, u8 pan = 63, u8 format = 0) {
+ // REG_IME = IME_DISABLE;
- channel = getFreeSoundChannel();
-/* if (format == 2) {
- channel = 1;
- } else {
- channel = 0;
- }*/
+ channel = getFreeSoundChannel();
+ /*
+ if (format == 2) {
+ channel = 1;
+ } else {
+ channel = 0;
+ }
+ */
- if (channel > 1) channel = 1;
+ if (channel > 1)
+ channel = 1;
- bytes &= ~7; // Multiple of 4 bytes!
-// bytes += 4;
+ bytes &= ~7; // Multiple of 4 bytes!
+ // bytes += 4;
- SCHANNEL_CR(channel) = 0;
- SCHANNEL_TIMER(channel) = SOUND_FREQ(sampleRate);
- SCHANNEL_SOURCE(channel) = ((uint32) (data));
- SCHANNEL_LENGTH(channel) = ((bytes & 0x7FFFFFFF) >> 2);
- SCHANNEL_REPEAT_POINT(channel) = 0;
+ SCHANNEL_CR(channel) = 0;
+ SCHANNEL_TIMER(channel) = SOUND_FREQ(sampleRate);
+ SCHANNEL_SOURCE(channel) = (uint32)data;
+ SCHANNEL_LENGTH(channel) = (bytes & 0x7FFFFFFF) >> 2;
+ SCHANNEL_REPEAT_POINT(channel) = 0;
- SCHANNEL_CR(channel + 2) = 0;
- SCHANNEL_TIMER(channel + 2) = SOUND_FREQ(sampleRate);
- SCHANNEL_SOURCE(channel + 2) = ((uint32) (data));
- SCHANNEL_LENGTH(channel + 2) = ((bytes & 0x7FFFFFFF) >> 2);
- SCHANNEL_REPEAT_POINT(channel + 2) = 0;
+ SCHANNEL_CR(channel + 2) = 0;
+ SCHANNEL_TIMER(channel + 2) = SOUND_FREQ(sampleRate);
+ SCHANNEL_SOURCE(channel + 2) = (uint32)data;
+ SCHANNEL_LENGTH(channel + 2) = (bytes & 0x7FFFFFFF) >> 2;
+ SCHANNEL_REPEAT_POINT(channel + 2) = 0;
- uint32 flags = SCHANNEL_ENABLE | SOUND_VOL(vol) | SOUND_PAN(pan);
+ uint32 flags = SCHANNEL_ENABLE | SOUND_VOL(vol) | SOUND_PAN(pan);
- switch (format) {
+ switch (format) {
case 1: {
flags |= SOUND_FORMAT_8BIT;
- flags |= SOUND_REPEAT;// | (1 << 15);
+ flags |= SOUND_REPEAT; // | (1 << 15);
break;
}
case 0: {
flags |= SOUND_FORMAT_16BIT;
- flags |= SOUND_REPEAT;// | (1 << 15);
+ flags |= SOUND_REPEAT; // | (1 << 15);
break;
}
case 2: {
flags |= SOUND_FORMAT_ADPCM;
- flags |= SOUND_ONE_SHOT;// | (1 << 15);
+ flags |= SOUND_ONE_SHOT; // | (1 << 15);
- SCHANNEL_SOURCE(channel) = (unsigned int) IPC->adpcm.buffer[0];
- //bytes += 32;
- SCHANNEL_LENGTH(channel) = (((bytes + 4) & 0x7FFFFFFF) >> 2);
+ SCHANNEL_SOURCE(channel) = (unsigned int)IPC->adpcm.buffer[0];
+ // bytes += 32;
+ SCHANNEL_LENGTH(channel) = ((bytes + 4) & 0x7FFFFFFF) >> 2;
SCHANNEL_CR(channel + 1) = 0;
- SCHANNEL_SOURCE(channel + 1) = (unsigned int) IPC->adpcm.buffer[0];
- SCHANNEL_LENGTH(channel + 1) = (((bytes + 4) & 0x7FFFFFFF) >> 2);
- SCHANNEL_TIMER(channel + 1) = SOUND_FREQ(sampleRate);
+ SCHANNEL_SOURCE(channel + 1) = (unsigned int)IPC->adpcm.buffer[0];
+ SCHANNEL_LENGTH(channel + 1) = ((bytes + 4) & 0x7FFFFFFF) >> 2;
+ SCHANNEL_TIMER(channel + 1) = SOUND_FREQ(sampleRate);
SCHANNEL_REPEAT_POINT(channel + 1) = 0;
SCHANNEL_CR(channel + 1) = flags;
temp = bytes;
adpcmBufferNum = 0;
break;
}
- }
-
-
-// if (bytes & 0x80000000) {
-// flags |= SOUND_REPEAT;
-// } else {
-// }
-
-
-
+ }
- soundData = (vu8 *) data;
+ /*
+ if (bytes & 0x80000000) {
+ flags |= SOUND_REPEAT;
+ } else {
+ }
+ */
- SCHANNEL_CR(channel) = flags;
- SCHANNEL_CR(channel + 2) = flags;
+ soundData = (vu8 *)data;
+ SCHANNEL_CR(channel) = flags;
+ SCHANNEL_CR(channel + 2) = flags;
+ if (channel == 0) {
+ for (volatile int i = 0; i < 16384 * 2; i++) {
+ // Delay loop - this makes everything stay in sync!
+ }
- if (channel == 0) {
- for (volatile int i = 0; i < 16384 * 2; i++) {
- // Delay loop - this makes everything stay in sync!
- }
+ TIMER0_CR = 0;
+ TIMER0_DATA = SOUND_FREQ(sampleRate) * 2;
+ TIMER0_CR = TIMER_ENABLE | TIMER_DIV_1;
- TIMER0_CR = 0;
- TIMER0_DATA = SOUND_FREQ(sampleRate) * 2;
- TIMER0_CR = TIMER_ENABLE | TIMER_DIV_1;
+ TIMER1_CR = 0;
+ TIMER1_DATA = 65536 - ((bytes & 0x7FFFFFFF) >> 3); // Trigger four times during the length of the buffer
+ TIMER1_CR = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_CASCADE;
- TIMER1_CR = 0;
- TIMER1_DATA = 65536 - ((bytes & 0x7FFFFFFF) >> 3); // Trigger four times during the length of the buffer
- TIMER1_CR = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_CASCADE;
+ playingSection = 0;
+ } else {
+ for (volatile int i = 0; i < 16384 * 2; i++) {
+ // Delay loop - this makes everything stay in sync!
+ }
- playingSection = 0;
- } else {
- for (volatile int i = 0; i < 16384 * 2; i++) {
- // Delay loop - this makes everything stay in sync!
- }
+ TIMER2_CR = 0;
+ TIMER2_DATA = SOUND_FREQ(sampleRate) * 2;
+ TIMER2_CR = TIMER_ENABLE | TIMER_DIV_1;
- TIMER2_CR = 0;
- TIMER2_DATA = SOUND_FREQ(sampleRate) * 2;
- TIMER2_CR = TIMER_ENABLE | TIMER_DIV_1;
+ TIMER3_CR = 0;
+ TIMER3_DATA = 65536 - ((bytes & 0x7FFFFFFF) >> 3); // Trigger four times during the length of the buffer
+ TIMER3_CR = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_CASCADE;
- TIMER3_CR = 0;
- TIMER3_DATA = 65536 - ((bytes & 0x7FFFFFFF) >> 3); // Trigger four times during the length of the buffer
- TIMER3_CR = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_CASCADE;
+ for (int r = 0; r < 4; r++) {
+ // IPC->streamFillNeeded[r] = true;
+ }
- for (int r = 0; r < 4; r++) {
-// IPC->streamFillNeeded[r] = true;
+ IPC->streamPlayingSection = 0;
}
- IPC->streamPlayingSection = 0;
- }
-
-
-
-// IPC->fillSoundFirstHalf = true;
-// IPC->fillSoundSecondHalf = true;
-// soundFirstHalf = true;
+ // IPC->fillSoundFirstHalf = true;
+ // IPC->fillSoundSecondHalf = true;
+ // soundFirstHalf = true;
-// REG_IME = IME_ENABLE;
+ // REG_IME = IME_ENABLE;
}
void stopSound(int chan) {
- SCHANNEL_CR(chan) = 0;
+ SCHANNEL_CR(chan) = 0;
}
void DummyHandler() {
@@ -235,146 +229,132 @@ void DummyHandler() {
}
void powerManagerWrite(uint32 command, u32 data, bool enable) {
-
- uint16 result;
- SerialWaitBusy();
-
- // Write the command and wait for it to complete
- REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz | (1 << 11);
- REG_SPIDATA = command | 0x80;
- SerialWaitBusy();
-
- // Write the second command and clock in the data
- REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz;
- REG_SPIDATA = 0;
- SerialWaitBusy();
-
- result = REG_SPIDATA & 0xFF;
-
-
-
- // Write the command and wait for it to complete
- REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz | (1 << 11);
- REG_SPIDATA = command;
- SerialWaitBusy();
-
- // Write the second command and clock in the data
- REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz;
- REG_SPIDATA = enable? (result | data): (result & ~data);
- SerialWaitBusy();
+ uint16 result;
+ SerialWaitBusy();
+
+ // Write the command and wait for it to complete
+ REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz | (1 << 11);
+ REG_SPIDATA = command | 0x80;
+ SerialWaitBusy();
+
+ // Write the second command and clock in the data
+ REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz;
+ REG_SPIDATA = 0;
+ SerialWaitBusy();
+
+ result = REG_SPIDATA & 0xFF;
+
+ // Write the command and wait for it to complete
+ REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz | (1 << 11);
+ REG_SPIDATA = command;
+ SerialWaitBusy();
+
+ // Write the second command and clock in the data
+ REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz;
+ REG_SPIDATA = enable ? (result | data) : (result & ~data);
+ SerialWaitBusy();
}
/*
void performSleep() {
+ powerManagerWrite(0, 0x30, true);
- powerManagerWrite(0, 0x30, true);
-
- // Here, I set up a dummy interrupt handler, then trigger all interrupts.
- // These are just aknowledged by the handler without doing anything else.
- // Why? Because without it the sleep mode will only happen once, and then
- // never again. I got the idea from reading the MoonShell source.
- IME = 0;
- u32 irq = (u32) IRQ_HANDLER;
- IRQ_HANDLER = DummyHandler;
- IF = ~0;
- IME = 1;
+ // Here, I set up a dummy interrupt handler, then trigger all interrupts.
+ // These are just aknowledged by the handler without doing anything else.
+ // Why? Because without it the sleep mode will only happen once, and then
+ // never again. I got the idea from reading the MoonShell source.
+ IME = 0;
+ u32 irq = (u32)IRQ_HANDLER;
+ IRQ_HANDLER = DummyHandler;
+ IF = ~0;
+ IME = 1;
+ // Now save which interrupts are enabled, then set only the screens unfolding
+ // interrupt to be enabled, so that the first interrupt that happens is the
+ // one I want.
+ int saveInts = IE;
- // Now save which interrupts are enabled, then set only the screens unfolding
- // interrupt to be enabled, so that the first interrupt that happens is the
- // one I want.
- int saveInts = IE;
+ IE = IRQ_TIMER0; // Screens unfolding interrupt
+ // Now call the sleep function in the bios
+ bool b;
+ do {
+ TIMER0_CR = 0;
+ TIMER0_DATA = TIMER_FREQ(20);
+ TIMER0_CR = TIMER_ENABLE | TIMER_DIV_64;
+ swiDelay(100);
- IE = IRQ_TIMER0; // Screens unfolding interrupt
+ swiSleep();
- // Now call the sleep function in the bios
- bool b;
- do {
- TIMER0_CR = 0;
- TIMER0_DATA = TIMER_FREQ(20);
- TIMER0_CR = TIMER_ENABLE | TIMER_DIV_64;
+ swiDelay(100);
- swiDelay(100);
-
- swiSleep();
-
- swiDelay(100);
-
- powerManagerWrite(0, 0x30, b = !b);
- } while (!(TIMER0_CR & TIMER_ENABLE));
-
- TIMER0_CR = 0;
-
- // We're back from sleep, now restore the interrupt state and IRQ handler
- IRQ_HANDLER = (void (*)()) irq;
- IE = saveInts;
- IF = ~0;
- IME = 1;
+ powerManagerWrite(0, 0x30, b = !b);
+ } while (!(TIMER0_CR & TIMER_ENABLE));
+ TIMER0_CR = 0;
+ // We're back from sleep, now restore the interrupt state and IRQ handler
+ IRQ_HANDLER = (void (*)())irq;
+ IE = saveInts;
+ IF = ~0;
+ IME = 1;
- powerManagerWrite(0, 0x30, false);
+ powerManagerWrite(0, 0x30, false);
}
-
*/
-void performSleep() {
- powerManagerWrite(0, 0x30, true);
- IPC->performArm9SleepMode = true; // Tell ARM9 to sleep
+void performSleep() {
+ powerManagerWrite(0, 0x30, true);
-// u32 irq = (u32) IRQ_HANDLER;
-// IRQ_HANDLER = DummyHandler;
-// POWER_CR &= ~POWER_SOUND;
+ IPC->performArm9SleepMode = true; // Tell ARM9 to sleep
-// int saveInts = REG_IE;
-// REG_IE = (1 << 22) | IRQ_VBLANK; // Lid open
-// *((u32 *) (0x0380FFF8)) = *((u32 *) (0x0380FFF8)) | (REG_IE & REG_IF);
-// VBLANK_INTR_WAIT_FLAGS = IRQ_VBLANK;
+ // u32 irq = (u32)IRQ_HANDLER;
+ // IRQ_HANDLER = DummyHandler;
+ // POWER_CR &= ~POWER_SOUND;
+ // int saveInts = REG_IE;
+ // REG_IE = (1 << 22) | IRQ_VBLANK; // Lid open
+ // *((u32 *)(0x0380FFF8)) = *((u32 *)(0x0380FFF8)) | (REG_IE & REG_IF);
+ // VBLANK_INTR_WAIT_FLAGS = IRQ_VBLANK;
- int r = 0;
- while ((REG_KEYXY & (1 << 7))) { // Wait for lid to open
- swiDelay(1000000);
- r++;
- }
+ int r = 0;
+ while ((REG_KEYXY & (1 << 7))) { // Wait for lid to open
+ swiDelay(1000000);
+ r++;
+ }
-// IRQ_HANDLER = (void (*)()) irq;
- IPC->performArm9SleepMode = false; // Tell ARM9 to wake up
-// REG_IE = saveInts;
+ // IRQ_HANDLER = (void (*)())irq;
+ IPC->performArm9SleepMode = false; // Tell ARM9 to wake up
+ // REG_IE = saveInts;
-// POWER_CR |= POWER_SOUND;
+ // POWER_CR |= POWER_SOUND;
- powerManagerWrite(0, 0x30, false);
+ powerManagerWrite(0, 0x30, false);
}
void powerOff() {
powerManagerWrite(0, 0x40, true);
}
-//////////////////////////////////////////////////////////////////////
-
-
void InterruptTimer1() {
-
IPC->fillNeeded[playingSection] = true;
soundFilled[playingSection] = false;
if (playingSection == 3) {
-// IME = IME_DISABLED;
+ // IME = IME_DISABLED;
- // while (SCHANNEL_CR(0) & SCHANNEL_ENABLE) {
- // }
-// SCHANNEL_CR(0) &= ~SCHANNEL_ENABLE;
+ // while (SCHANNEL_CR(0) & SCHANNEL_ENABLE) {
+ // }
+ // SCHANNEL_CR(0) &= ~SCHANNEL_ENABLE;
-// SCHANNEL_CR(0) |= SCHANNEL_ENABLE;
-// TIMER1_CR = 0;
-// TIMER1_CR = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_CASCADE;
+ // SCHANNEL_CR(0) |= SCHANNEL_ENABLE;
+ // TIMER1_CR = 0;
+ // TIMER1_CR = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_CASCADE;
playingSection = 0;
-// IME = IME_ENABLED;
+ // IME = IME_ENABLED;
} else {
playingSection++;
}
@@ -395,8 +375,8 @@ void InterruptTimer1() {
}
void InterruptTimer3() {
- while (IPC->adpcm.semaphore); // Wait for buffer to become free if needed
- IPC->adpcm.semaphore = true; // Lock the buffer structure to prevent clashing with the ARM7
+ while (IPC->adpcm.semaphore); // Wait for buffer to become free if needed
+ IPC->adpcm.semaphore = true; // Lock the buffer structure to prevent clashing with the ARM7
IPC->streamFillNeeded[IPC->streamPlayingSection] = true;
@@ -406,153 +386,145 @@ void InterruptTimer3() {
IPC->streamPlayingSection++;
}
-
IPC->adpcm.semaphore = false;
}
-// IPC->performArm9SleepMode = false;
-
- // precalculate some values
-// static int16 TOUCH_WIDTH = TOUCH_CAL_X2 - TOUCH_CAL_X1;
-// static int16 TOUCH_HEIGHT = TOUCH_CAL_Y2 - TOUCH_CAL_Y1;
-// static int16 CNTRL_WIDTH = TOUCH_CNTRL_X2 - (TOUCH_CNTRL_X1 - 8);
-// static int16 CNTRL_HEIGHT = TOUCH_CNTRL_Y2 - (TOUCH_CNTRL_Y1 - 8);
-
-
+// IPC->performArm9SleepMode = false;
+// precalculate some values
+// static int16 TOUCH_WIDTH = TOUCH_CAL_X2 - TOUCH_CAL_X1;
+// static int16 TOUCH_HEIGHT = TOUCH_CAL_Y2 - TOUCH_CAL_Y1;
+// static int16 CNTRL_WIDTH = TOUCH_CNTRL_X2 - (TOUCH_CNTRL_X1 - 8);
+// static int16 CNTRL_HEIGHT = TOUCH_CNTRL_Y2 - (TOUCH_CNTRL_Y1 - 8);
void InterruptVBlank() {
- uint16 but=0, x=0, y=0, xpx=0, ypx=0, z1=0, z2=0, batt=0, aux=0;
- int t1=0, t2=0;
- uint32 temp=0;
- uint8 ct[sizeof(IPC->curtime)];
+ uint16 but = 0, x = 0, y = 0, xpx = 0, ypx = 0, z1 = 0, z2 = 0, batt = 0, aux = 0;
+ int t1 = 0, t2 = 0;
+ uint32 temp = 0;
+ uint8 ct[sizeof(IPC->curtime)];
static int heartbeat = 0;
- // Update the heartbeat
- heartbeat++;
-
- // Read the X/Y buttons and the /PENIRQ line
- but = REG_KEYXY;
- if (!(but & 0x40)) {
- // Read the touch screen
- touchPosition p;
- touchReadXY(&p);
-
-// x = touchRead(TSC_MEASURE_X);
- // y = touchRead(TSC_MEASURE_Y);
+ // Update the heartbeat
+ heartbeat++;
- x = p.rawx;
- y = p.rawy;
+ // Read the X/Y buttons and the /PENIRQ line
+ but = REG_KEYXY;
+ if (!(but & 0x40)) {
+ // Read the touch screen
+ touchPosition p;
+ touchReadXY(&p);
- xpx = p.px;
- ypx = p.py;
+ // x = touchRead(TSC_MEASURE_X);
+ // y = touchRead(TSC_MEASURE_Y);
-// xpx = ( ((SCREEN_WIDTH -60) * x) / TOUCH_WIDTH ) - TOUCH_OFFSET_X;
- // ypx = ( ((SCREEN_HEIGHT-60) * y) / TOUCH_HEIGHT ) - TOUCH_OFFSET_Y;
+ x = p.rawx;
+ y = p.rawy;
-// xpx = (IPC->touchX - (int16) TOUCH_CAL_X1) * CNTRL_WIDTH / TOUCH_WIDTH + (int16) (TOUCH_CNTRL_X1 - 8);
- // ypx = (IPC->touchY - (int16) TOUCH_CAL_Y1) * CNTRL_HEIGHT / TOUCH_HEIGHT + (int16) (TOUCH_CNTRL_Y1 - 8);
+ // xpx = p.px;
+ // ypx = p.py;
+ xpx = ( ((SCREEN_WIDTH - 60) * x) / TOUCH_WIDTH ) - TOUCH_OFFSET_X;
+ ypx = ( ((SCREEN_HEIGHT - 60) * y) / TOUCH_HEIGHT ) - TOUCH_OFFSET_Y;
- z1 = touchRead(TSC_MEASURE_Z1);
- z2 = touchRead(TSC_MEASURE_Z2);
- }
+ // xpx = (IPC->touchX - (int16) TOUCH_CAL_X1) * CNTRL_WIDTH / TOUCH_WIDTH + (int16) (TOUCH_CNTRL_X1 - 8);
+ // ypx = (IPC->touchY - (int16) TOUCH_CAL_Y1) * CNTRL_HEIGHT / TOUCH_HEIGHT + (int16) (TOUCH_CNTRL_Y1 - 8);
- if (but & (1 << 7)) { // Check if screen is folded
- needSleep = true;
+ z1 = touchRead(TSC_MEASURE_Z1);
+ z2 = touchRead(TSC_MEASURE_Z2);
}
+ // Check if screen is folded
+ if (but & (1 << 7)) {
+ needSleep = true;
+ }
- batt = touchRead(TSC_MEASURE_BATTERY);
- aux = touchRead(TSC_MEASURE_AUX);
-
- // Read the time
- rtcGetTime((uint8 *)ct);
- BCDToInteger((uint8 *)&(ct[1]), 7);
-
- // Read the temperature
- temp = touchReadTemperature(&t1, &t2);
-
-
- // Update the IPC struct
- IPC->heartbeat = heartbeat;
- IPC->buttons = but;
- IPC->touchX = x;
- IPC->touchY = y;
- IPC->touchXpx = xpx;
- IPC->touchYpx = ypx;
- IPC->touchZ1 = z1;
- IPC->touchZ2 = z2;
- IPC->battery = batt;
- IPC->aux = aux;
-
- for (u32 i=0; i<sizeof(ct); i++) {
- IPC->curtime[i] = ct[i];
- }
-
- IPC->temperature = temp;
- IPC->tdiode1 = t1;
- IPC->tdiode2 = t2;
-
-
+ batt = touchRead(TSC_MEASURE_BATTERY);
+ aux = touchRead(TSC_MEASURE_AUX);
+
+ // Read the time
+ rtcGetTime((uint8 *)ct);
+ BCDToInteger((uint8 *)&(ct[1]), 7);
+
+ // Read the temperature
+ temp = touchReadTemperature(&t1, &t2);
+
+ // Update the IPC struct
+ IPC->heartbeat = heartbeat;
+ IPC->buttons = but;
+ IPC->touchX = x;
+ IPC->touchY = y;
+ IPC->touchXpx = xpx;
+ IPC->touchYpx = ypx;
+ IPC->touchZ1 = z1;
+ IPC->touchZ2 = z2;
+ IPC->battery = batt;
+ IPC->aux = aux;
+
+ for (u32 i = 0; i < sizeof(ct); i++) {
+ IPC->curtime[i] = ct[i];
+ }
- //sound code :)
- TransferSound *snd = IPC->soundData;
- IPC->soundData = 0;
- if (snd) {
- for (int i=0; i<snd->count; i++) {
- s8 chan = getFreeSoundChannel();
- if (snd->data[i].rate > 0) {
- if (chan >= 0) {
- startSound(snd->data[i].rate, snd->data[i].data, snd->data[i].len, chan, snd->data[i].vol, snd->data[i].pan, snd->data[i].format);
+ IPC->temperature = temp;
+ IPC->tdiode1 = t1;
+ IPC->tdiode2 = t2;
+
+ // sound code :)
+ TransferSound *snd = IPC->soundData;
+ IPC->soundData = 0;
+ if (snd) {
+ for (int i = 0; i < snd->count; i++) {
+ s8 chan = getFreeSoundChannel();
+ if (snd->data[i].rate > 0) {
+ if (chan >= 0) {
+ startSound(snd->data[i].rate, snd->data[i].data, snd->data[i].len, chan, snd->data[i].vol, snd->data[i].pan, snd->data[i].format);
+ }
+ } else {
+ stopSound(-snd->data[i].rate);
}
- } else {
- stopSound(-snd->data[i].rate);
}
- }
- }
-
+ }
- #ifdef USE_DEBUGGER
- Wifi_Update(); // update wireless in vblank
- #endif
+#ifdef USE_DEBUGGER
+ Wifi_Update(); // update wireless in vblank
+#endif
}
-//////////////////////////////////////////////////////////////////////
-
-
#ifdef USE_DEBUGGER
-
// callback to allow wifi library to notify arm9
void arm7_synctoarm9() { // send fifo message
- REG_IPC_FIFO_TX = 0x87654321;
+ REG_IPC_FIFO_TX = 0x87654321;
}
+
// interrupt handler to allow incoming notifications from arm9
void arm7_fifo() { // check incoming fifo messages
- u32 msg = REG_IPC_FIFO_RX;
- if (msg==0x87654321) Wifi_Sync();
+ u32 msg = REG_IPC_FIFO_RX;
+ if (msg == 0x87654321)
+ Wifi_Sync();
}
-
-
void initDebugger() {
-
// set up the wifi irq
irqSet(IRQ_WIFI, Wifi_Interrupt); // set up wifi interrupt
irqEnable(IRQ_WIFI);
- //get them talking together
+ // get them talking together
// sync with arm9 and init wifi
u32 fifo_temp;
while (1) { // wait for magic number
- while (REG_IPC_FIFO_CR&IPC_FIFO_RECV_EMPTY) swiWaitForVBlank();
- fifo_temp=REG_IPC_FIFO_RX;
- if (fifo_temp==0x12345678) break;
+ while (REG_IPC_FIFO_CR & IPC_FIFO_RECV_EMPTY)
+ swiWaitForVBlank();
+
+ fifo_temp = REG_IPC_FIFO_RX;
+
+ if (fifo_temp == 0x12345678)
+ break;
}
- while (REG_IPC_FIFO_CR&IPC_FIFO_RECV_EMPTY) swiWaitForVBlank();
- fifo_temp=REG_IPC_FIFO_RX; // give next value to wifi_init
+ while (REG_IPC_FIFO_CR & IPC_FIFO_RECV_EMPTY)
+ swiWaitForVBlank();
+
+ fifo_temp = REG_IPC_FIFO_RX; // give next value to wifi_init
Wifi_Init(fifo_temp);
irqSet(IRQ_FIFO_NOT_EMPTY,arm7_fifo); // set up fifo irq
@@ -561,7 +533,6 @@ void initDebugger() {
Wifi_SetSyncHandler(arm7_synctoarm9); // allow wifi lib to notify arm9
// arm7 wifi init complete
-
}
#endif
@@ -571,82 +542,75 @@ void reboot() {
}
#endif
-
int main(int argc, char ** argv) {
-
-
#ifdef USE_DEBUGGER
- REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR;
+ REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR;
#endif
- // Reset the clock if needed
- rtcReset();
-
- //enable sound
-// powerOn(POWER_SOUND);
- SOUND_CR = SOUND_ENABLE | SOUND_VOL(0x7F);
- IPC->soundData = 0;
- IPC->reset = false;
-
-
- //fifoInit();
+ // Reset the clock if needed
+ rtcReset();
- for (int r = 0; r < 8; r++) {
- IPC->adpcm.arm7Buffer[r] = (u8 *) malloc(512);
- }
+ // enable sound
+ // powerOn(POWER_SOUND);
+ SOUND_CR = SOUND_ENABLE | SOUND_VOL(0x7F);
+ IPC->soundData = 0;
+ IPC->reset = false;
- for (int r = 0; r < 4; r++) {
- soundFilled[r] = false;
- }
+ // fifoInit();
+ for (int r = 0; r < 8; r++) {
+ IPC->adpcm.arm7Buffer[r] = (u8 *)malloc(512);
+ }
- // Set up the interrupt handler
+ for (int r = 0; r < 4; r++) {
+ soundFilled[r] = false;
+ }
- irqInit();
+ // Set up the interrupt handler
- irqSet(IRQ_VBLANK, InterruptVBlank);
- irqEnable(IRQ_VBLANK);
+ irqInit();
- irqSet(IRQ_TIMER1, InterruptTimer1);
- irqEnable(IRQ_TIMER1);
+ irqSet(IRQ_VBLANK, InterruptVBlank);
+ irqEnable(IRQ_VBLANK);
- irqSet(IRQ_TIMER3, InterruptTimer3);
- irqEnable(IRQ_TIMER3);
+ irqSet(IRQ_TIMER1, InterruptTimer1);
+ irqEnable(IRQ_TIMER1);
-/* REG_IME = 0;
- IRQ_HANDLER = &InterruptHandler;
- REG_IE = IRQ_VBLANK | IRQ_TIMER1 | IRQ_TIMER3;
- REG_IF = ~0;
- DISP_SR = DISP_VBLANK_IRQ;
- REG_IME = 1;
- */
+ irqSet(IRQ_TIMER3, InterruptTimer3);
+ irqEnable(IRQ_TIMER3);
+ /*
+ REG_IME = 0;
+ IRQ_HANDLER = &InterruptHandler;
+ REG_IE = IRQ_VBLANK | IRQ_TIMER1 | IRQ_TIMER3;
+ REG_IF = ~0;
+ DISP_SR = DISP_VBLANK_IRQ;
+ REG_IME = 1;
+ */
#ifdef USE_DEBUGGER
- initDebugger();
+ initDebugger();
#endif
- // Keep the ARM7 out of main RAM
- while ((1)) {
- if (needSleep) {
- performSleep();
- needSleep = false;
- }
+ // Keep the ARM7 out of main RAM
+ while ((1)) {
+ if (needSleep) {
+ performSleep();
+ needSleep = false;
+ }
#ifdef USE_LIBCARTRESET
- if (passmeloopQuery()) {
- reboot();
- }
+ if (passmeloopQuery()) {
+ reboot();
+ }
#endif
- if (IPC->reset) {
- powerOff();
+ if (IPC->reset) {
+ powerOff();
+ }
+
+ swiWaitForVBlank();
}
- swiWaitForVBlank();
- }
- return 0;
+ return 0;
}
-
-
-//////////////////////////////////////////////////////////////////////
diff --git a/backends/platform/ds/arm9/source/cdaudio.cpp b/backends/platform/ds/arm9/source/cdaudio.cpp
index c963f4d8bd..3952eeb6ab 100644
--- a/backends/platform/ds/arm9/source/cdaudio.cpp
+++ b/backends/platform/ds/arm9/source/cdaudio.cpp
@@ -23,10 +23,10 @@
// Disable symbol overrides for FILE as that is used in FLAC headers
#define FORBIDDEN_SYMBOL_EXCEPTION_FILE
+#include "dsmain.h"
#include "cdaudio.h"
#include "backends/fs/ds/ds-fs.h"
#include "common/config-manager.h"
-#include "dsmain.h"
#include "NDS/scummvm_ipc.h"
#define WAV_FORMAT_IMA_ADPCM 0x14
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index b7c9c108a6..041892aed6 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -68,8 +68,9 @@
// - Try discworld?
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
-
+// Allow use of stuff in <nds.h>
+#define FORBIDDEN_SYMBOL_EXCEPTION_printf
+#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#include <nds.h>
@@ -439,12 +440,12 @@ void playSound(const void *data, u32 length, bool loop, bool adpcm, int rate) {
soundControl.count = 0;
}
- soundControl.data[soundControl.count].data = data;
- soundControl.data[soundControl.count].len = length | (loop? 0x80000000: 0x00000000);
- soundControl.data[soundControl.count].rate = rate; // 367 samples per frame
- soundControl.data[soundControl.count].pan = 64;
- soundControl.data[soundControl.count].vol = 127;
- soundControl.data[soundControl.count].format = adpcm? 2: 0;
+ soundControl.data[soundControl.count].data = data;
+ soundControl.data[soundControl.count].len = length | (loop ? 0x80000000 : 0x00000000);
+ soundControl.data[soundControl.count].rate = rate; // 367 samples per frame
+ soundControl.data[soundControl.count].pan = 64;
+ soundControl.data[soundControl.count].vol = 127;
+ soundControl.data[soundControl.count].format = adpcm ? 2 : 0;
soundControl.count++;
@@ -573,7 +574,7 @@ void initGame() {
s_currentGame = &gameList[0]; // Default game
for (int r = 0; r < NUM_SUPPORTED_GAMES; r++) {
- if (!stricmp(gameName, gameList[r].gameId)) {
+ if (!scumm_stricmp(gameName, gameList[r].gameId)) {
s_currentGame = &gameList[r];
// consolePrintf("Game list num: %d\n", r);
}
@@ -640,7 +641,7 @@ void displayMode8Bit() {
displayModeIs8Bit = true;
if (isCpuScalerEnabled()) {
- videoSetMode(MODE_5_2D | (consoleEnable? DISPLAY_BG0_ACTIVE: 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP);
+ videoSetMode(MODE_5_2D | (consoleEnable ? DISPLAY_BG0_ACTIVE : 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP);
videoSetModeSub(MODE_3_2D /*| DISPLAY_BG0_ACTIVE*/ | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); //sub bg 0 will be used to print text
vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
@@ -659,7 +660,7 @@ void displayMode8Bit() {
BG3_YDY = (int) ((200.0f / 192.0f) * 256);
} else {
- videoSetMode(MODE_5_2D | (consoleEnable? DISPLAY_BG0_ACTIVE: 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP);
+ videoSetMode(MODE_5_2D | (consoleEnable ? DISPLAY_BG0_ACTIVE : 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP);
videoSetModeSub(MODE_3_2D /*| DISPLAY_BG0_ACTIVE*/ | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP); //sub bg 0 will be used to print text
vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
@@ -690,7 +691,7 @@ void displayMode8Bit() {
consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 2, 0, true, true);
// Set this again because consoleinit resets it
- videoSetMode(MODE_5_2D | (consoleEnable? DISPLAY_BG0_ACTIVE: 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP);
+ videoSetMode(MODE_5_2D | (consoleEnable ? DISPLAY_BG0_ACTIVE : 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP);
// Move the cursor to the bottom of the screen using ANSI escape code
consolePrintf("\033[23;0f");
@@ -970,7 +971,7 @@ void displayMode16BitFlipBuffer() {
u16 *back = get16BitBackBuffer();
// highBuffer = !highBuffer;
-// BG3_CR = BG_BMP16_512x256 | BG_BMP_RAM(highBuffer? 1: 0);
+// BG3_CR = BG_BMP16_512x256 | BG_BMP_RAM(highBuffer ? 1 : 0);
if (isCpuScalerEnabled()) {
Rescale_320x256x1555_To_256x256x1555(BG_GFX, back, 512, 512);
@@ -1805,13 +1806,13 @@ void triggerIcon(int imageNum) {
void setIcon(int num, int x, int y, int imageNum, int flags, bool enable) {
- sprites[num].attribute[0] = ATTR0_BMP | (enable? (y & 0xFF): 192) | (!enable? ATTR0_DISABLED: 0);
+ sprites[num].attribute[0] = ATTR0_BMP | (enable ? (y & 0xFF) : 192) | (!enable ? ATTR0_DISABLED : 0);
sprites[num].attribute[1] = ATTR1_SIZE_32 | (x & 0x1FF) | flags;
sprites[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16);
}
void setIconMain(int num, int x, int y, int imageNum, int flags, bool enable) {
- spritesMain[num].attribute[0] = ATTR0_BMP | (y & 0xFF) | (!enable? ATTR0_DISABLED: 0);
+ spritesMain[num].attribute[0] = ATTR0_BMP | (y & 0xFF) | (!enable ? ATTR0_DISABLED : 0);
spritesMain[num].attribute[1] = ATTR1_SIZE_32 | (x & 0x1FF) | flags;
spritesMain[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16);
}
@@ -1841,7 +1842,7 @@ void updateStatus() {
}
if (indyFightState) {
- setIcon(1, (190 - 32), 150, 3, (indyFightRight? 0: ATTR1_FLIP_X), true);
+ setIcon(1, (190 - 32), 150, 3, (indyFightRight ? 0 : ATTR1_FLIP_X), true);
// consolePrintf("%d\n", indyFightRight);
} else {
// setIcon(1, 0, 0, 0, 0, false);
@@ -2164,19 +2165,11 @@ void VBlankHandler(void) {
}
- subScTargetX = xCenter - ((subScreenWidth >> 1) << 8);
+ subScTargetX = xCenter - ((subScreenWidth >> 1) << 8);
subScTargetY = yCenter - ((subScreenHeight >> 1) << 8);
-
-
-
- if (subScTargetX < 0) subScTargetX = 0;
- if (subScTargetX > (gameWidth - subScreenWidth) << 8) subScTargetX = (gameWidth - subScreenWidth) << 8;
-
- if (subScTargetY < 0) subScTargetY = 0;
- if (subScTargetY > (gameHeight - subScreenHeight) << 8) subScTargetY = (gameHeight - subScreenHeight) << 8;
-
-
+ subScTargetX = CLIP(subScTargetX, 0, (gameWidth - subScreenWidth) << 8);
+ subScTargetY = CLIP(subScTargetY, 0, (gameHeight - subScreenHeight) << 8);
subScX += (subScTargetX - subScX) >> 2;
subScY += (subScTargetY - subScY) >> 2;
@@ -2499,7 +2492,7 @@ void penUpdate() {
// if (getKeysHeld() & KEY_L) consolePrintf("%d, %d penX=%d, penY=%d tz=%d\n", IPC->touchXpx, IPC->touchYpx, penX, penY, IPC->touchZ1);
- bool penDownThisFrame = (IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0);
+ bool penDownThisFrame = (!(IPC->buttons & 0x40)) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0);
static bool moved = false;
if (( (tapScreenClicks) || getKeyboardEnable() ) && (getIsDisplayMode8Bit())) {
@@ -2626,7 +2619,7 @@ void penUpdate() {
penDownSaved = true;
}
- if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) {
+ if ((!(IPC->buttons & 0x40)) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) {
penX = IPC->touchXpx + touchXOffset;
penY = IPC->touchYpx + touchYOffset;
moved = true;
@@ -2648,7 +2641,7 @@ void penUpdate() {
- if ((IPC->touchZ1 > 0) || ((penDownFrames == 2)) ) {
+ if ((!(IPC->buttons & 0x40)) || ((penDownFrames == 2)) ) {
penDownLastFrame = true;
penDownFrames++;
} else {
diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h
index fec97d878e..7345fc2ceb 100644
--- a/backends/platform/ds/arm9/source/dsmain.h
+++ b/backends/platform/ds/arm9/source/dsmain.h
@@ -23,6 +23,8 @@
#ifndef _DSMAIN_H
#define _DSMAIN_H
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
#include <nds.h>
#include "osystem_ds.h"
diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp
index 733592e958..562038166b 100644
--- a/backends/platform/ds/arm9/source/dsoptions.cpp
+++ b/backends/platform/ds/arm9/source/dsoptions.cpp
@@ -20,8 +20,8 @@
*
*/
-#include "dsoptions.h"
#include "dsmain.h"
+#include "dsoptions.h"
#include "gui/dialog.h"
#include "gui/gui-manager.h"
#include "gui/widgets/list.h"
diff --git a/backends/platform/ds/arm9/source/fat/disc_io.c b/backends/platform/ds/arm9/source/fat/disc_io.c
index 5896cbb750..74fc8fb09b 100644
--- a/backends/platform/ds/arm9/source/fat/disc_io.c
+++ b/backends/platform/ds/arm9/source/fat/disc_io.c
@@ -367,7 +367,7 @@ bool disc_setDsSlotInterface (void)
active_interface = DLDI_GetInterface();
- if (stricmp((char *)(&_dldi_driver_name), "Default (No interface)")) {
+ if (strcasecmp((char *)(&_dldi_driver_name), "Default (No interface)")) {
char name[48];
memcpy(name, &_dldi_driver_name, 48);
name[47] = '\0';
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index 861ee2e0c5..c35433d3fc 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -23,6 +23,9 @@
// Allow use of stuff in <time.h>
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
+// Allow use of stuff in <nds.h>
+#define FORBIDDEN_SYMBOL_EXCEPTION_printf
+#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
#include "common/scummsys.h"
#include "common/system.h"
diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h
index f883bd14d1..c8698ca418 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.h
+++ b/backends/platform/ds/arm9/source/osystem_ds.h
@@ -24,6 +24,10 @@
#ifndef _OSYSTEM_DS_H_
#define _OSYSTEM_DS_H_
+// Allow use of stuff in <nds.h>
+#define FORBIDDEN_SYMBOL_EXCEPTION_printf
+#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
+
#include "backends/base-backend.h"
#include "common/events.h"
#include "nds.h"
diff --git a/backends/platform/ds/arm9/source/wordcompletion.cpp b/backends/platform/ds/arm9/source/wordcompletion.cpp
index 36fa31247c..2257c49005 100644
--- a/backends/platform/ds/arm9/source/wordcompletion.cpp
+++ b/backends/platform/ds/arm9/source/wordcompletion.cpp
@@ -20,8 +20,8 @@
*
*/
-#include "wordcompletion.h"
#include "osystem_ds.h"
+#include "wordcompletion.h"
#include "engines/agi/agi.h" // Caution for #define for NUM_CHANNELS, causes problems in mixer_intern.h
#ifdef ENABLE_AGI
diff --git a/backends/platform/ds/arm9/source/zipreader.cpp b/backends/platform/ds/arm9/source/zipreader.cpp
index 0de2b0c981..2ad0a39ed2 100644
--- a/backends/platform/ds/arm9/source/zipreader.cpp
+++ b/backends/platform/ds/arm9/source/zipreader.cpp
@@ -23,6 +23,7 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/scummsys.h"
+#include "common/str.h"
#include "zipreader.h"
ZipFile::ZipFile() {
@@ -193,7 +194,7 @@ bool ZipFile::findFile(const char *search) {
}
- if (!stricmp(name, searchName)) {
+ if (!scumm_stricmp(name, searchName)) {
// consolePrintf("'%s'=='%s'\n", name, searchName);
return true; // Got it!
} else {
diff --git a/backends/platform/ds/ds.mk b/backends/platform/ds/ds.mk
index 78216cb9a2..18feea00c2 100644
--- a/backends/platform/ds/ds.mk
+++ b/backends/platform/ds/ds.mk
@@ -75,7 +75,7 @@ endif
# Compiler options for files which should be optimised for speed
-OPT_SPEED := -O3 -mno-thumb
+OPT_SPEED := -O3 -marm
# Compiler options for files which should be optimised for space
OPT_SIZE := -Os -mthumb
@@ -134,7 +134,8 @@ engines/teenagent/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
#
#############################################################################
-all: scummvm.nds scummvm.ds.gba
+# FIXME: Newer versions of devkitARM don't include dsbuild, which is needed to create scummvm.ds.gba
+all: scummvm.nds # scummvm.ds.gba
clean: dsclean
@@ -145,11 +146,8 @@ dsclean:
# TODO: Add a 'dsdist' target ?
-%.bin: %.elf
- $(OBJCOPY) -S -O binary $< $@
-
-%.nds: %.bin $(ndsdir)/arm7/arm7.bin
- ndstool -c $@ -9 $< -7 $(ndsdir)/arm7/arm7.bin -b $(srcdir)/$(ndsdir)/$(LOGO) "$(@F);ScummVM $(VERSION);DS Port"
+%.nds: %.elf $(ndsdir)/arm7/arm7.elf
+ ndstool -c $@ -9 $< -7 $(ndsdir)/arm7/arm7.elf -b $(srcdir)/$(ndsdir)/$(LOGO) "$(@F);ScummVM $(VERSION);DS Port"
%.ds.gba: %.nds
dsbuild $< -o $@ -l $(srcdir)/$(ndsdir)/arm9/ndsloader.bin
@@ -170,10 +168,7 @@ dsclean:
# HACK/FIXME: C compiler, for cartreset.c -- we should switch this to use CXX
# as soon as possible.
-CC := $(DEVKITPRO)/devkitARM/bin/arm-eabi-gcc
-
-# HACK/TODO: Pointer to objcopy. This should really be set by configure
-OBJCOPY := $(DEVKITPRO)/devkitARM/bin/arm-eabi-objcopy
+CC := $(DEVKITPRO)/devkitARM/bin/arm-none-eabi-gcc
#
# Set various flags
@@ -194,7 +189,7 @@ ARM7_CFLAGS := -g -Wall -O2\
ARM7_CXXFLAGS := $(ARM7_CFLAGS) -fno-exceptions -fno-rtti
-ARM7_LDFLAGS := -g $(ARM7_ARCH) -mno-fpu
+ARM7_LDFLAGS := -g $(ARM7_ARCH) -mfloat-abi=soft
# HACK/FIXME: Define a custom build rule for cartreset.c.
# We do this because it is a .c file, not a .cpp file and so is outside our
@@ -218,10 +213,6 @@ $(ndsdir)/arm7/arm7.elf: \
$(ndsdir)/arm7/source/main.o
$(CXX) $(ARM7_LDFLAGS) -specs=ds_arm7.specs $+ -L$(DEVKITPRO)/libnds/lib -lnds7 -o $@
-# Rule for creating ARM7 .bin files from .elf files
-$(ndsdir)/arm7/arm7.bin: $(ndsdir)/arm7/arm7.elf
- $(OBJCOPY) -O binary $< $@
-
diff --git a/backends/platform/ios7/README.md b/backends/platform/ios7/README.md
index f7d828ee94..48a3d3e830 100644
--- a/backends/platform/ios7/README.md
+++ b/backends/platform/ios7/README.md
@@ -6,132 +6,7 @@ I tried to use all the latest iOS features to replace the old code. For instance
## Compilation ##
-First, clone the repository:
-```
-$ git clone https://github.com/scummvm/scummvm.git
-```
-
-### Compilation from Xcode ###
-
-This is the recommended way to compile ScummVM, and the only one which makes it possible to run ScummVM on a non-jailbroken device!
-
-The next step is to compile the **create_project** tool. Open the Xcode project you'll found in the **devtools/create\_project/xcode/** directory. Once compiled, copy the binary somewhere in your *PATH*, and create a **build** directory somewhere on your harddisk. It is recommended to create this directory next to the cloned repository (they share the same parent).
-
-Execute the following commands in a terminal:
-```
-$ cd path_to_the_build_directory
-$ create_project path_to_scummvm_repository --xcode --enable-fluidsynth --disable-jpeg --disable-bink --disable-16bit --disable-mt32emu --disable-nasm --disable-opengl --disable-theora --disable-taskbar
-```
-
-This will create an Xcode project for ScummVM, for both the OS X, and the iOS target.
-
-Now, download the external libraries from http://bsr43.free.fr/scummvm/ScummVM-iOS-libraries.zip. Unzip the archive in your **build** directory. Please make sure that the **lib**, and **include** directories are at the root of the **build** directory, not in a subdirectory.
-
-Now, your **build** directory should contain:
-* a generated **engines** directory,
-* a generated **scummvm.xcodeproj** project,
-* an **include** directory,
-* a **lib** directory.
-
-You are ready to compile ScummVM: open the **scummvm.xcodeproj** project, and build it.
-
-### Compilation from command line ###
-
-For jailbroken devices, it is also possible to compile the project from command line. You'll need a working toolchain, and some tools, like **ldid**, to fake the code signature.
-
-Here is a script to download, and compile all the required tools. This script has been wrote for Debian 8.2, and should be run as root.
-
-```
-#!/bin/bash
-
-if [ $UID -ne 0 ]; then
- echo "This script should be run by the root user"
- exit 1
-fi
-
-# Install the Clang compiler
-apt-get install -y clang-3.4 libclang-3.4-dev llvm-3.4 libtool bison flex automake subversion git pkg-config wget libssl-dev uuid-dev libxml2-dev || exit 1
-
-# Add LLVM to the linker library path
-echo /usr/lib/llvm-3.4/lib > /etc/ld.so.conf.d/libllvm-3.4.conf
-ldconfig
-
-# Add symlinks for the LLVM headers
-ln -s /usr/lib/llvm-3.4/bin/llvm-config /usr/bin/llvm-config || exit 1
-ln -s /usr/include/llvm-3.4/llvm /usr/include/llvm || exit 1
-ln -s /usr/include/llvm-c-3.4/llvm-c /usr/include/llvm-c || exit 1
-ln -s /usr/bin/clang-3.4 /usr/bin/clang || exit 1
-ln -s /usr/bin/clang++-3.4 /usr/bin/clang++ || exit 1
-
-# Build the linker
-svn checkout http://ios-toolchain-based-on-clang-for-linux.googlecode.com/svn/trunk/cctools-porting || exit 1
-cd cctools-porting
-sed -i'' 's/proz -k=20 --no-curses/wget/g' cctools-ld64.sh
-./cctools-ld64.sh || exit 1
-
-cd cctools-855-ld64-236.3
-./autogen.sh || exit 1
-./configure --prefix=/usr/local --target=arm-apple-darwin11 || exit 1
-make || exit 1
-make install || exit 1
-cd ../..
-
-# Install ios-tools
-wget https://ios-toolchain-based-on-clang-for-linux.googlecode.com/files/iphonesdk-utils-2.0.tar.gz || exit 1
-tar xzf iphonesdk-utils-2.0.tar.gz
-cd iphonesdk-utils-2.0
-patch -p0 <<_EOF
-*** genLocalization2/getLocalizedStringFromFile.cpp 2015-04-02 04:45:39.309837816 +0530
---- genLocalization2/getLocalizedStringFromFile.cpp 2015-04-02 04:45:11.525700021 +0530
-***************
-*** 113,115 ****
- clang::HeaderSearch headerSearch(headerSearchOptions,
-- fileManager,
- *pDiagnosticsEngine,
---- 113,115 ----
- clang::HeaderSearch headerSearch(headerSearchOptions,
-+ sourceManager,
- *pDiagnosticsEngine,
-***************
-*** 129,134 ****
- false);
-- clang::HeaderSearch headerSearch(fileManager,
- *pDiagnosticsEngine,
- languageOptions,
-- pTargetInfo);
- ApplyHeaderSearchOptions(headerSearch, headerSearchOptions, languageOptions, pTargetInfo->getTriple());
---- 129,134 ----
- false);
-+ clang::HeaderSearch headerSearch(fileManager);/*,
- *pDiagnosticsEngine,
- languageOptions,
-+ pTargetInfo);*/
- ApplyHeaderSearchOptions(headerSearch, headerSearchOptions, languageOptio
-_EOF
-
-./autogen.sh || exit 1
-CC=clang CXX=clang++ ./configure --prefix=/usr/local || exit 1
-make || exit 1
-make install || exit 1
-
-# Install the iOS SDK 8.1
-mkdir -p /usr/share/ios-sdk
-cd /usr/share/ios-sdk
-wget http://iphone.howett.net/sdks/dl/iPhoneOS8.1.sdk.tbz2 || exit 1
-tar xjf iPhoneOS8.1.sdk.tbz2
-rm iPhoneOS8.1.sdk.tbz2
-```
-
-Now, in order to compile ScummVM, execute the following commands:
-```
-$ export SDKROOT=/usr/share/ios-sdk/iPhoneOS8.1.sdk
-$ export CC=ios-clang
-$ export CXX=ios-clang++
-$ ./configure --host=ios7 --disable-mt32emu --enable-release
-$ make ios7bundle
-```
-
-At the end of the compilation, you'll find a **ScummVM.app** application: copy it over SSH, and reboot your device.
+See http://wiki.scummvm.org/index.php/Compiling_ScummVM/iPhone
## Usage ##
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index e0ac599b1d..9b9d2bdee0 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -123,7 +123,7 @@ public:
static OSystem_iOS7 *sharedInstance();
virtual void initBackend();
-
+
virtual void engineInit();
virtual void engineDone();
diff --git a/backends/platform/n64/osys_n64_base.cpp b/backends/platform/n64/osys_n64_base.cpp
index 1282b16d47..2bde28dd62 100644
--- a/backends/platform/n64/osys_n64_base.cpp
+++ b/backends/platform/n64/osys_n64_base.cpp
@@ -227,7 +227,7 @@ int OSystem_N64::getDefaultGraphicsMode() const {
bool OSystem_N64::setGraphicsMode(const char *mode) {
int i = 0;
while (s_supportedGraphicsModes[i].name) {
- if (!strcmpi(s_supportedGraphicsModes[i].name, mode)) {
+ if (!scumm_stricmp(s_supportedGraphicsModes[i].name, mode)) {
_graphicMode = s_supportedGraphicsModes[i].id;
switchGraphicModeId(_graphicMode);
diff --git a/backends/platform/n64/portdefs.h b/backends/platform/n64/portdefs.h
index 63ec989a8d..364520803b 100644
--- a/backends/platform/n64/portdefs.h
+++ b/backends/platform/n64/portdefs.h
@@ -36,17 +36,4 @@
#undef assert
#define assert(x) ((x) ? 0 : (print_error("ASSERT TRIGGERED:\n\n("#x")\n%s\nline: %d", __FILE__, __LINE__)))
-// Typedef basic data types in a way that is compatible with the N64 SDK.
-typedef unsigned char byte;
-typedef unsigned char uint8;
-typedef signed char int8;
-typedef unsigned short int uint16;
-typedef signed short int int16;
-typedef unsigned int uint32;
-typedef signed int int32;
-
-// Define SCUMMVM_DONT_DEFINE_TYPES to prevent scummsys.h from trying to
-// re-define those data types.
-#define SCUMMVM_DONT_DEFINE_TYPES
-
-#endif
+#endif // __N64_PORTDEFS__
diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp
index 33bf190d70..54ad0d3223 100644
--- a/backends/platform/psp/display_manager.cpp
+++ b/backends/platform/psp/display_manager.cpp
@@ -332,7 +332,7 @@ bool DisplayManager::setGraphicsMode(const char *name) {
int i = 0;
while (_supportedModes[i].name) {
- if (!strcmpi(_supportedModes[i].name, name)) {
+ if (!scumm_stricmp(_supportedModes[i].name, name)) {
setGraphicsMode(_supportedModes[i].id);
return true;
}
diff --git a/backends/platform/psp/input.cpp b/backends/platform/psp/input.cpp
index 7a2047f28e..8e5f170a7d 100644
--- a/backends/platform/psp/input.cpp
+++ b/backends/platform/psp/input.cpp
@@ -336,7 +336,7 @@ bool Nub::getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad) {
// keep track of remainder for true sub-pixel cursor position
_hiresX %= 1024;
_hiresY %= 1024;
-
+
int32 oldX = _cursor->getX();
int32 oldY = _cursor->getY();
diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp
index 8ecbe7306c..62037200ea 100644
--- a/backends/platform/sdl/macosx/macosx.cpp
+++ b/backends/platform/sdl/macosx/macosx.cpp
@@ -124,6 +124,10 @@ Common::String OSystem_MacOSX::getTextFromClipboard() {
return getTextFromClipboardMacOSX();
}
+bool OSystem_MacOSX::setTextInClipboard(const Common::String &text) {
+ return setTextInClipboardMacOSX(text);
+}
+
bool OSystem_MacOSX::openUrl(const Common::String &url) {
CFURLRef urlRef = CFURLCreateWithBytes (NULL, (UInt8*)url.c_str(), url.size(), kCFStringEncodingASCII, NULL);
OSStatus err = LSOpenCFURLRef(urlRef, NULL);
diff --git a/backends/platform/sdl/macosx/macosx.h b/backends/platform/sdl/macosx/macosx.h
index ba07364681..5ef30baa64 100644
--- a/backends/platform/sdl/macosx/macosx.h
+++ b/backends/platform/sdl/macosx/macosx.h
@@ -35,6 +35,7 @@ public:
virtual bool hasTextInClipboard();
virtual Common::String getTextFromClipboard();
+ virtual bool setTextInClipboard(const Common::String &text);
virtual bool openUrl(const Common::String &url);
diff --git a/backends/platform/sdl/macosx/macosx_wrapper.h b/backends/platform/sdl/macosx/macosx_wrapper.h
index 84f0c1b2ba..ca4e433890 100644
--- a/backends/platform/sdl/macosx/macosx_wrapper.h
+++ b/backends/platform/sdl/macosx/macosx_wrapper.h
@@ -27,6 +27,7 @@
bool hasTextInClipboardMacOSX();
Common::String getTextFromClipboardMacOSX();
+bool setTextInClipboardMacOSX(const Common::String &text);
Common::String getDesktopPathMacOSX();
#endif
diff --git a/backends/platform/sdl/macosx/macosx_wrapper.mm b/backends/platform/sdl/macosx/macosx_wrapper.mm
index 02516e5ffe..32dfa040cc 100644
--- a/backends/platform/sdl/macosx/macosx_wrapper.mm
+++ b/backends/platform/sdl/macosx/macosx_wrapper.mm
@@ -24,11 +24,13 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/platform/sdl/macosx/macosx_wrapper.h"
+#include "common/translation.h"
#include <AppKit/NSPasteboard.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSPathUtilities.h>
#include <AvailabilityMacros.h>
+#include <CoreFoundation/CFString.h>
bool hasTextInClipboardMacOSX() {
return [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]] != nil;
@@ -40,13 +42,33 @@ Common::String getTextFromClipboardMacOSX() {
// Note: on OS X 10.6 and above it is recommanded to use NSPasteboardTypeString rather than NSStringPboardType.
// But since we still target older version use NSStringPboardType.
NSPasteboard *pb = [NSPasteboard generalPasteboard];
- NSString* str = [pb stringForType:NSStringPboardType];
+ NSString *str = [pb stringForType:NSStringPboardType];
if (str == nil)
return Common::String();
- // If the string cannot be represented using the requested encoding we get a null pointer below.
- // This is fine as ScummVM would not know what to do with non-ASCII characters (although maybe
- // we should use NSISOLatin1StringEncoding?).
- return Common::String([str cStringUsingEncoding:NSASCIIStringEncoding]);
+
+ // If translations are supported, use the current TranslationManager charset and otherwise
+ // use ASCII. If the string cannot be represented using the requested encoding we get a null
+ // pointer below, which is fine as ScummVM would not know what to do with the string anyway.
+#ifdef USE_TRANSLATION
+ NSString* encStr = [NSString stringWithCString:TransMan.getCurrentCharset().c_str() encoding:NSASCIIStringEncoding];
+ NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)encStr));
+#else
+ NSStringEncoding encoding = NSISOLatin1StringEncoding;
+#endif
+ return Common::String([str cStringUsingEncoding:encoding]);
+}
+
+bool setTextInClipboardMacOSX(const Common::String &text) {
+ NSPasteboard *pb = [NSPasteboard generalPasteboard];
+ [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
+
+#ifdef USE_TRANSLATION
+ NSString* encStr = [NSString stringWithCString:TransMan.getCurrentCharset().c_str() encoding:NSASCIIStringEncoding];
+ NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)encStr));
+#else
+ NSStringEncoding encoding = NSISOLatin1StringEncoding;
+#endif
+ return [pb setString:[NSString stringWithCString:text.c_str() encoding:encoding] forType:NSStringPboardType];
}
Common::String getDesktopPathMacOSX() {
diff --git a/backends/platform/sdl/psp2/psp2-main.cpp b/backends/platform/sdl/psp2/psp2-main.cpp
index 0bdf0b34bc..70cc52388e 100644
--- a/backends/platform/sdl/psp2/psp2-main.cpp
+++ b/backends/platform/sdl/psp2/psp2-main.cpp
@@ -40,7 +40,7 @@ int main(int argc, char *argv[]) {
scePowerSetBusClockFrequency(222);
scePowerSetGpuClockFrequency(222);
scePowerSetGpuXbarClockFrequency(166);
-
+
// Create our OSystem instance
g_system = new OSystem_PSP2();
assert(g_system);
@@ -57,7 +57,7 @@ int main(int argc, char *argv[]) {
// Free OSystem
delete (OSystem_PSP2 *)g_system;
-
+
#ifdef __PSP2_DEBUG__
psp2shell_exit();
#endif
diff --git a/backends/platform/sdl/psp2/psp2.cpp b/backends/platform/sdl/psp2/psp2.cpp
index 3034b6d886..80604a69d5 100644
--- a/backends/platform/sdl/psp2/psp2.cpp
+++ b/backends/platform/sdl/psp2/psp2.cpp
@@ -55,11 +55,11 @@ OSystem_PSP2::OSystem_PSP2(Common::String baseConfigName)
}
void OSystem_PSP2::init() {
-
+
#if __PSP2_DEBUG__
gDebugLevel = 3;
#endif
-
+
// Initialze File System Factory
sceIoMkdir("ux0:data", 0755);
sceIoMkdir("ux0:data/scummvm", 0755);
@@ -71,7 +71,7 @@ void OSystem_PSP2::init() {
}
void OSystem_PSP2::initBackend() {
-
+
ConfMan.set("joystick_num", 0);
ConfMan.registerDefault("fullscreen", true);
ConfMan.registerDefault("aspect_ratio", false);
@@ -105,7 +105,7 @@ void OSystem_PSP2::initBackend() {
ConfMan.setBool("frontpanel_touchpad_mode", false);
}
-
+
// Create the savefile manager
if (_savefileManager == 0)
_savefileManager = new DefaultSaveFileManager("ux0:data/scummvm/saves");
diff --git a/backends/platform/sdl/riscos/riscos-main.cpp b/backends/platform/sdl/riscos/riscos-main.cpp
index 2ff8294c1a..3f7058e3b8 100644
--- a/backends/platform/sdl/riscos/riscos-main.cpp
+++ b/backends/platform/sdl/riscos/riscos-main.cpp
@@ -29,7 +29,7 @@
#include "base/main.h"
int main(int argc, char *argv[]) {
-
+
// Create our OSystem instance
g_system = new OSystem_RISCOS();
assert(g_system);
diff --git a/backends/platform/sdl/riscos/riscos.cpp b/backends/platform/sdl/riscos/riscos.cpp
index 0cdbceb902..73c0fdae03 100644
--- a/backends/platform/sdl/riscos/riscos.cpp
+++ b/backends/platform/sdl/riscos/riscos.cpp
@@ -101,4 +101,4 @@ Common::WriteStream *OSystem_RISCOS::createLogFile() {
}
#endif
-
+
diff --git a/backends/platform/sdl/riscos/riscos.mk b/backends/platform/sdl/riscos/riscos.mk
index 534b7aeb52..0a3061fd3a 100644
--- a/backends/platform/sdl/riscos/riscos.mk
+++ b/backends/platform/sdl/riscos/riscos.mk
@@ -21,4 +21,5 @@ ifdef DYNAMIC_MODULES
endif
mkdir -p !ScummVM/docs
cp ${srcdir}/dists/riscos/!Help,feb !ScummVM/!Help,feb
- cp $(DIST_FILES_DOCS) !ScummVM/docs \ No newline at end of file
+ cp $(DIST_FILES_DOCS) !ScummVM/docs
+ cp -r ${srcdir}/doc/* !ScummVM/docs
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 3082a69ebf..72af6d592a 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -33,6 +33,7 @@
#include "gui/EventRecorder.h"
#include "common/taskbar.h"
#include "common/textconsole.h"
+#include "common/translation.h"
#include "backends/saves/default/default-saves.h"
@@ -502,17 +503,46 @@ Common::String OSystem_SDL::getTextFromClipboard() {
#if SDL_VERSION_ATLEAST(2, 0, 0)
char *text = SDL_GetClipboardText();
+ // The string returned by SDL is in UTF-8. Convert to the
+ // current TranslationManager encoding or ISO-8859-1.
+#ifdef USE_TRANSLATION
+ char *conv_text = SDL_iconv_string(TransMan.getCurrentCharset().c_str(), "UTF-8", text, SDL_strlen(text) + 1);
+#else
+ char *conv_text = SDL_iconv_string("ISO-8859-1", "UTF-8", text, SDL_strlen(text) + 1);
+#endif
+ if (conv_text) {
+ SDL_free(text);
+ text = conv_text;
+ }
Common::String strText = text;
SDL_free(text);
- // FIXME: The string returned by SDL is in UTF-8, it is not clear
- // what encoding should be used for the returned string.
return strText;
#else
return "";
#endif
}
+bool OSystem_SDL::setTextInClipboard(const Common::String &text) {
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ // The encoding we need to use is UTF-8. Assume we currently have the
+ // current TranslationManager encoding or ISO-8859-1.
+#ifdef USE_TRANSLATION
+ char *utf8_text = SDL_iconv_string("UTF-8", TransMan.getCurrentCharset().c_str(), text.c_str(), text.size() + 1);
+#else
+ char *utf8_text = SDL_iconv_string("UTF-8", "ISO-8859-1", text.c_str(), text.size() + 1);
+#endif
+ if (utf8_text) {
+ int status = SDL_SetClipboardText(utf8_text);
+ SDL_free(utf8_text);
+ return status == 0;
+ }
+ return SDL_SetClipboardText(text.c_str()) == 0;
+#else
+ return false;
+#endif
+}
+
uint32 OSystem_SDL::getMillis(bool skipRecord) {
uint32 millis = SDL_GetTicks();
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 61513fa65f..c746d2d2dd 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -72,6 +72,7 @@ public:
// Clipboard
virtual bool hasTextInClipboard();
virtual Common::String getTextFromClipboard();
+ virtual bool setTextInClipboard(const Common::String &text);
virtual void setWindowCaption(const char *caption);
virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
diff --git a/backends/platform/wii/osystem_events.cpp b/backends/platform/wii/osystem_events.cpp
index 2499300a56..ae9c27f03b 100644
--- a/backends/platform/wii/osystem_events.cpp
+++ b/backends/platform/wii/osystem_events.cpp
@@ -228,7 +228,7 @@ bool OSystem_Wii::pollKeyboard(Common::Event &event) {
keyboard_event kbdEvent;
s32 res = KEYBOARD_GetEvent(&kbdEvent);
-
+
if (!res)
return false;
diff --git a/backends/plugins/ds/ds-provider.cpp b/backends/plugins/ds/ds-provider.cpp
index 1c9744518e..c5419a989a 100644
--- a/backends/plugins/ds/ds-provider.cpp
+++ b/backends/plugins/ds/ds-provider.cpp
@@ -20,6 +20,10 @@
*
*/
+// Allow use of stuff in <nds.h>
+#define FORBIDDEN_SYMBOL_EXCEPTION_printf
+#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
+
#include "common/scummsys.h"
#if defined(DYNAMIC_MODULES) && defined(__DS__)
diff --git a/backends/plugins/elf/version.cpp b/backends/plugins/elf/version.cpp
index ac999e1d7c..e91ec6b172 100644
--- a/backends/plugins/elf/version.cpp
+++ b/backends/plugins/elf/version.cpp
@@ -27,6 +27,6 @@
const char *gScummVMPluginBuildDate = "Git Master"; /* ScummVM Git Master */
#else
const char *gScummVMPluginBuildDate __attribute__((visibility("hidden"))) =
- __DATE__ " " __TIME__ ;
+ __DATE__ " " __TIME__;
#endif
#endif
diff --git a/backends/saves/psp/psp-saves.cpp b/backends/saves/psp/psp-saves.cpp
index 9d9affbc1b..ba09223884 100644
--- a/backends/saves/psp/psp-saves.cpp
+++ b/backends/saves/psp/psp-saves.cpp
@@ -60,16 +60,15 @@ PSPSaveFileManager::PSPSaveFileManager(const Common::String &defaultSavepath)
*/
void PSPSaveFileManager::checkPath(const Common::FSNode &dir) {
- const char *savePath = dir.getPath().c_str();
clearError();
PowerMan.beginCriticalSection();
//check if the save directory exists
- SceUID fd = sceIoDopen(savePath);
+ SceUID fd = sceIoDopen(dir.getPath().c_str());
if (fd < 0) {
//No? then let's create it.
- sceIoMkdir(savePath, 0777);
+ sceIoMkdir(dir.getPath().c_str(), 0777);
} else {
//it exists, so close it again.
sceIoDclose(fd);
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 2e981fb75a..96548b9129 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -68,18 +68,18 @@ static const char HELP_STRING[] =
" -h, --help Display a brief help text and exit\n"
" -z, --list-games Display list of supported games and exit\n"
" -t, --list-targets Display list of configured targets and exit\n"
- " --list-saves=TARGET Display a list of saved games for the game (TARGET) specified\n"
+ " --list-saves Display a list of saved games for the target specified\n"
+ " with --game=TARGET, or all targets if none is specified\n"
" -a, --add Add all games from current or specified directory.\n"
" If --game=ID is passed only the game with id ID is added. See also --detect\n"
- " Use --path=PATH before -a, --add to specify a directory.\n"
+ " Use --path=PATH to specify a directory.\n"
" --detect Display a list of games with their ID from current or\n"
" specified directory without adding it to the config.\n"
- " Use --path=PATH before --detect to specify a directory.\n"
+ " Use --path=PATH to specify a directory.\n"
" --game=ID In combination with --add or --detect only adds or attempts to\n"
" detect the game with id ID.\n"
" --auto-detect Display a list of games from current or specified directory\n"
- " and start the first one. Use --path=PATH before --auto-detect\n"
- " to specify a directory.\n"
+ " and start the first one. Use --path=PATH to specify a directory.\n"
" --recursive In combination with --add or --detect recurse down all subdirectories\n"
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
" --console Enable the console window (default:enabled)\n"
@@ -131,7 +131,14 @@ static const char HELP_STRING[] =
" --native-mt32 True Roland MT-32 (disable GM emulation)\n"
" --enable-gs Enable Roland GS mode for MIDI playback\n"
" --output-rate=RATE Select output sample rate in Hz (e.g. 22050)\n"
- " --opl-driver=DRIVER Select AdLib (OPL) emulator (db, mame)\n"
+ " --opl-driver=DRIVER Select AdLib (OPL) emulator (db, mame"
+#ifndef DISABLE_NUKED_OPL
+ ", nuked"
+#endif
+#ifdef ENABLE_OPL2LPT
+ ", opl2lpt"
+#endif
+ ")\n"
" --aspect-ratio Enable aspect ratio correction\n"
" --render-mode=MODE Enable additional render modes (hercGreen, hercAmber,\n"
" cga, ega, vga, amiga, fmtowns, pc9821, pc9801, 2gs,\n"
@@ -148,7 +155,7 @@ static const char HELP_STRING[] =
" --alt-intro Use alternative intro for CD versions of Beneath a\n"
" Steel Sky and Flight of the Amazon Queen\n"
#endif
- " --copy-protection Enable copy protection in SCUMM games, when\n"
+ " --copy-protection Enable copy protection in games, when\n"
" ScummVM disables it by default.\n"
" --talkspeed=NUM Set talk speed for games (default: 60)\n"
#if defined(ENABLE_SCUMM) || defined(ENABLE_GROOVIE)
@@ -189,6 +196,11 @@ static void usage(const char *s, ...) {
exit(1);
}
+static void ensureFirstCommand(const Common::String &existingCommand, const char *newCommand) {
+ if (!existingCommand.empty())
+ usage("--%s: Cannot accept more than one command (already found --%s).", newCommand, existingCommand.c_str());
+}
+
#endif // DISABLE_COMMAND_LINE
@@ -220,6 +232,7 @@ void registerDefaults() {
ConfMan.registerDefault("music_driver", "auto");
ConfMan.registerDefault("mt32_device", "null");
ConfMan.registerDefault("gm_device", "null");
+ ConfMan.registerDefault("opl2lpt_parport", "null");
ConfMan.registerDefault("cdrom", 0);
@@ -233,7 +246,7 @@ void registerDefaults() {
ConfMan.registerDefault("boot_param", 0);
ConfMan.registerDefault("dump_scripts", false);
ConfMan.registerDefault("save_slot", -1);
- ConfMan.registerDefault("autosave_period", 5 * 60); // By default, trigger autosave every 5 minutes
+ ConfMan.registerDefault("autosave_period", 5 * 60); // By default, trigger autosave every 5 minutes
#if defined(ENABLE_SCUMM) || defined(ENABLE_SWORD2)
ConfMan.registerDefault("object_labels", true);
@@ -300,7 +313,7 @@ void registerDefaults() {
// Use this for options which have an *optional* value
#define DO_OPTION_OPT(shortCmd, longCmd, defaultVal) \
- if (isLongCmd ? (!strcmp(s+2, longCmd) || !memcmp(s+2, longCmd"=", sizeof(longCmd"=") - 1)) : (tolower(s[1]) == shortCmd)) { \
+ if (isLongCmd ? (!strcmp(s + 2, longCmd) || !memcmp(s + 2, longCmd"=", sizeof(longCmd"=") - 1)) : (tolower(s[1]) == shortCmd)) { \
s += 2; \
if (isLongCmd) { \
s += sizeof(longCmd) - 1; \
@@ -329,7 +342,7 @@ void registerDefaults() {
// Use this for boolean options; this distinguishes between "-x" and "-X",
// resp. between "--some-option" and "--no-some-option".
#define DO_OPTION_BOOL(shortCmd, longCmd) \
- if (isLongCmd ? (!strcmp(s+2, longCmd) || !strcmp(s+2, "no-" longCmd)) : (tolower(s[1]) == shortCmd)) { \
+ if (isLongCmd ? (!strcmp(s + 2, longCmd) || !strcmp(s + 2, "no-" longCmd)) : (tolower(s[1]) == shortCmd)) { \
bool boolValue = (Common::isLower(s[1]) != 0); \
s += 2; \
if (isLongCmd) { \
@@ -342,12 +355,13 @@ void registerDefaults() {
// Use this for options which never have a value, i.e. for 'commands', like "--help".
#define DO_COMMAND(shortCmd, longCmd) \
- if (isLongCmd ? (!strcmp(s+2, longCmd)) : (tolower(s[1]) == shortCmd)) { \
+ if (isLongCmd ? (!strcmp(s + 2, longCmd)) : (tolower(s[1]) == shortCmd)) { \
s += 2; \
if (isLongCmd) \
s += sizeof(longCmd) - 1; \
if (*s != '\0') goto unknownOption; \
- return longCmd;
+ ensureFirstCommand(command, longCmd); \
+ command = longCmd;
#define DO_LONG_OPTION_OPT(longCmd, d) DO_OPTION_OPT(0, longCmd, d)
@@ -363,19 +377,21 @@ void registerDefaults() {
// End an option handler
#define END_COMMAND \
+ continue; \
}
Common::String parseCommandLine(Common::StringMap &settings, int argc, const char * const *argv) {
const char *s, *s2;
+ Common::String command;
if (!argv)
- return Common::String();
+ return command;
// argv[0] contains the name of the executable.
if (argv[0]) {
s = strrchr(argv[0], '/');
- s_appName = s ? (s+1) : argv[0];
+ s_appName = s ? (s + 1) : argv[0];
}
// We store all command line settings into a string map.
@@ -443,12 +459,8 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
END_COMMAND
#endif
- DO_LONG_OPTION("list-saves")
- // FIXME: Need to document this.
- // TODO: Make the argument optional. If no argument is given, list all saved games
- // for all configured targets.
- return "list-saves";
- END_OPTION
+ DO_LONG_COMMAND("list-saves")
+ END_COMMAND
DO_OPTION('c', "config")
END_OPTION
@@ -665,7 +677,7 @@ unknownOption:
}
}
- return Common::String();
+ return command;
}
/** List all supported game IDs, i.e. all games which any loaded plugin supports. */
@@ -675,9 +687,9 @@ static void listGames() {
const PluginList &plugins = EngineMan.getPlugins();
for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
- GameList list = (*iter)->get<MetaEngine>().getSupportedGames();
- for (GameList::iterator v = list.begin(); v != list.end(); ++v) {
- printf("%-20s %s\n", v->gameid().c_str(), v->description().c_str());
+ PlainGameList list = (*iter)->get<MetaEngine>().getSupportedGames();
+ for (PlainGameList::iterator v = list.begin(); v != list.end(); ++v) {
+ printf("%-20s %s\n", v->gameId, v->description);
}
}
}
@@ -702,10 +714,10 @@ static void listTargets() {
// FIXME: At this point, we should check for a "gameid" override
// to find the proper desc. In fact, the platform probably should
// be taken into account, too.
- Common::String gameid(name);
- GameDescriptor g = EngineMan.findGame(gameid);
- if (g.description().size() > 0)
- description = g.description();
+ const Common::String &gameid = name;
+ PlainGameDescriptor g = EngineMan.findGame(gameid);
+ if (g.description)
+ description = g.description;
}
targets.push_back(Common::String::format("%-20s %s", name.c_str(), description.c_str()));
@@ -718,65 +730,97 @@ static void listTargets() {
}
/** List all saves states for the given target. */
-static Common::Error listSaves(const char *target) {
+static Common::Error listSaves(const Common::String &target) {
Common::Error result = Common::kNoError;
+ // If no target is specified, list save games for all known targets
+ Common::Array<Common::String> targets;
+ if (!target.empty())
+ targets.push_back(target);
+ else {
+ const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
+ Common::ConfigManager::DomainMap::const_iterator iter;
+
+ targets.reserve(domains.size());
+ for (iter = domains.begin(); iter != domains.end(); ++iter)
+ targets.push_back(iter->_key);
+ }
+
// FIXME HACK
g_system->initBackend();
- // Grab the "target" domain, if any
- const Common::ConfigManager::Domain *domain = ConfMan.getDomain(target);
-
- // Set up the game domain as newly active domain, so
- // target specific savepath will be checked
Common::String oldDomain = ConfMan.getActiveDomainName();
- ConfMan.setActiveDomain(target);
-
- // Grab the gameid from the domain resp. use the target as gameid
- Common::String gameid;
- if (domain)
- gameid = domain->getVal("gameid");
- if (gameid.empty())
- gameid = target;
- gameid.toLowercase(); // Normalize it to lower case
-
- // Find the plugin that will handle the specified gameid
- const Plugin *plugin = nullptr;
- GameDescriptor game = EngineMan.findGame(gameid, &plugin);
-
- if (!plugin) {
- return Common::Error(Common::kEnginePluginNotFound,
- Common::String::format("target '%s', gameid '%s", target, gameid.c_str()));
- }
- const MetaEngine &metaEngine = plugin->get<MetaEngine>();
+ bool atLeastOneFound = false;
+ for (Common::Array<Common::String>::const_iterator i = targets.begin(), end = targets.end(); i != end; ++i) {
+ // Grab the "target" domain, if any
+ const Common::ConfigManager::Domain *domain = ConfMan.getDomain(*i);
+
+ // Set up the game domain as newly active domain, so
+ // target specific savepath will be checked
+ ConfMan.setActiveDomain(*i);
+
+ // Grab the gameid from the domain resp. use the target as gameid
+ Common::String gameid;
+ if (domain)
+ gameid = domain->getVal("gameid");
+ if (gameid.empty())
+ gameid = *i;
+ gameid.toLowercase(); // Normalize it to lower case
+
+ // Find the plugin that will handle the specified gameid
+ const Plugin *plugin = nullptr;
+ EngineMan.findGame(gameid, &plugin);
+
+ if (!plugin) {
+ // If the target was specified, treat this as an error, and otherwise skip it.
+ if (!target.empty())
+ return Common::Error(Common::kEnginePluginNotFound,
+ Common::String::format("target '%s', gameid '%s", i->c_str(), gameid.c_str()));
+ printf("Plugin could not be loaded for target '%s', gameid '%s", i->c_str(), gameid.c_str());
+ continue;
+ }
+
+ const MetaEngine &metaEngine = plugin->get<MetaEngine>();
+
+ if (!metaEngine.hasFeature(MetaEngine::kSupportsListSaves)) {
+ // If the target was specified, treat this as an error, and otherwise skip it.
+ if (!target.empty())
+ // TODO: Include more info about the target (desc, engine name, ...) ???
+ return Common::Error(Common::kEnginePluginNotSupportSaves,
+ Common::String::format("target '%s', gameid '%s", i->c_str(), gameid.c_str()));
+ continue;
+ }
- if (!metaEngine.hasFeature(MetaEngine::kSupportsListSaves)) {
- // TODO: Include more info about the target (desc, engine name, ...) ???
- return Common::Error(Common::kEnginePluginNotSupportSaves,
- Common::String::format("target '%s', gameid '%s", target, gameid.c_str()));
- } else {
// Query the plugin for a list of saved games
- SaveStateList saveList = metaEngine.listSaves(target);
+ SaveStateList saveList = metaEngine.listSaves(i->c_str());
if (saveList.size() > 0) {
// TODO: Include more info about the target (desc, engine name, ...) ???
- printf("Save states for target '%s' (gameid '%s'):\n", target, gameid.c_str());
+ if (atLeastOneFound)
+ printf("\n");
+ printf("Save states for target '%s' (gameid '%s'):\n", i->c_str(), gameid.c_str());
printf(" Slot Description \n"
- " ---- ------------------------------------------------------\n");
+ " ---- ------------------------------------------------------\n");
for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) {
printf(" %-4d %s\n", x->getSaveSlot(), x->getDescription().c_str());
// TODO: Could also iterate over the full hashmap, printing all key-value pairs
}
+ atLeastOneFound = true;
} else {
- printf("There are no save states for target '%s' (gameid '%s'):\n", target, gameid.c_str());
+ // If the target was specified, indicate no save games were found for it. Otherwise just skip it.
+ if (!target.empty())
+ printf("There are no save states for target '%s' (gameid '%s'):\n", i->c_str(), gameid.c_str());
}
}
// Revert to the old active domain
ConfMan.setActiveDomain(oldDomain);
+ if (!atLeastOneFound && target.empty())
+ printf("No save states could be found.\n");
+
return result;
}
@@ -810,61 +854,36 @@ static void listAudioDevices() {
}
/** Display all games in the given directory, or current directory if empty */
-static GameList getGameList(const Common::FSNode &dir) {
+static DetectedGames getGameList(const Common::FSNode &dir) {
Common::FSList files;
- //Collect all files from directory
+ // Collect all files from directory
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
printf("Path %s does not exist or is not a directory.\n", dir.getPath().c_str());
- return GameList();
+ return DetectedGames();
}
// detect Games
- GameList candidates(EngineMan.detectGames(files));
- Common::String dataPath = dir.getPath();
- // add game data path
- for (GameList::iterator v = candidates.begin(); v != candidates.end(); ++v) {
- (*v)["path"] = dataPath;
- }
- return candidates;
-}
-
-static bool addGameToConf(const GameDescriptor &gd) {
- const Common::String &domain = gd.preferredtarget();
+ DetectionResults detectionResults = EngineMan.detectGames(files);
- // If game has already been added, don't add
- if (ConfMan.hasGameDomain(domain))
- return false;
-
- // Add the name domain
- ConfMan.addGameDomain(domain);
-
- // Copy all non-empty key/value pairs into the new domain
- for (GameDescriptor::const_iterator iter = gd.begin(); iter != gd.end(); ++iter) {
- if (!iter->_value.empty() && iter->_key != "preferredtarget")
- ConfMan.set(iter->_key, iter->_value, domain);
+ if (detectionResults.foundUnknownGames()) {
+ Common::String report = detectionResults.generateUnknownGameReport(false, 80);
+ g_system->logMessage(LogMessageType::kInfo, report.c_str());
}
- // Display added game info
- printf("Game Added: \n GameID: %s\n Name: %s\n Language: %s\n Platform: %s\n",
- gd.gameid().c_str(),
- gd.description().c_str(),
- Common::getLanguageDescription(gd.language()),
- Common::getPlatformDescription(gd.platform()));
-
- return true;
+ return detectionResults.listRecognizedGames();
}
-static GameList recListGames(const Common::FSNode &dir, const Common::String &gameId, bool recursive) {
- GameList list = getGameList(dir);
+static DetectedGames recListGames(const Common::FSNode &dir, const Common::String &gameId, bool recursive) {
+ DetectedGames list = getGameList(dir);
if (recursive) {
Common::FSList files;
dir.getChildren(files, Common::FSNode::kListDirectoriesOnly);
for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
- GameList rec = recListGames(*file, gameId, recursive);
- for (GameList::const_iterator game = rec.begin(); game != rec.end(); ++game) {
- if (gameId.empty() || game->gameid().c_str() == gameId)
+ DetectedGames rec = recListGames(*file, gameId, recursive);
+ for (DetectedGames::const_iterator game = rec.begin(); game != rec.end(); ++game) {
+ if (gameId.empty() || game->gameId == gameId)
list.push_back(*game);
}
}
@@ -878,40 +897,49 @@ static Common::String detectGames(const Common::String &path, const Common::Stri
bool noPath = path.empty();
//Current directory
Common::FSNode dir(path);
- GameList candidates = recListGames(dir, gameId, recursive);
+ DetectedGames candidates = recListGames(dir, gameId, recursive);
if (candidates.empty()) {
printf("WARNING: ScummVM could not find any game in %s\n", dir.getPath().c_str());
if (noPath) {
- printf("WARNING: Consider using --path=<path> *before* --add or --detect to specify a directory\n");
+ printf("WARNING: Consider using --path=<path> to specify a directory\n");
}
if (!recursive) {
- printf("WARNING: Consider using --recursive *before* --add or --detect to search inside subdirectories\n");
+ printf("WARNING: Consider using --recursive to search inside subdirectories\n");
}
return Common::String();
}
// TODO this is not especially pretty
printf("ID Description Full Path\n");
printf("-------------- ---------------------------------------------------------- ---------------------------------------------------------\n");
- for (GameList::iterator v = candidates.begin(); v != candidates.end(); ++v) {
- printf("%-14s %-58s %s\n", v->gameid().c_str(), v->description().c_str(), (*v)["path"].c_str());
+ for (DetectedGames::const_iterator v = candidates.begin(); v != candidates.end(); ++v) {
+ printf("%-14s %-58s %s\n", v->gameId.c_str(), v->description.c_str(), v->path.c_str());
}
- return candidates[0].gameid();
+ return candidates[0].gameId;
}
static int recAddGames(const Common::FSNode &dir, const Common::String &game, bool recursive) {
int count = 0;
- GameList list = getGameList(dir);
- for (GameList::iterator v = list.begin(); v != list.end(); ++v) {
- if (v->gameid().c_str() != game && !game.empty()) {
- printf("Found %s, only adding %s per --game option, ignoring...\n", v->gameid().c_str(), game.c_str());
- } else if (!addGameToConf(*v)) {
- // TODO Is it reall the case that !addGameToConf iff already added?
- printf("Found %s, but has already been added, skipping\n", v->gameid().c_str());
+ DetectedGames list = getGameList(dir);
+ for (DetectedGames::const_iterator v = list.begin(); v != list.end(); ++v) {
+ if (v->gameId != game && !game.empty()) {
+ printf("Found %s, only adding %s per --game option, ignoring...\n", v->gameId.c_str(), game.c_str());
+ } else if (ConfMan.hasGameDomain(v->preferredTarget)) {
+ // TODO Better check for game already added?
+ printf("Found %s, but has already been added, skipping\n", v->gameId.c_str());
} else {
- printf("Found %s, adding...\n", v->gameid().c_str());
+ Common::String target = EngineMan.createTargetForGame(*v);
count++;
+
+ // Display added game info
+ printf("Game Added: \n Target: %s\n GameID: %s\n Name: %s\n Language: %s\n Platform: %s\n",
+ target.c_str(),
+ v->gameId.c_str(),
+ v->description.c_str(),
+ Common::getLanguageDescription(v->language),
+ Common::getPlatformDescription(v->platform)
+ );
}
}
@@ -970,11 +998,13 @@ static void runDetectorTest() {
continue;
}
- GameList candidates(EngineMan.detectGames(files));
+ DetectionResults detectionResults = EngineMan.detectGames(files);
+ DetectedGames candidates = detectionResults.listRecognizedGames();
+
bool gameidDiffers = false;
- GameList::iterator x;
+ DetectedGames::const_iterator x;
for (x = candidates.begin(); x != candidates.end(); ++x) {
- gameidDiffers |= (scumm_stricmp(gameid.c_str(), x->gameid().c_str()) != 0);
+ gameidDiffers |= (scumm_stricmp(gameid.c_str(), x->gameId.c_str()) != 0);
}
if (candidates.empty()) {
@@ -997,10 +1027,10 @@ static void runDetectorTest() {
for (x = candidates.begin(); x != candidates.end(); ++x) {
printf(" gameid '%s', desc '%s', language '%s', platform '%s'\n",
- x->gameid().c_str(),
- x->description().c_str(),
- Common::getLanguageCode(x->language()),
- Common::getPlatformCode(x->platform()));
+ x->gameId.c_str(),
+ x->description.c_str(),
+ Common::getLanguageDescription(x->language),
+ Common::getPlatformDescription(x->platform));
}
}
int total = domains.size();
@@ -1035,7 +1065,7 @@ void upgradeTargets() {
if (gameid.empty()) {
gameid = name;
}
- gameid.toLowercase(); // TODO: Is this paranoia? Maybe we should just assume all lowercase, always?
+ gameid.toLowercase(); // TODO: Is this paranoia? Maybe we should just assume all lowercase, always?
Common::FSNode dir(path);
Common::FSList files;
@@ -1048,24 +1078,26 @@ void upgradeTargets() {
Common::Platform plat = Common::parsePlatform(dom.getVal("platform"));
Common::String desc(dom.getVal("description"));
- GameList candidates(EngineMan.detectGames(files));
- GameDescriptor *g = 0;
+ DetectionResults detectionResults = EngineMan.detectGames(files);
+ DetectedGames candidates = detectionResults.listRecognizedGames();
+
+ DetectedGame *g = 0;
// We proceed as follows:
// * If detection failed to produce candidates, skip.
// * If there is a unique detector match, trust it.
// * If there are multiple match, run over them comparing gameid, language and platform.
// If we end up with a unique match, use it. Otherwise, skip.
- if (candidates.size() == 0) {
+ if (candidates.empty()) {
printf(" ... failed to detect game, skipping\n");
continue;
}
if (candidates.size() > 1) {
// Scan over all candidates, check if there is a unique match for gameid, language and platform
- GameList::iterator x;
+ DetectedGames::iterator x;
int matchesFound = 0;
for (x = candidates.begin(); x != candidates.end(); ++x) {
- if (x->gameid() == gameid && x->language() == lang && x->platform() == plat) {
+ if (x->gameId == gameid && x->language == lang && x->platform == plat) {
matchesFound++;
g = &(*x);
}
@@ -1083,27 +1115,27 @@ void upgradeTargets() {
// the target referred to by dom. We update several things
// Always set the gameid explicitly (in case of legacy targets)
- dom["gameid"] = g->gameid();
+ dom["gameid"] = g->gameId;
// Always set the GUI options. The user should not modify them, and engines might
// gain more features over time, so we want to keep this list up-to-date.
- if (g->contains("guioptions")) {
- printf(" -> update guioptions to '%s'\n", (*g)["guioptions"].c_str());
- dom["guioptions"] = (*g)["guioptions"];
+ if (!g->getGUIOptions().empty()) {
+ printf(" -> update guioptions to '%s'\n", g->getGUIOptions().c_str());
+ dom["guioptions"] = g->getGUIOptions();
} else if (dom.contains("guioptions")) {
dom.erase("guioptions");
}
// Update the language setting but only if none has been set yet.
- if (lang == Common::UNK_LANG && g->language() != Common::UNK_LANG) {
- printf(" -> set language to '%s'\n", Common::getLanguageCode(g->language()));
- dom["language"] = (*g)["language"];
+ if (lang == Common::UNK_LANG && g->language != Common::UNK_LANG) {
+ printf(" -> set language to '%s'\n", Common::getLanguageCode(g->language));
+ dom["language"] = Common::getLanguageCode(g->language);
}
// Update the platform setting but only if none has been set yet.
- if (plat == Common::kPlatformUnknown && g->platform() != Common::kPlatformUnknown) {
- printf(" -> set platform to '%s'\n", Common::getPlatformCode(g->platform()));
- dom["platform"] = (*g)["platform"];
+ if (plat == Common::kPlatformUnknown && g->platform != Common::kPlatformUnknown) {
+ printf(" -> set platform to '%s'\n", Common::getPlatformCode(g->platform));
+ dom["platform"] = Common::getPlatformCode(g->platform);
}
// TODO: We could also update the description. But not everybody will want that.
@@ -1112,8 +1144,8 @@ void upgradeTargets() {
// should only be updated if the user explicitly requests this.
#if 0
if (desc != g->description()) {
- printf(" -> update desc from '%s' to\n '%s' ?\n", desc.c_str(), g->description().c_str());
- dom["description"] = (*g)["description"];
+ printf(" -> update desc from '%s' to\n '%s' ?\n", desc.c_str(), g->description.c_str());
+ dom["description"] = g->description;
}
#endif
}
@@ -1149,7 +1181,7 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
listGames();
return true;
} else if (command == "list-saves") {
- err = listSaves(settings["list-saves"].c_str());
+ err = listSaves(settings["game"]);
return true;
} else if (command == "list-themes") {
listThemes();
@@ -1210,8 +1242,8 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
// domain (i.e. a target) matching this argument, or alternatively
// whether there is a gameid matching that name.
if (!command.empty()) {
- GameDescriptor gd = EngineMan.findGame(command);
- if (ConfMan.hasGameDomain(command) || !gd.gameid().empty()) {
+ PlainGameDescriptor gd = EngineMan.findGame(command);
+ if (ConfMan.hasGameDomain(command) || gd.gameId) {
bool idCameFromCommandLine = false;
// WORKAROUND: Fix for bug #1719463: "DETECTOR: Launching
diff --git a/base/main.cpp b/base/main.cpp
index f529f3ec08..be561f9766 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -128,13 +128,13 @@ static const Plugin *detectPlugin() {
printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveDomainName().c_str(), gameid.c_str());
printf(" Looking for a plugin supporting this gameid... ");
- GameDescriptor game = EngineMan.findGame(gameid, &plugin);
+ PlainGameDescriptor game = EngineMan.findGame(gameid, &plugin);
if (plugin == 0) {
printf("failed\n");
warning("%s is an invalid gameid. Use the --list-games option to list supported gameid", gameid.c_str());
} else {
- printf("%s\n Starting '%s'\n", plugin->getName(), game.description().c_str());
+ printf("%s\n Starting '%s'\n", plugin->getName(), game.description);
}
return plugin;
@@ -193,13 +193,10 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
dir.getPath().c_str()
);
- // Autoadded is set only when no path was provided and
- // the game is run from command line.
- //
- // Thus, we remove this garbage entry
- //
- // Fixes bug #1544799
- if (ConfMan.hasKey("autoadded")) {
+ // If a temporary target failed to launch, remove it from the configuration manager
+ // so it not visible in the launcher.
+ // Temporary targets are created when starting games from the command line using the game id.
+ if (ConfMan.hasKey("id_came_from_command_line")) {
ConfMan.removeGameDomain(ConfMan.getActiveDomainName().c_str());
}
@@ -210,10 +207,13 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
Common::String caption(ConfMan.get("description"));
if (caption.empty()) {
- caption = EngineMan.findGame(ConfMan.get("gameid")).description();
+ PlainGameDescriptor game = EngineMan.findGame(ConfMan.get("gameid"));
+ if (game.description) {
+ caption = game.description;
+ }
}
if (caption.empty())
- caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name
+ caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name
if (!caption.empty()) {
system.setWindowCaption(caption.c_str());
}
@@ -394,7 +394,7 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
if (settings.contains("debuglevel")) {
gDebugLevel = (int)strtol(settings["debuglevel"].c_str(), 0, 10);
printf("Debuglevel (from command line): %d\n", gDebugLevel);
- settings.erase("debuglevel"); // This option should not be passed to ConfMan.
+ settings.erase("debuglevel"); // This option should not be passed to ConfMan.
} else if (ConfMan.hasKey("debuglevel"))
gDebugLevel = ConfMan.getInt("debuglevel");
@@ -535,12 +535,12 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
g_eventRec.deinit();
#endif
- #if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES)
+#if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES)
// do our best to prevent fragmentation by unloading as soon as we can
PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false);
// reallocate the config manager to get rid of any fragmentation
ConfMan.defragment();
- #endif
+#endif
// Did an error occur ?
if (result.getCode() != Common::kNoError && result.getCode() != Common::kUserCanceled) {
@@ -549,20 +549,20 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
}
// Quit unless an error occurred, or Return to launcher was requested
- #ifndef FORCE_RTL
+#ifndef FORCE_RTL
if (result.getCode() == Common::kNoError && !g_system->getEventManager()->shouldRTL())
break;
- #endif
+#endif
// Reset RTL flag in case we want to load another engine
g_system->getEventManager()->resetRTL();
- #ifdef FORCE_RTL
+#ifdef FORCE_RTL
g_system->getEventManager()->resetQuit();
- #endif
- #ifdef ENABLE_EVENTRECORDER
+#endif
+#ifdef ENABLE_EVENTRECORDER
if (g_eventRec.checkForContinueGame()) {
continue;
}
- #endif
+#endif
// At this point, we usually return to the launcher. However, the
// game may have requested that one or more other games be "chained"
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 18755003b4..023f2f3bb3 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -22,6 +22,7 @@
#include "base/plugins.h"
+#include "common/translation.h"
#include "common/func.h"
#include "common/debug.h"
#include "common/config-manager.h"
@@ -257,7 +258,7 @@ void PluginManagerUncached::init() {
unloadAllPlugins();
_allEnginePlugins.clear();
- unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); // empty the engine plugins
+ unloadPluginsExcept(PLUGIN_TYPE_ENGINE, NULL, false); // empty the engine plugins
for (ProviderList::iterator pp = _providers.begin();
pp != _providers.end();
@@ -362,7 +363,7 @@ bool PluginManagerUncached::loadNextPlugin() {
return true;
}
}
- return false; // no more in list
+ return false; // no more in list
}
/**
@@ -457,13 +458,11 @@ DECLARE_SINGLETON(EngineManager);
* For the uncached version, we first try to find the plugin using the gameId
* and only if we can't find it there, we loop through the plugins.
**/
-GameDescriptor EngineManager::findGame(const Common::String &gameName, const Plugin **plugin) const {
- GameDescriptor result;
-
+PlainGameDescriptor EngineManager::findGame(const Common::String &gameName, const Plugin **plugin) const {
// First look for the game using the plugins in memory. This is critical
// for calls coming from inside games
- result = findGameInLoadedPlugins(gameName, plugin);
- if (!result.gameid().empty()) {
+ PlainGameDescriptor result = findGameInLoadedPlugins(gameName, plugin);
+ if (result.gameId) {
return result;
}
@@ -471,7 +470,7 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Plu
// by plugin
if (PluginMan.loadPluginFromGameId(gameName)) {
result = findGameInLoadedPlugins(gameName, plugin);
- if (!result.gameid().empty()) {
+ if (result.gameId) {
return result;
}
}
@@ -480,7 +479,7 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Plu
PluginMan.loadFirstPlugin();
do {
result = findGameInLoadedPlugins(gameName, plugin);
- if (!result.gameid().empty()) {
+ if (result.gameId) {
// Update with new plugin file name
PluginMan.updateConfigWithFileName(gameName);
break;
@@ -493,10 +492,9 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Plu
/**
* Find the game within the plugins loaded in memory
**/
-GameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin) const {
+PlainGameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin) const {
// Find the GameDescriptor for this target
const PluginList &plugins = getPlugins();
- GameDescriptor result;
if (plugin)
*plugin = 0;
@@ -504,18 +502,20 @@ GameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &game
PluginList::const_iterator iter;
for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
- result = (*iter)->get<MetaEngine>().findGame(gameName.c_str());
- if (!result.gameid().empty()) {
+ PlainGameDescriptor pgd = (*iter)->get<MetaEngine>().findGame(gameName.c_str());
+ if (pgd.gameId) {
if (plugin)
*plugin = *iter;
- return result;
+ return pgd;
}
}
- return result;
+
+ return PlainGameDescriptor::empty();
}
-GameList EngineManager::detectGames(const Common::FSList &fslist) const {
- GameList candidates;
+DetectionResults EngineManager::detectGames(const Common::FSList &fslist) const {
+ DetectedGames candidates;
+ Common::String path = fslist.begin()->getParent().getPath();
PluginList plugins;
PluginList::const_iterator iter;
PluginManager::instance().loadFirstPlugin();
@@ -524,16 +524,75 @@ GameList EngineManager::detectGames(const Common::FSList &fslist) const {
// Iterate over all known games and for each check if it might be
// the game in the presented directory.
for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
- candidates.push_back((*iter)->get<MetaEngine>().detectGames(fslist));
+ const MetaEngine &metaEngine = (*iter)->get<MetaEngine>();
+ DetectedGames engineCandidates = metaEngine.detectGames(fslist);
+
+ for (uint i = 0; i < engineCandidates.size(); i++) {
+ engineCandidates[i].engineName = metaEngine.getName();
+ engineCandidates[i].path = path;
+ candidates.push_back(engineCandidates[i]);
+ }
+
}
} while (PluginManager::instance().loadNextPlugin());
- return candidates;
+
+ return DetectionResults(candidates);
}
const PluginList &EngineManager::getPlugins() const {
return PluginManager::instance().getPlugins(PLUGIN_TYPE_ENGINE);
}
+namespace {
+
+void addStringToConf(const Common::String &key, const Common::String &value, const Common::String &domain) {
+ if (!value.empty())
+ ConfMan.set(key, value, domain);
+}
+
+} // End of anonymous namespace
+
+Common::String EngineManager::createTargetForGame(const DetectedGame &game) {
+ // The auto detector or the user made a choice.
+ // Pick a domain name which does not yet exist (after all, we
+ // are *adding* a game to the config, not replacing).
+ Common::String domain = game.preferredTarget;
+
+ assert(!domain.empty());
+ if (ConfMan.hasGameDomain(domain)) {
+ int suffixN = 1;
+ Common::String gameid(domain);
+
+ while (ConfMan.hasGameDomain(domain)) {
+ domain = gameid + Common::String::format("-%d", suffixN);
+ suffixN++;
+ }
+ }
+
+ // Add the name domain
+ ConfMan.addGameDomain(domain);
+
+ // Copy all non-empty relevant values into the new domain
+ addStringToConf("gameid", game.gameId, domain);
+ addStringToConf("description", game.description, domain);
+ addStringToConf("language", Common::getLanguageCode(game.language), domain);
+ addStringToConf("platform", Common::getPlatformCode(game.platform), domain);
+ addStringToConf("path", game.path, domain);
+ addStringToConf("extra", game.extra, domain);
+ addStringToConf("guioptions", game.getGUIOptions(), domain);
+
+ // TODO: Setting the description field here has the drawback
+ // that the user does never notice when we upgrade our descriptions.
+ // It might be nice to leave this field empty, and only set it to
+ // a value when the user edits the description string.
+ // However, at this point, that's impractical. Once we have a method
+ // to query all backends for the proper & full description of a given
+ // game target, we can change this (currently, you can only query
+ // for the generic gameid description; it's not possible to obtain
+ // a description which contains extended information like language, etc.).
+
+ return domain;
+}
// Music plugins
diff --git a/base/plugins.h b/base/plugins.h
index ce45f7102a..3ad2875906 100644
--- a/base/plugins.h
+++ b/base/plugins.h
@@ -179,9 +179,9 @@ public:
//unloadPlugin();
}
-// virtual bool isLoaded() const = 0; // TODO
- virtual bool loadPlugin() = 0; // TODO: Rename to load() ?
- virtual void unloadPlugin() = 0; // TODO: Rename to unload() ?
+// virtual bool isLoaded() const = 0; // TODO
+ virtual bool loadPlugin() = 0; // TODO: Rename to load() ?
+ virtual void unloadPlugin() = 0; // TODO: Rename to unload() ?
/**
* The following functions query information from the plugin object once
diff --git a/base/version.h b/base/version.h
index 2e362b5c72..74a0e72254 100644
--- a/base/version.h
+++ b/base/version.h
@@ -23,10 +23,10 @@
#ifndef BASE_VERSION_H
#define BASE_VERSION_H
-extern const char *gScummVMVersion; // e.g. "0.4.1"
-extern const char *gScummVMBuildDate; // e.g. "2003-06-24"
+extern const char *gScummVMVersion; // e.g. "0.4.1"
+extern const char *gScummVMBuildDate; // e.g. "2003-06-24"
extern const char *gScummVMVersionDate; // e.g. "0.4.1 (2003-06-24)"
-extern const char *gScummVMFullVersion; // e.g. "ScummVM 0.4.1 (2003-06-24)"
-extern const char *gScummVMFeatures; // e.g. "ALSA MPEG2 zLib"
+extern const char *gScummVMFullVersion; // e.g. "ScummVM 0.4.1 (2003-06-24)"
+extern const char *gScummVMFeatures; // e.g. "ALSA MPEG2 zLib"
#endif
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp
index 5c8a9a3119..617ce32d36 100644
--- a/common/EventDispatcher.cpp
+++ b/common/EventDispatcher.cpp
@@ -24,7 +24,7 @@
namespace Common {
-EventDispatcher::EventDispatcher() : _autoFreeMapper(false), _mapper(0) {
+EventDispatcher::EventDispatcher() : _autoFreeMapper(false), _mapper(nullptr) {
}
EventDispatcher::~EventDispatcher() {
@@ -41,7 +41,7 @@ EventDispatcher::~EventDispatcher() {
if (_autoFreeMapper) {
delete _mapper;
}
- _mapper = 0;
+ _mapper = nullptr;
}
void EventDispatcher::dispatch() {
diff --git a/common/algorithm.h b/common/algorithm.h
index 0d3a11b348..8384eb7089 100644
--- a/common/algorithm.h
+++ b/common/algorithm.h
@@ -141,7 +141,8 @@ In find_if(In first, In last, Pred p) {
*/
template<class In, class Op>
Op for_each(In first, In last, Op f) {
- while (first != last) f(*first++);
+ while (first != last)
+ f(*first++);
return f;
}
diff --git a/common/archive.cpp b/common/archive.cpp
index 5a339900b6..7e189654a6 100644
--- a/common/archive.cpp
+++ b/common/archive.cpp
@@ -253,7 +253,7 @@ const ArchiveMemberPtr SearchSet::getMember(const String &name) const {
SeekableReadStream *SearchSet::createReadStreamForMember(const String &name) const {
if (name.empty())
- return 0;
+ return nullptr;
ArchiveNodeList::const_iterator it = _list.begin();
for (; it != _list.end(); ++it) {
@@ -262,12 +262,12 @@ SeekableReadStream *SearchSet::createReadStreamForMember(const String &name) con
return stream;
}
- return 0;
+ return nullptr;
}
SearchManager::SearchManager() {
- clear(); // Force a reset
+ clear(); // Force a reset
}
void SearchManager::clear() {
diff --git a/common/array.h b/common/array.h
index d4dac35866..5e8ecb57ab 100644
--- a/common/array.h
+++ b/common/array.h
@@ -57,7 +57,7 @@ protected:
T *_storage;
public:
- Array() : _capacity(0), _size(0), _storage(0) {}
+ Array() : _capacity(0), _size(0), _storage(nullptr) {}
/**
* Constructs an array with `count` default-inserted instances of T. No
@@ -77,7 +77,7 @@ public:
uninitialized_fill_n(_storage, count, value);
}
- Array(const Array<T> &array) : _capacity(array._size), _size(array._size), _storage(0) {
+ Array(const Array<T> &array) : _capacity(array._size), _size(array._size), _storage(nullptr) {
if (array._storage) {
allocCapacity(_size);
uninitialized_copy(array._storage, array._storage + _size, _storage);
@@ -96,7 +96,7 @@ public:
~Array() {
freeStorage(_storage, _size);
- _storage = 0;
+ _storage = nullptr;
_capacity = _size = 0;
}
@@ -216,7 +216,7 @@ public:
void clear() {
freeStorage(_storage, _size);
- _storage = 0;
+ _storage = nullptr;
_size = 0;
_capacity = 0;
}
@@ -310,7 +310,7 @@ protected:
if (!_storage)
::error("Common::Array: failure to allocate %u bytes", capacity * (size_type)sizeof(T));
} else {
- _storage = 0;
+ _storage = nullptr;
}
}
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index fdd0c6f033..e3f0831b47 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -52,7 +52,7 @@ char const *const ConfigManager::kCloudDomain = "cloud";
#pragma mark -
-ConfigManager::ConfigManager() : _activeDomain(0) {
+ConfigManager::ConfigManager() : _activeDomain(nullptr) {
}
void ConfigManager::defragment() {
@@ -85,7 +85,7 @@ void ConfigManager::loadDefaultConfigFile() {
// Open the default config file
assert(g_system);
SeekableReadStream *stream = g_system->createConfigReadStream();
- _filename.clear(); // clear the filename to indicate that we are using the default config file
+ _filename.clear(); // clear the filename to indicate that we are using the default config file
// ... load it, if available ...
if (stream) {
@@ -321,7 +321,7 @@ void ConfigManager::flushToDisk() {
void ConfigManager::writeDomain(WriteStream &stream, const String &name, const Domain &domain) {
if (domain.empty())
- return; // Don't bother writing empty domains.
+ return; // Don't bother writing empty domains.
// WORKAROUND: Fix for bug #1972625 "ALL: On-the-fly targets are
// written to the config file": Do not save domains that came from
@@ -386,7 +386,7 @@ const ConfigManager::Domain *ConfigManager::getDomain(const String &domName) con
if (_miscDomains.contains(domName))
return &_miscDomains[domName];
- return 0;
+ return nullptr;
}
ConfigManager::Domain *ConfigManager::getDomain(const String &domName) {
@@ -410,7 +410,7 @@ ConfigManager::Domain *ConfigManager::getDomain(const String &domName) {
if (_miscDomains.contains(domName))
return &_miscDomains[domName];
- return 0;
+ return nullptr;
}
@@ -620,7 +620,7 @@ void ConfigManager::registerDefault(const String &key, bool value) {
void ConfigManager::setActiveDomain(const String &domName) {
if (domName.empty()) {
- _activeDomain = 0;
+ _activeDomain = nullptr;
} else {
assert(isValidDomainName(domName));
_activeDomain = &_gameDomains[domName];
@@ -654,7 +654,7 @@ void ConfigManager::removeGameDomain(const String &domName) {
assert(isValidDomainName(domName));
if (domName == _activeDomainName) {
_activeDomainName.clear();
- _activeDomain = 0;
+ _activeDomain = nullptr;
}
_gameDomains.erase(domName);
}
diff --git a/common/config-manager.h b/common/config-manager.h
index 669faaaf88..58f4373dde 100644
--- a/common/config-manager.h
+++ b/common/config-manager.h
@@ -171,7 +171,7 @@ public:
DomainMap::iterator beginGameDomains() { return _gameDomains.begin(); }
DomainMap::iterator endGameDomains() { return _gameDomains.end(); }
- static void defragment(); // move in memory to reduce fragmentation
+ static void defragment(); // move in memory to reduce fragmentation
void copyFrom(ConfigManager &source);
private:
@@ -185,7 +185,7 @@ private:
Domain _transientDomain;
DomainMap _gameDomains;
- DomainMap _miscDomains; // Any other domains
+ DomainMap _miscDomains; // Any other domains
Domain _appDomain;
Domain _defaultsDomain;
diff --git a/common/coroutines.cpp b/common/coroutines.cpp
index 248777febd..0e7a1098cf 100644
--- a/common/coroutines.cpp
+++ b/common/coroutines.cpp
@@ -31,7 +31,7 @@
namespace Common {
/** Helper null context instance */
-CoroContext nullContext = NULL;
+CoroContext nullContext = nullptr;
DECLARE_SINGLETON(CoroutineScheduler);
@@ -73,7 +73,7 @@ static void displayCoroStats() {
#endif
CoroBaseContext::CoroBaseContext(const char *func)
- : _line(0), _sleep(0), _subctx(0) {
+ : _line(0), _sleep(0), _subctx(nullptr) {
#ifdef COROUTINE_DEBUG
_funcName = func;
changeCoroStats(_funcName, +1);
@@ -95,9 +95,9 @@ CoroBaseContext::~CoroBaseContext() {
//--------------------- Scheduler Class ------------------------
CoroutineScheduler::CoroutineScheduler() {
- processList = NULL;
- pFreeProcesses = NULL;
- pCurrent = NULL;
+ processList = nullptr;
+ pFreeProcesses = nullptr;
+ pCurrent = nullptr;
#ifdef DEBUG
// diagnostic process counters
@@ -105,12 +105,12 @@ CoroutineScheduler::CoroutineScheduler() {
maxProcs = 0;
#endif
- pRCfunction = NULL;
+ pRCfunction = nullptr;
pidCounter = 0;
active = new PROCESS;
- active->pPrevious = NULL;
- active->pNext = NULL;
+ active->pPrevious = nullptr;
+ active->pNext = nullptr;
reset();
}
@@ -118,17 +118,17 @@ CoroutineScheduler::CoroutineScheduler() {
CoroutineScheduler::~CoroutineScheduler() {
// Kill all running processes (i.e. free memory allocated for their state).
PROCESS *pProc = active->pNext;
- while (pProc != NULL) {
+ while (pProc != nullptr) {
delete pProc->state;
- pProc->state = 0;
+ pProc->state = nullptr;
pProc = pProc->pNext;
}
free(processList);
- processList = NULL;
+ processList = nullptr;
delete active;
- active = 0;
+ active = nullptr;
// Clear the event list
Common::List<EVENT *>::iterator i;
@@ -142,12 +142,12 @@ void CoroutineScheduler::reset() {
numProcs = 0;
#endif
- if (processList == NULL) {
+ if (processList == nullptr) {
// first time - allocate memory for process list
processList = (PROCESS *)calloc(CORO_MAX_PROCESSES, sizeof(PROCESS));
// make sure memory allocated
- if (processList == NULL) {
+ if (processList == nullptr) {
error("Cannot allocate memory for process data");
}
@@ -157,22 +157,22 @@ void CoroutineScheduler::reset() {
// Kill all running processes (i.e. free memory allocated for their state).
PROCESS *pProc = active->pNext;
- while (pProc != NULL) {
+ while (pProc != nullptr) {
delete pProc->state;
- pProc->state = 0;
+ pProc->state = nullptr;
Common::fill(&pProc->pidWaiting[0], &pProc->pidWaiting[CORO_MAX_PID_WAITING], 0);
pProc = pProc->pNext;
}
// no active processes
- pCurrent = active->pNext = NULL;
+ pCurrent = active->pNext = nullptr;
// place first process on free list
pFreeProcesses = processList;
// link all other processes after first
for (int i = 1; i <= CORO_NUM_PROCESS; i++) {
- processList[i - 1].pNext = (i == CORO_NUM_PROCESS) ? NULL : processList + i;
+ processList[i - 1].pNext = (i == CORO_NUM_PROCESS) ? nullptr : processList + i;
processList[i - 1].pPrevious = (i == 1) ? active : processList + (i - 2);
}
}
@@ -223,7 +223,7 @@ void CoroutineScheduler::schedule() {
// start dispatching active process list
PROCESS *pNext;
PROCESS *pProc = active->pNext;
- while (pProc != NULL) {
+ while (pProc != nullptr) {
pNext = pProc->pNext;
if (--pProc->sleepTime <= 0) {
@@ -241,7 +241,7 @@ void CoroutineScheduler::schedule() {
// pCurrent may have been changed
pNext = pCurrent->pNext;
- pCurrent = NULL;
+ pCurrent = nullptr;
}
pProc = pNext;
@@ -284,16 +284,16 @@ void CoroutineScheduler::reschedule(PPROCESS pReSchedProc) {
// Find the last process in the list.
// But if the target process is down the list from here, do nothing
- for (pEnd = pCurrent; pEnd->pNext != NULL; pEnd = pEnd->pNext) {
+ for (pEnd = pCurrent; pEnd->pNext != nullptr; pEnd = pEnd->pNext) {
if (pEnd->pNext == pReSchedProc)
return;
}
- assert(pEnd->pNext == NULL);
+ assert(pEnd->pNext == nullptr);
// Could be in the middle of a KillProc()!
// Dying process was last and this process was penultimate
- if (pReSchedProc->pNext == NULL)
+ if (pReSchedProc->pNext == nullptr)
return;
// If we're moving the current process, move it back by one, so that the next
@@ -306,7 +306,7 @@ void CoroutineScheduler::reschedule(PPROCESS pReSchedProc) {
pReSchedProc->pNext->pPrevious = pReSchedProc->pPrevious;
pEnd->pNext = pReSchedProc;
pReSchedProc->pPrevious = pEnd;
- pReSchedProc->pNext = NULL;
+ pReSchedProc->pNext = nullptr;
}
void CoroutineScheduler::giveWay(PPROCESS pReSchedProc) {
@@ -324,9 +324,9 @@ void CoroutineScheduler::giveWay(PPROCESS pReSchedProc) {
PPROCESS pEnd;
// Find the last process in the list.
- for (pEnd = pCurrent; pEnd->pNext != NULL; pEnd = pEnd->pNext)
+ for (pEnd = pCurrent; pEnd->pNext != nullptr; pEnd = pEnd->pNext)
;
- assert(pEnd->pNext == NULL);
+ assert(pEnd->pNext == nullptr);
// If we're moving the current process, move it back by one, so that the next
@@ -339,7 +339,7 @@ void CoroutineScheduler::giveWay(PPROCESS pReSchedProc) {
pReSchedProc->pNext->pPrevious = pReSchedProc->pPrevious;
pEnd->pNext = pReSchedProc;
pReSchedProc->pPrevious = pEnd;
- pReSchedProc->pNext = NULL;
+ pReSchedProc->pNext = nullptr;
}
void CoroutineScheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *expired) {
@@ -366,11 +366,11 @@ void CoroutineScheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duratio
while (g_system->getMillis() <= _ctx->endTime) {
// Check to see if a process or event with the given Id exists
_ctx->pProcess = getProcess(pid);
- _ctx->pEvent = !_ctx->pProcess ? getEvent(pid) : NULL;
+ _ctx->pEvent = !_ctx->pProcess ? getEvent(pid) : nullptr;
// If there's no active process or event, presume it's a process that's finished,
// so the waiting can immediately exit
- if ((_ctx->pProcess == NULL) && (_ctx->pEvent == NULL)) {
+ if ((_ctx->pProcess == nullptr) && (_ctx->pEvent == nullptr)) {
if (expired)
*expired = false;
break;
@@ -378,7 +378,7 @@ void CoroutineScheduler::waitForSingleObject(CORO_PARAM, int pid, uint32 duratio
// If a process was found, don't go into the if statement, and keep waiting.
// Likewise if it's an event that's not yet signalled
- if ((_ctx->pEvent != NULL) && _ctx->pEvent->signalled) {
+ if ((_ctx->pEvent != nullptr) && _ctx->pEvent->signalled) {
// Unless the event is flagged for manual reset, reset it now
if (!_ctx->pEvent->manualReset)
_ctx->pEvent->signalled = false;
@@ -429,7 +429,7 @@ void CoroutineScheduler::waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *
for (_ctx->i = 0; _ctx->i < nCount; ++_ctx->i) {
_ctx->pProcess = getProcess(pidList[_ctx->i]);
- _ctx->pEvent = !_ctx->pProcess ? getEvent(pidList[_ctx->i]) : NULL;
+ _ctx->pEvent = !_ctx->pProcess ? getEvent(pidList[_ctx->i]) : nullptr;
// Determine the signalled state
_ctx->pidSignalled = (_ctx->pProcess) || !_ctx->pEvent ? false : _ctx->pEvent->signalled;
@@ -495,7 +495,7 @@ PROCESS *CoroutineScheduler::createProcess(uint32 pid, CORO_ADDR coroAddr, const
pProc = pFreeProcesses;
// trap no free process
- assert(pProc != NULL); // Out of processes
+ assert(pProc != nullptr); // Out of processes
#ifdef DEBUG
// one more process in use
@@ -506,9 +506,9 @@ PROCESS *CoroutineScheduler::createProcess(uint32 pid, CORO_ADDR coroAddr, const
// get link to next free process
pFreeProcesses = pProc->pNext;
if (pFreeProcesses)
- pFreeProcesses->pPrevious = NULL;
+ pFreeProcesses->pPrevious = nullptr;
- if (pCurrent != NULL) {
+ if (pCurrent != nullptr) {
// place new process before the next active process
pProc->pNext = pCurrent->pNext;
if (pProc->pNext)
@@ -532,7 +532,7 @@ PROCESS *CoroutineScheduler::createProcess(uint32 pid, CORO_ADDR coroAddr, const
pProc->coroAddr = coroAddr;
// clear coroutine state
- pProc->state = 0;
+ pProc->state = nullptr;
// wake process up as soon as possible
pProc->sleepTime = 1;
@@ -575,11 +575,11 @@ void CoroutineScheduler::killProcess(PROCESS *pKillProc) {
#endif
// Free process' resources
- if (pRCfunction != NULL)
+ if (pRCfunction != nullptr)
(pRCfunction)(pKillProc);
delete pKillProc->state;
- pKillProc->state = 0;
+ pKillProc->state = nullptr;
// Take the process out of the active chain list
pKillProc->pPrevious->pNext = pKillProc->pNext;
@@ -590,7 +590,7 @@ void CoroutineScheduler::killProcess(PROCESS *pKillProc) {
pKillProc->pNext = pFreeProcesses;
if (pFreeProcesses)
pKillProc->pNext->pPrevious = pKillProc;
- pKillProc->pPrevious = NULL;
+ pKillProc->pPrevious = nullptr;
// make pKillProc the first free process
pFreeProcesses = pKillProc;
@@ -614,7 +614,7 @@ int CoroutineScheduler::killMatchingProcess(uint32 pidKill, int pidMask) {
int numKilled = 0;
PROCESS *pProc, *pPrev; // process list pointers
- for (pProc = active->pNext, pPrev = active; pProc != NULL; pPrev = pProc, pProc = pProc->pNext) {
+ for (pProc = active->pNext, pPrev = active; pProc != nullptr; pPrev = pProc, pProc = pProc->pNext) {
if ((pProc->pid & (uint32)pidMask) == pidKill) {
// found a matching process
@@ -624,11 +624,11 @@ int CoroutineScheduler::killMatchingProcess(uint32 pidKill, int pidMask) {
numKilled++;
// Free the process' resources
- if (pRCfunction != NULL)
+ if (pRCfunction != nullptr)
(pRCfunction)(pProc);
delete pProc->state;
- pProc->state = 0;
+ pProc->state = nullptr;
// make prev point to next to unlink pProc
pPrev->pNext = pProc->pNext;
@@ -637,7 +637,7 @@ int CoroutineScheduler::killMatchingProcess(uint32 pidKill, int pidMask) {
// link first free process after pProc
pProc->pNext = pFreeProcesses;
- pProc->pPrevious = NULL;
+ pProc->pPrevious = nullptr;
pFreeProcesses->pPrevious = pProc;
// make pProc the first free process
@@ -665,7 +665,7 @@ void CoroutineScheduler::setResourceCallback(VFPTRPP pFunc) {
PROCESS *CoroutineScheduler::getProcess(uint32 pid) {
PROCESS *pProc = active->pNext;
- while ((pProc != NULL) && (pProc->pid != pid))
+ while ((pProc != nullptr) && (pProc->pid != pid))
pProc = pProc->pNext;
return pProc;
@@ -679,7 +679,7 @@ EVENT *CoroutineScheduler::getEvent(uint32 pid) {
return evt;
}
- return NULL;
+ return nullptr;
}
diff --git a/common/coroutines.h b/common/coroutines.h
index 4fef1a0d4e..5e3fb4cf0e 100644
--- a/common/coroutines.h
+++ b/common/coroutines.h
@@ -97,7 +97,7 @@ public:
~CoroContextHolder() {
if (_ctx && _ctx->_sleep == 0) {
delete _ctx;
- _ctx = 0;
+ _ctx = nullptr;
}
}
};
@@ -409,14 +409,14 @@ public:
* If the specified process has already run on this tick, make it run
* again on the current tick.
*/
- void reschedule(PPROCESS pReSchedProc = NULL);
+ void reschedule(PPROCESS pReSchedProc = nullptr);
/**
* Moves the specified process to the end of the dispatch queue
* allowing it to run again within the current game cycle.
* @param pGiveProc Which process
*/
- void giveWay(PPROCESS pReSchedProc = NULL);
+ void giveWay(PPROCESS pReSchedProc = nullptr);
/**
* Continously makes a given process wait for another process to finish or event to signal.
@@ -425,7 +425,7 @@ public:
* @param duration Duration in milliseconds
* @param expired If specified, set to true if delay period expired
*/
- void waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *expired = NULL);
+ void waitForSingleObject(CORO_PARAM, int pid, uint32 duration, bool *expired = nullptr);
/**
* Continously makes a given process wait for given prcesses to finished or events to be set
@@ -437,7 +437,7 @@ public:
* @param expired Set to true if delay period expired
*/
void waitForMultipleObjects(CORO_PARAM, int nCount, uint32 *pidList, bool bWaitAll,
- uint32 duration, bool *expired = NULL);
+ uint32 duration, bool *expired = nullptr);
/**
* Make the active process sleep for the given duration in milliseconds
diff --git a/common/dcl.cpp b/common/dcl.cpp
index 75a533aa9d..7c2fc2ce80 100644
--- a/common/dcl.cpp
+++ b/common/dcl.cpp
@@ -98,7 +98,7 @@ uint32 DecompressorDCL::getBitsLSB(int n) {
// Fetching more data to buffer if needed
if (_nBits < n)
fetchBitsLSB();
- uint32 ret = (_dwBits & ~((~0) << n));
+ uint32 ret = (_dwBits & ~(~0UL << n));
_dwBits >>= n;
_nBits -= n;
return ret;
diff --git a/common/dct.cpp b/common/dct.cpp
index 27e0c0bf41..9d551b95ba 100644
--- a/common/dct.cpp
+++ b/common/dct.cpp
@@ -30,7 +30,7 @@
namespace Common {
-DCT::DCT(int bits, TransformType trans) : _bits(bits), _cos(_bits + 2), _trans(trans), _rdft(0) {
+DCT::DCT(int bits, TransformType trans) : _bits(bits), _cos(_bits + 2), _trans(trans), _rdft(nullptr) {
int n = 1 << _bits;
_tCos = _cos.getTable();
diff --git a/common/fft.cpp b/common/fft.cpp
index 27a04abb6a..a750792047 100644
--- a/common/fft.cpp
+++ b/common/fft.cpp
@@ -51,7 +51,7 @@ FFT::FFT(int bits, int inverse) : _bits(bits), _inverse(inverse) {
if (i+4 <= _bits)
_cosTables[i] = new Common::CosineTable(i+4);
else
- _cosTables[i] = 0;
+ _cosTables[i] = nullptr;
}
}
diff --git a/common/file.cpp b/common/file.cpp
index 9797bcaa69..5fc4f9012b 100644
--- a/common/file.cpp
+++ b/common/file.cpp
@@ -31,7 +31,7 @@
namespace Common {
File::File()
- : _handle(0) {
+ : _handle(nullptr) {
}
File::~File() {
@@ -46,7 +46,7 @@ bool File::open(const String &filename, Archive &archive) {
assert(!filename.empty());
assert(!_handle);
- SeekableReadStream *stream = 0;
+ SeekableReadStream *stream = nullptr;
if ((stream = archive.createReadStreamForMember(filename))) {
debug(8, "Opening hashed: %s", filename.c_str());
@@ -83,7 +83,7 @@ bool File::open(SeekableReadStream *stream, const String &name) {
} else {
debug(2, "File::open: opening '%s' failed", name.c_str());
}
- return _handle != NULL;
+ return _handle != nullptr;
}
@@ -101,11 +101,11 @@ bool File::exists(const String &filename) {
void File::close() {
delete _handle;
- _handle = NULL;
+ _handle = nullptr;
}
bool File::isOpen() const {
- return _handle != NULL;
+ return _handle != nullptr;
}
bool File::err() const {
@@ -144,7 +144,7 @@ uint32 File::read(void *ptr, uint32 len) {
}
-DumpFile::DumpFile() : _handle(0) {
+DumpFile::DumpFile() : _handle(nullptr) {
}
DumpFile::~DumpFile() {
@@ -182,19 +182,19 @@ bool DumpFile::open(const FSNode &node) {
_handle = node.createWriteStream();
- if (_handle == NULL)
+ if (_handle == nullptr)
debug(2, "File %s not found", node.getName().c_str());
- return _handle != NULL;
+ return _handle != nullptr;
}
void DumpFile::close() {
delete _handle;
- _handle = NULL;
+ _handle = nullptr;
}
bool DumpFile::isOpen() const {
- return _handle != NULL;
+ return _handle != nullptr;
}
bool DumpFile::err() const {
diff --git a/common/fs.cpp b/common/fs.cpp
index 3a7026b1cc..d93270ff0d 100644
--- a/common/fs.cpp
+++ b/common/fs.cpp
@@ -37,7 +37,7 @@ FSNode::FSNode(AbstractFSNode *realNode)
FSNode::FSNode(const String &p) {
assert(g_system);
FilesystemFactory *factory = g_system->getFilesystemFactory();
- AbstractFSNode *tmp = 0;
+ AbstractFSNode *tmp = nullptr;
if (p.empty() || p == ".")
tmp = factory->makeCurrentDirectoryFileNode();
@@ -62,7 +62,7 @@ bool FSNode::exists() const {
FSNode FSNode::getChild(const String &n) const {
// If this node is invalid or not a directory, return an invalid node
- if (_realNode == 0 || !_realNode->isDirectory())
+ if (_realNode == nullptr || !_realNode->isDirectory())
return FSNode();
AbstractFSNode *node = _realNode->getChild(n);
@@ -97,11 +97,11 @@ String FSNode::getName() const {
}
FSNode FSNode::getParent() const {
- if (_realNode == 0)
+ if (_realNode == nullptr)
return *this;
AbstractFSNode *node = _realNode->getParent();
- if (node == 0) {
+ if (node == nullptr) {
return *this;
} else {
return FSNode(node);
@@ -126,27 +126,27 @@ bool FSNode::isWritable() const {
}
SeekableReadStream *FSNode::createReadStream() const {
- if (_realNode == 0)
- return 0;
+ if (_realNode == nullptr)
+ return nullptr;
if (!_realNode->exists()) {
warning("FSNode::createReadStream: '%s' does not exist", getName().c_str());
- return 0;
+ return nullptr;
} else if (_realNode->isDirectory()) {
warning("FSNode::createReadStream: '%s' is a directory", getName().c_str());
- return 0;
+ return nullptr;
}
return _realNode->createReadStream();
}
WriteStream *FSNode::createWriteStream() const {
- if (_realNode == 0)
- return 0;
+ if (_realNode == nullptr)
+ return nullptr;
if (_realNode->isDirectory()) {
warning("FSNode::createWriteStream: '%s' is a directory", getName().c_str());
- return 0;
+ return nullptr;
}
return _realNode->createWriteStream();
@@ -195,7 +195,7 @@ FSNode *FSDirectory::lookupCache(NodeCache &cache, const String &name) const {
return &cache[name];
}
- return 0;
+ return nullptr;
}
bool FSDirectory::hasFile(const String &name) const {
@@ -225,11 +225,11 @@ const ArchiveMemberPtr FSDirectory::getMember(const String &name) const {
SeekableReadStream *FSDirectory::createReadStreamForMember(const String &name) const {
if (name.empty() || !_node.isDirectory())
- return 0;
+ return nullptr;
FSNode *node = lookupCache(_fileCache, name);
if (!node)
- return 0;
+ return nullptr;
SeekableReadStream *stream = node->createReadStream();
if (!stream)
warning("FSDirectory::createReadStreamForMember: Can't create stream for file '%s'", name.c_str());
@@ -243,11 +243,11 @@ FSDirectory *FSDirectory::getSubDirectory(const String &name, int depth, bool fl
FSDirectory *FSDirectory::getSubDirectory(const String &prefix, const String &name, int depth, bool flat) {
if (name.empty() || !_node.isDirectory())
- return 0;
+ return nullptr;
FSNode *node = lookupCache(_subDirCache, name);
if (!node)
- return 0;
+ return nullptr;
return new FSDirectory(prefix, *node, depth, flat);
}
diff --git a/common/fs.h b/common/fs.h
index f516bf7a9c..ed287cc17a 100644
--- a/common/fs.h
+++ b/common/fs.h
@@ -269,7 +269,7 @@ public:
class FSDirectory : public Archive {
FSNode _node;
- String _prefix; // string that is prepended to each cache item key
+ String _prefix; // string that is prepended to each cache item key
void setPrefix(const String &prefix);
// Caches are case insensitive, clashes are dealt with when creating
diff --git a/common/gui_options.cpp b/common/gui_options.cpp
index 6f340bf88f..06b6c20a61 100644
--- a/common/gui_options.cpp
+++ b/common/gui_options.cpp
@@ -86,7 +86,7 @@ const struct GameOpt {
{ GUIO_GAMEOPTIONS11, "gameOptionB" },
{ GUIO_GAMEOPTIONS12, "gameOptionC" },
- { GUIO_NONE, 0 }
+ { GUIO_NONE, nullptr }
};
bool checkGameGUIOption(const String &option, const String &str) {
diff --git a/common/hash-str.h b/common/hash-str.h
index 82af6cca93..fcd41ab6a7 100644
--- a/common/hash-str.h
+++ b/common/hash-str.h
@@ -29,11 +29,10 @@
namespace Common {
uint hashit(const char *str);
-uint hashit_lower(const char *str); // Generate a hash based on the lowercase version of the string
+uint hashit_lower(const char *str); // Generate a hash based on the lowercase version of the string
inline uint hashit(const String &str) { return hashit(str.c_str()); }
inline uint hashit_lower(const String &str) { return hashit_lower(str.c_str()); }
-
// FIXME: The following functors obviously are not consistently named
struct CaseSensitiveString_EqualTo {
@@ -53,8 +52,6 @@ struct IgnoreCase_Hash {
uint operator()(const String& x) const { return hashit_lower(x.c_str()); }
};
-
-
// Specalization of the Hash functor for String objects.
// We do case sensitve hashing here, because that is what
// the default EqualTo is compatible with. If one wants to use
@@ -78,9 +75,6 @@ struct Hash<const char *> {
// String map -- by default case insensitive
typedef HashMap<String, String, IgnoreCase_Hash, IgnoreCase_EqualTo> StringMap;
-
-
} // End of namespace Common
-
#endif
diff --git a/common/hashmap.cpp b/common/hashmap.cpp
index 99840993ce..e9eac9fc94 100644
--- a/common/hashmap.cpp
+++ b/common/hashmap.cpp
@@ -95,10 +95,10 @@ void updateHashCollisionStats(int collisions, int dummyHits, int lookups, int ar
g_size / g_totalHashmaps, g_max_size,
g_capacity / g_totalHashmaps, g_max_capacity);
debug(" %d less than %d; %d less than %d; %d less than %d; %d less than %d",
- g_stats[0], 2*8/3,
- g_stats[1],2*16/3,
- g_stats[2],2*32/3,
- g_stats[3],2*64/3);
+ g_stats[0], 2 * 8 / 3,
+ g_stats[1], 2 * 16 / 3,
+ g_stats[2], 2 * 32 / 3,
+ g_stats[3], 2 * 64 / 3);
// TODO:
// * Should record the maximal size of the map during its lifetime, not that at its death
diff --git a/common/hashmap.h b/common/hashmap.h
index d7ba100571..1f93b68455 100644
--- a/common/hashmap.h
+++ b/common/hashmap.h
@@ -178,16 +178,16 @@ private:
IteratorImpl(size_type idx, hashmap_t *hashmap) : _idx(idx), _hashmap(hashmap) {}
NodeType *deref() const {
- assert(_hashmap != 0);
+ assert(_hashmap != nullptr);
assert(_idx <= _hashmap->_mask);
Node *node = _hashmap->_storage[_idx];
- assert(node != 0);
+ assert(node != nullptr);
assert(node != HASHMAP_DUMMY_NODE);
return node;
}
public:
- IteratorImpl() : _idx(0), _hashmap(0) {}
+ IteratorImpl() : _idx(0), _hashmap(nullptr) {}
template<class T>
IteratorImpl(const IteratorImpl<T> &c) : _idx(c._idx), _hashmap(c._hashmap) {}
@@ -201,7 +201,7 @@ private:
assert(_hashmap);
do {
_idx++;
- } while (_idx <= _hashmap->_mask && (_hashmap->_storage[_idx] == 0 || _hashmap->_storage[_idx] == HASHMAP_DUMMY_NODE));
+ } while (_idx <= _hashmap->_mask && (_hashmap->_storage[_idx] == nullptr || _hashmap->_storage[_idx] == HASHMAP_DUMMY_NODE));
if (_idx > _hashmap->_mask)
_idx = (size_type)-1;
@@ -315,7 +315,7 @@ HashMap<Key, Val, HashFunc, EqualFunc>::HashMap()
#endif
_mask = HASHMAP_MIN_CAPACITY - 1;
_storage = new Node *[HASHMAP_MIN_CAPACITY];
- assert(_storage != NULL);
+ assert(_storage != nullptr);
memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *));
_size = 0;
@@ -355,7 +355,7 @@ HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() {
delete[] _storage;
#ifdef DEBUG_HASH_COLLISIONS
extern void updateHashCollisionStats(int, int, int, int, int);
- updateHashCollisionStats(_collisions, _dummyHits, _lookups, _mask+1, _size);
+ updateHashCollisionStats(_collisions, _dummyHits, _lookups, _mask + 1, _size);
#endif
}
@@ -369,9 +369,9 @@ HashMap<Key, Val, HashFunc, EqualFunc>::~HashMap() {
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) {
_mask = map._mask;
- _storage = new Node *[_mask+1];
- assert(_storage != NULL);
- memset(_storage, 0, (_mask+1) * sizeof(Node *));
+ _storage = new Node *[_mask + 1];
+ assert(_storage != nullptr);
+ memset(_storage, 0, (_mask + 1) * sizeof(Node *));
// Simply clone the map given to us, one by one.
_size = 0;
@@ -380,7 +380,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::assign(const HM_t &map) {
if (map._storage[ctr] == HASHMAP_DUMMY_NODE) {
_storage[ctr] = HASHMAP_DUMMY_NODE;
_deleted++;
- } else if (map._storage[ctr] != NULL) {
+ } else if (map._storage[ctr] != nullptr) {
_storage[ctr] = allocNode(map._storage[ctr]->_key);
_storage[ctr]->_value = map._storage[ctr]->_value;
_size++;
@@ -396,7 +396,7 @@ template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) {
for (size_type ctr = 0; ctr <= _mask; ++ctr) {
freeNode(_storage[ctr]);
- _storage[ctr] = NULL;
+ _storage[ctr] = nullptr;
}
#ifdef USE_HASHMAP_MEMORY_POOL
@@ -406,9 +406,9 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) {
if (shrinkArray && _mask >= HASHMAP_MIN_CAPACITY) {
delete[] _storage;
- _mask = HASHMAP_MIN_CAPACITY;
+ _mask = HASHMAP_MIN_CAPACITY - 1;
_storage = new Node *[HASHMAP_MIN_CAPACITY];
- assert(_storage != NULL);
+ assert(_storage != nullptr);
memset(_storage, 0, HASHMAP_MIN_CAPACITY * sizeof(Node *));
}
@@ -418,7 +418,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::clear(bool shrinkArray) {
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(size_type newCapacity) {
- assert(newCapacity > _mask+1);
+ assert(newCapacity > _mask + 1);
#ifndef NDEBUG
const size_type old_size = _size;
@@ -431,12 +431,12 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(size_type newCapacity
_deleted = 0;
_mask = newCapacity - 1;
_storage = new Node *[newCapacity];
- assert(_storage != NULL);
+ assert(_storage != nullptr);
memset(_storage, 0, newCapacity * sizeof(Node *));
// rehash all the old elements
for (size_type ctr = 0; ctr <= old_mask; ++ctr) {
- if (old_storage[ctr] == NULL || old_storage[ctr] == HASHMAP_DUMMY_NODE)
+ if (old_storage[ctr] == nullptr || old_storage[ctr] == HASHMAP_DUMMY_NODE)
continue;
// Insert the element from the old table into the new table.
@@ -445,7 +445,7 @@ void HashMap<Key, Val, HashFunc, EqualFunc>::expandStorage(size_type newCapacity
// don't have to call _equal().
const size_type hash = _hash(old_storage[ctr]->_key);
size_type idx = hash & _mask;
- for (size_type perturb = hash; _storage[idx] != NULL && _storage[idx] != HASHMAP_DUMMY_NODE; perturb >>= HASHMAP_PERTURB_SHIFT) {
+ for (size_type perturb = hash; _storage[idx] != nullptr && _storage[idx] != HASHMAP_DUMMY_NODE; perturb >>= HASHMAP_PERTURB_SHIFT) {
idx = (5 * idx + perturb + 1) & _mask;
}
@@ -467,7 +467,7 @@ typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, Has
const size_type hash = _hash(key);
size_type ctr = hash & _mask;
for (size_type perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
- if (_storage[ctr] == NULL)
+ if (_storage[ctr] == nullptr)
break;
if (_storage[ctr] == HASHMAP_DUMMY_NODE) {
#ifdef DEBUG_HASH_COLLISIONS
@@ -487,7 +487,7 @@ typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, Has
_lookups++;
debug("collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d",
_collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups),
- (const void *)this, _mask+1, _size);
+ (const void *)this, _mask + 1, _size);
#endif
return ctr;
@@ -501,7 +501,7 @@ typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, Has
size_type first_free = NONE_FOUND;
bool found = false;
for (size_type perturb = hash; ; perturb >>= HASHMAP_PERTURB_SHIFT) {
- if (_storage[ctr] == NULL)
+ if (_storage[ctr] == nullptr)
break;
if (_storage[ctr] == HASHMAP_DUMMY_NODE) {
#ifdef DEBUG_HASH_COLLISIONS
@@ -525,7 +525,7 @@ typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, Has
_lookups++;
debug("collisions %d, dummies hit %d, lookups %d, ratio %f in HashMap %p; size %d num elements %d",
_collisions, _dummyHits, _lookups, ((double) _collisions / (double)_lookups),
- (const void *)this, _mask+1, _size);
+ (const void *)this, _mask + 1, _size);
#endif
if (!found && first_free != _mask + 1)
@@ -535,7 +535,7 @@ typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, Has
if (_storage[ctr])
_deleted--;
_storage[ctr] = allocNode(key);
- assert(_storage[ctr] != NULL);
+ assert(_storage[ctr] != nullptr);
_size++;
// Keep the load factor below a certain threshold.
@@ -546,7 +546,7 @@ typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, Has
capacity = capacity < 500 ? (capacity * 4) : (capacity * 2);
expandStorage(capacity);
ctr = lookup(key);
- assert(_storage[ctr] != NULL);
+ assert(_storage[ctr] != nullptr);
}
}
@@ -557,7 +557,7 @@ typename HashMap<Key, Val, HashFunc, EqualFunc>::size_type HashMap<Key, Val, Has
template<class Key, class Val, class HashFunc, class EqualFunc>
bool HashMap<Key, Val, HashFunc, EqualFunc>::contains(const Key &key) const {
size_type ctr = lookup(key);
- return (_storage[ctr] != NULL);
+ return (_storage[ctr] != nullptr);
}
template<class Key, class Val, class HashFunc, class EqualFunc>
@@ -573,7 +573,7 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::operator[](const Key &key) co
template<class Key, class Val, class HashFunc, class EqualFunc>
Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) {
size_type ctr = lookupAndCreateIfMissing(key);
- assert(_storage[ctr] != NULL);
+ assert(_storage[ctr] != nullptr);
return _storage[ctr]->_value;
}
@@ -585,7 +585,7 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key) const
template<class Key, class Val, class HashFunc, class EqualFunc>
const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key, const Val &defaultVal) const {
size_type ctr = lookup(key);
- if (_storage[ctr] != NULL)
+ if (_storage[ctr] != nullptr)
return _storage[ctr]->_value;
else
return defaultVal;
@@ -594,7 +594,7 @@ const Val &HashMap<Key, Val, HashFunc, EqualFunc>::getVal(const Key &key, const
template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::setVal(const Key &key, const Val &val) {
size_type ctr = lookupAndCreateIfMissing(key);
- assert(_storage[ctr] != NULL);
+ assert(_storage[ctr] != nullptr);
_storage[ctr]->_value = val;
}
@@ -619,7 +619,7 @@ template<class Key, class Val, class HashFunc, class EqualFunc>
void HashMap<Key, Val, HashFunc, EqualFunc>::erase(const Key &key) {
size_type ctr = lookup(key);
- if (_storage[ctr] == NULL)
+ if (_storage[ctr] == nullptr)
return;
// If we remove a key, we replace it with a dummy node.
diff --git a/common/huffman.h b/common/huffman.h
index f703d078dc..b4de5ab483 100644
--- a/common/huffman.h
+++ b/common/huffman.h
@@ -47,11 +47,11 @@ public:
* @param lengths Lengths of the individual codes.
* @param symbols The symbols. If 0, assume they are identical to the code indices.
*/
- Huffman(uint8 maxLength, uint32 codeCount, const uint32 *codes, const uint8 *lengths, const uint32 *symbols = 0);
+ Huffman(uint8 maxLength, uint32 codeCount, const uint32 *codes, const uint8 *lengths, const uint32 *symbols = nullptr);
~Huffman();
/** Modify the codes' symbols. */
- void setSymbols(const uint32 *symbols = 0);
+ void setSymbols(const uint32 *symbols = nullptr);
/** Return the next symbol in the bitstream. */
template<class BITSTREAM>
diff --git a/common/iff_container.cpp b/common/iff_container.cpp
index 1eee7ad71e..98d12dc417 100644
--- a/common/iff_container.cpp
+++ b/common/iff_container.cpp
@@ -34,7 +34,7 @@ IFFParser::~IFFParser() {
if (_disposeStream) {
delete _stream;
}
- _stream = 0;
+ _stream = nullptr;
}
void IFFParser::setInputStream(ReadStream *stream) {
diff --git a/common/iff_container.h b/common/iff_container.h
index e684f253b2..a88b159733 100644
--- a/common/iff_container.h
+++ b/common/iff_container.h
@@ -172,7 +172,7 @@ class IFFParser {
IFF_ID id;
uint32 size;
- IFFChunkNav() : _input(0) {
+ IFFChunkNav() : _input(nullptr) {
}
void setInputStream(ReadStream *input) {
_input = input;
diff --git a/common/ini-file.cpp b/common/ini-file.cpp
index 7fa17da76c..7e5a098b4e 100644
--- a/common/ini-file.cpp
+++ b/common/ini-file.cpp
@@ -249,7 +249,7 @@ void INIFile::removeSection(const String &section) {
bool INIFile::hasSection(const String &section) const {
assert(isValidName(section));
const Section *s = getSection(section);
- return s != 0;
+ return s != nullptr;
}
void INIFile::renameSection(const String &oldName, const String &newName) {
@@ -341,7 +341,7 @@ INIFile::Section *INIFile::getSection(const String &section) {
return &(*i);
}
}
- return 0;
+ return nullptr;
}
const INIFile::Section *INIFile::getSection(const String &section) const {
@@ -350,11 +350,11 @@ const INIFile::Section *INIFile::getSection(const String &section) const {
return &(*i);
}
}
- return 0;
+ return nullptr;
}
bool INIFile::Section::hasKey(const String &key) const {
- return getKey(key) != 0;
+ return getKey(key) != nullptr;
}
const INIFile::KeyValue* INIFile::Section::getKey(const String &key) const {
@@ -363,7 +363,7 @@ const INIFile::KeyValue* INIFile::Section::getKey(const String &key) const {
return &(*i);
}
}
- return 0;
+ return nullptr;
}
void INIFile::Section::setKey(const String &key, const String &value) {
diff --git a/common/installshield_cab.cpp b/common/installshield_cab.cpp
index e9e8586185..a7fcf81607 100644
--- a/common/installshield_cab.cpp
+++ b/common/installshield_cab.cpp
@@ -174,7 +174,7 @@ const ArchiveMemberPtr InstallShieldCabinet::getMember(const String &name) const
SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const String &name) const {
if (!_map.contains(name))
- return 0;
+ return nullptr;
const FileEntry &entry = _map[name];
@@ -195,7 +195,7 @@ SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const String
if (!result) {
warning("failed to inflate CAB file '%s'", name.c_str());
free(dst);
- return 0;
+ return nullptr;
}
return new MemoryReadStream(dst, entry.uncompressedSize, DisposeAfterUse::YES);
diff --git a/common/json.cpp b/common/json.cpp
index c8caf01519..89f780bfc8 100644
--- a/common/json.cpp
+++ b/common/json.cpp
@@ -76,17 +76,17 @@ JSON::JSON() {}
JSONValue *JSON::parse(const char *data) {
// Skip any preceding whitespace, end of data = no JSON = fail
if (!skipWhitespace(&data))
- return NULL;
+ return nullptr;
// We need the start of a value here now...
JSONValue *value = JSONValue::parse(&data);
- if (value == NULL)
- return NULL;
+ if (value == nullptr)
+ return nullptr;
// Can be white space now and should be at the end of the string then...
if (skipWhitespace(&data)) {
delete value;
- return NULL;
+ return nullptr;
}
// We're now at the end of the string
@@ -103,7 +103,7 @@ JSONValue *JSON::parse(const char *data) {
* @return String Returns a JSON encoded string representation of the given value
*/
String JSON::stringify(const JSONValue *value) {
- if (value != NULL)
+ if (value != nullptr)
return value->stringify();
else
return "";
@@ -276,7 +276,7 @@ JSONValue *JSONValue::parse(const char **data) {
if (**data == '"') {
String str;
if (!JSON::extractString(&(++(*data)), str))
- return NULL;
+ return nullptr;
else
return new JSONValue(str);
}
@@ -310,7 +310,7 @@ JSONValue *JSONValue::parse(const char **data) {
else if (**data >= '1' && **data <= '9')
number = integer = JSON::parseInt(data);
else
- return NULL;
+ return nullptr;
// Could be a decimal now...
if (**data == '.') {
@@ -318,7 +318,7 @@ JSONValue *JSONValue::parse(const char **data) {
// Not get any digits?
if (!(**data >= '0' && **data <= '9'))
- return NULL;
+ return nullptr;
// Find the decimal and sort the decimal place out
// Use ParseDecimal as ParseInt won't work with decimals less than 0.1
@@ -343,7 +343,7 @@ JSONValue *JSONValue::parse(const char **data) {
// Not get any digits?
if (!(**data >= '0' && **data <= '9'))
- return NULL;
+ return nullptr;
// Sort the expo out
double expo = JSON::parseInt(data);
@@ -371,7 +371,7 @@ JSONValue *JSONValue::parse(const char **data) {
// Whitespace at the start?
if (!JSON::skipWhitespace(data)) {
FREE_OBJECT(object);
- return NULL;
+ return nullptr;
}
// Special case - empty object
@@ -384,32 +384,32 @@ JSONValue *JSONValue::parse(const char **data) {
String name;
if (!JSON::extractString(&(++(*data)), name)) {
FREE_OBJECT(object);
- return NULL;
+ return nullptr;
}
// More whitespace?
if (!JSON::skipWhitespace(data)) {
FREE_OBJECT(object);
- return NULL;
+ return nullptr;
}
// Need a : now
if (*((*data)++) != ':') {
FREE_OBJECT(object);
- return NULL;
+ return nullptr;
}
// More whitespace?
if (!JSON::skipWhitespace(data)) {
FREE_OBJECT(object);
- return NULL;
+ return nullptr;
}
// The value is here
JSONValue *value = parse(data);
- if (value == NULL) {
+ if (value == nullptr) {
FREE_OBJECT(object);
- return NULL;
+ return nullptr;
}
// Add the name:value
@@ -420,7 +420,7 @@ JSONValue *JSONValue::parse(const char **data) {
// More whitespace?
if (!JSON::skipWhitespace(data)) {
FREE_OBJECT(object);
- return NULL;
+ return nullptr;
}
// End of object?
@@ -432,7 +432,7 @@ JSONValue *JSONValue::parse(const char **data) {
// Want a , now
if (**data != ',') {
FREE_OBJECT(object);
- return NULL;
+ return nullptr;
}
(*data)++;
@@ -440,7 +440,7 @@ JSONValue *JSONValue::parse(const char **data) {
// Only here if we ran out of data
FREE_OBJECT(object);
- return NULL;
+ return nullptr;
}
// An array?
@@ -453,7 +453,7 @@ JSONValue *JSONValue::parse(const char **data) {
// Whitespace at the start?
if (!JSON::skipWhitespace(data)) {
FREE_ARRAY(array);
- return NULL;
+ return nullptr;
}
// Special case - empty array
@@ -464,9 +464,9 @@ JSONValue *JSONValue::parse(const char **data) {
// Get the value
JSONValue *value = parse(data);
- if (value == NULL) {
+ if (value == nullptr) {
FREE_ARRAY(array);
- return NULL;
+ return nullptr;
}
// Add the value
@@ -475,7 +475,7 @@ JSONValue *JSONValue::parse(const char **data) {
// More whitespace?
if (!JSON::skipWhitespace(data)) {
FREE_ARRAY(array);
- return NULL;
+ return nullptr;
}
// End of array?
@@ -487,7 +487,7 @@ JSONValue *JSONValue::parse(const char **data) {
// Want a , now
if (**data != ',') {
FREE_ARRAY(array);
- return NULL;
+ return nullptr;
}
(*data)++;
@@ -495,12 +495,12 @@ JSONValue *JSONValue::parse(const char **data) {
// Only here if we ran out of data
FREE_ARRAY(array);
- return NULL;
+ return nullptr;
}
// Ran out of possibilites, it's bad!
else {
- return NULL;
+ return nullptr;
}
}
@@ -871,7 +871,7 @@ JSONValue *JSONValue::child(std::size_t index) {
if (index < _arrayValue->size()) {
return (*_arrayValue)[index];
} else {
- return NULL;
+ return nullptr;
}
}
@@ -905,7 +905,7 @@ JSONValue *JSONValue::child(const char *name) {
if (it != _objectValue->end()) {
return it->_value;
} else {
- return NULL;
+ return nullptr;
}
}
diff --git a/common/json.h b/common/json.h
index 3b219993e7..a911196d18 100644
--- a/common/json.h
+++ b/common/json.h
@@ -65,7 +65,7 @@ static inline bool isinf(double x) {
// Simple function to check a string 's' has at least 'n' characters
static inline bool simplejson_wcsnlen(const char *s, size_t n) {
- if (s == 0)
+ if (s == nullptr)
return false;
const char *save = s;
diff --git a/common/language.cpp b/common/language.cpp
index b7397bec6d..4d40744d2f 100644
--- a/common/language.cpp
+++ b/common/language.cpp
@@ -46,13 +46,13 @@ const LanguageDescription g_languages[] = {
{ "jp", "ja_JP", "Japanese", JA_JPN },
{ "kr", "ko_KR", "Korean", KO_KOR },
{ "lv", "lv_LV", "Latvian", LV_LAT },
- { "nb", "nb_NO", "Norwegian Bokm\xE5l", NB_NOR }, // TODO Someone should verify the unix locale
+ { "nb", "nb_NO", "Norwegian Bokm\xE5l", NB_NOR },
{ "pl", "pl_PL", "Polish", PL_POL },
{ "br", "pt_BR", "Portuguese", PT_BRA },
{ "ru", "ru_RU", "Russian", RU_RUS },
{ "es", "es_ES", "Spanish", ES_ESP },
{ "se", "sv_SE", "Swedish", SE_SWE },
- { 0, 0, 0, UNK_LANG }
+ { nullptr, nullptr, nullptr, UNK_LANG }
};
Language parseLanguage(const String &str) {
@@ -87,7 +87,7 @@ const char *getLanguageCode(Language id) {
if (l->id == id)
return l->code;
}
- return 0;
+ return nullptr;
}
const char *getLanguageLocale(Language id) {
@@ -96,7 +96,7 @@ const char *getLanguageLocale(Language id) {
if (l->id == id)
return l->unixLocale;
}
- return 0;
+ return nullptr;
}
const char *getLanguageDescription(Language id) {
@@ -105,7 +105,7 @@ const char *getLanguageDescription(Language id) {
if (l->id == id)
return l->description;
}
- return 0;
+ return nullptr;
}
bool checkGameGUIOptionLanguage(Language lang, const String &str) {
diff --git a/common/list.h b/common/list.h
index 1bb4a2a5df..31cf161d22 100644
--- a/common/list.h
+++ b/common/list.h
@@ -170,7 +170,7 @@ public:
const_iterator i2;
const_iterator e2 = list.end();
- for (i = begin(), i2 = list.begin(); (i != e) && (i2 != e2) ; ++i, ++i2) {
+ for (i = begin(), i2 = list.begin(); (i != e) && (i2 != e2); ++i, ++i2) {
static_cast<Node *>(i._node)->_data = static_cast<const Node *>(i2._node)->_data;
}
diff --git a/common/list_intern.h b/common/list_intern.h
index b4f347561b..37f9259e54 100644
--- a/common/list_intern.h
+++ b/common/list_intern.h
@@ -55,7 +55,7 @@ namespace ListInternal {
NodeBase *_node;
- Iterator() : _node(0) {}
+ Iterator() : _node(nullptr) {}
explicit Iterator(NodeBase *node) : _node(node) {}
// Prefix inc
@@ -108,7 +108,7 @@ namespace ListInternal {
const NodeBase *_node;
- ConstIterator() : _node(0) {}
+ ConstIterator() : _node(nullptr) {}
explicit ConstIterator(const NodeBase *node) : _node(node) {}
ConstIterator(const Iterator<T> &x) : _node(x._node) {}
diff --git a/common/macresman.cpp b/common/macresman.cpp
index adca1ea10b..553b138717 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -67,9 +67,9 @@ void MacResManager::close() {
delete[] _resLists[i];
}
- delete[] _resLists; _resLists = 0;
- delete[] _resTypes; _resTypes = 0;
- delete _stream; _stream = 0;
+ delete[] _resLists; _resLists = nullptr;
+ delete[] _resTypes; _resTypes = nullptr;
+ delete _stream; _stream = nullptr;
_resMap.numTypes = 0;
}
@@ -463,7 +463,7 @@ bool MacResManager::load(SeekableReadStream &stream) {
SeekableReadStream *MacResManager::getDataFork() {
if (!_stream)
- return NULL;
+ return nullptr;
if (_mode == kResForkMacBinary) {
_stream->seek(MBI_DFLEN);
@@ -476,7 +476,7 @@ SeekableReadStream *MacResManager::getDataFork() {
return file;
delete file;
- return NULL;
+ return nullptr;
}
MacResIDArray MacResManager::getResIDArray(uint32 typeID) {
@@ -544,7 +544,7 @@ SeekableReadStream *MacResManager::getResource(uint32 typeID, uint16 resID) {
}
if (typeNum == -1)
- return NULL;
+ return nullptr;
for (int i = 0; i < _resTypes[typeNum].items; i++)
if (_resLists[typeNum][i].id == resID) {
@@ -553,14 +553,14 @@ SeekableReadStream *MacResManager::getResource(uint32 typeID, uint16 resID) {
}
if (resNum == -1)
- return NULL;
+ return nullptr;
_stream->seek(_dataOffset + _resLists[typeNum][resNum].dataOffset);
uint32 len = _stream->readUint32BE();
// Ignore resources with 0 length
if (!len)
- return 0;
+ return nullptr;
return _stream->readStream(len);
}
@@ -574,14 +574,14 @@ SeekableReadStream *MacResManager::getResource(const String &fileName) {
// Ignore resources with 0 length
if (!len)
- return 0;
+ return nullptr;
return _stream->readStream(len);
}
}
}
- return 0;
+ return nullptr;
}
SeekableReadStream *MacResManager::getResource(uint32 typeID, const String &fileName) {
@@ -596,14 +596,14 @@ SeekableReadStream *MacResManager::getResource(uint32 typeID, const String &file
// Ignore resources with 0 length
if (!len)
- return 0;
+ return nullptr;
return _stream->readStream(len);
}
}
}
- return 0;
+ return nullptr;
}
void MacResManager::readMap() {
@@ -640,7 +640,7 @@ void MacResManager::readMap() {
resPtr->nameOffset = _stream->readUint16BE();
resPtr->dataOffset = _stream->readUint32BE();
_stream->readUint32BE();
- resPtr->name = 0;
+ resPtr->name = nullptr;
resPtr->attr = resPtr->dataOffset >> 24;
resPtr->dataOffset &= 0xFFFFFF;
diff --git a/common/math.h b/common/math.h
index ddb5c67dfe..7b2ec6060e 100644
--- a/common/math.h
+++ b/common/math.h
@@ -107,12 +107,46 @@ inline int intLog2(uint32 v) {
}
#endif
-inline float rad2deg(float rad) {
- return rad * 180.0f / (float)M_PI;
+// Convert radians to degrees
+// Input and Output type can be different
+// Upconvert everything to floats
+template<class InputT, class OutputT>
+inline OutputT rad2deg(InputT rad) {
+ return (OutputT)( (float)rad * (float)57.2957795130823); // 180.0/M_PI = 57.2957795130823
}
-inline float deg2rad(float deg) {
- return deg * (float)M_PI / 180.0f;
+// Handle the case differently when the input type is double
+template<class OutputT>
+inline OutputT rad2deg(double rad) {
+ return (OutputT)( rad * 57.2957795130823);
+}
+
+// Convert radians to degrees
+// Input and Output type are the same
+template<class T>
+inline T rad2deg(T rad) {
+ return rad2deg<T,T>(rad);
+}
+
+// Convert degrees to radians
+// Input and Output type can be different
+// Upconvert everything to floats
+template<class InputT, class OutputT>
+inline OutputT deg2rad(InputT deg) {
+ return (OutputT)( (float)deg * (float)0.0174532925199433); // M_PI/180.0 = 0.0174532925199433
+}
+
+// Handle the case differently when the input type is double
+template<class OutputT>
+inline OutputT deg2rad(double deg) {
+ return (OutputT)( deg * 0.0174532925199433);
+}
+
+// Convert degrees to radians
+// Input and Output type are the same
+template<class T>
+inline T deg2rad(T deg) {
+ return deg2rad<T,T>(deg);
}
} // End of namespace Common
diff --git a/common/memorypool.cpp b/common/memorypool.cpp
index 1a9bfe2e29..f0134a430d 100644
--- a/common/memorypool.cpp
+++ b/common/memorypool.cpp
@@ -43,7 +43,7 @@ static size_t adjustChunkSize(size_t chunkSize) {
MemoryPool::MemoryPool(size_t chunkSize)
: _chunkSize(adjustChunkSize(chunkSize)) {
- _next = NULL;
+ _next = nullptr;
_chunksPerPage = INITIAL_CHUNKS_PER_PAGE;
}
@@ -64,7 +64,7 @@ void MemoryPool::allocPage() {
// Allocate a new page
page.numChunks = _chunksPerPage;
- assert(page.numChunks * _chunkSize < 16*1024*1024); // Refuse to allocate pages bigger than 16 MB
+ assert(page.numChunks * _chunkSize < 16*1024*1024); // Refuse to allocate pages bigger than 16 MB
page.start = ::malloc(page.numChunks * _chunkSize);
assert(page.start);
@@ -154,7 +154,7 @@ void MemoryPool::freeUnusedPages() {
::free(_pages[i].start);
++freedPagesCount;
- _pages[i].start = NULL;
+ _pages[i].start = nullptr;
}
}
@@ -163,7 +163,7 @@ void MemoryPool::freeUnusedPages() {
// Remove all now unused pages
size_t newSize = 0;
for (size_t i = 0; i < _pages.size(); ++i) {
- if (_pages[i].start != NULL) {
+ if (_pages[i].start != nullptr) {
if (newSize != i)
_pages[newSize] = _pages[i];
++newSize;
diff --git a/common/memstream.h b/common/memstream.h
index f6bf990208..8a8326e4a6 100644
--- a/common/memstream.h
+++ b/common/memstream.h
@@ -184,7 +184,7 @@ protected:
_size = new_len;
}
public:
- explicit MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _ptr(0), _data(0), _pos(0), _disposeMemory(disposeMemory) {}
+ explicit MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _ptr(nullptr), _data(nullptr), _pos(0), _disposeMemory(disposeMemory) {}
~MemoryWriteStreamDynamic() {
if (_disposeMemory)
@@ -247,7 +247,7 @@ private:
}
}
public:
- explicit MemoryReadWriteStream(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _data(0), _writePos(0), _readPos(0), _pos(0), _length(0), _disposeMemory(disposeMemory), _eos(false) {}
+ explicit MemoryReadWriteStream(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _data(nullptr), _writePos(0), _readPos(0), _pos(0), _length(0), _disposeMemory(disposeMemory), _eos(false) {}
~MemoryReadWriteStream() {
if (_disposeMemory)
@@ -289,8 +289,8 @@ public:
return dataSize;
}
- int32 pos() const { return _pos - _length; } //'read' position in the stream
- int32 size() const { return _size; } //that's also 'write' position in the stream, as it's append-only
+ int32 pos() const { return _pos - _length; } // 'read' position in the stream
+ int32 size() const { return _size; } // that's also 'write' position in the stream, as it's append-only
bool seek(int32, int) { return false; }
bool eos() const { return _eos; }
void clearErr() { _eos = false; }
diff --git a/common/mutex.cpp b/common/mutex.cpp
index a7b34eb334..e7a0bbfe76 100644
--- a/common/mutex.cpp
+++ b/common/mutex.cpp
@@ -62,14 +62,14 @@ StackLock::~StackLock() {
}
void StackLock::lock() {
- if (_mutexName != NULL)
+ if (_mutexName != nullptr)
debug(6, "Locking mutex %s", _mutexName);
g_system->lockMutex(_mutex);
}
void StackLock::unlock() {
- if (_mutexName != NULL)
+ if (_mutexName != nullptr)
debug(6, "Unlocking mutex %s", _mutexName);
g_system->unlockMutex(_mutex);
diff --git a/common/mutex.h b/common/mutex.h
index 6e467cfddf..f965a63e0d 100644
--- a/common/mutex.h
+++ b/common/mutex.h
@@ -46,8 +46,8 @@ class StackLock {
void lock();
void unlock();
public:
- explicit StackLock(MutexRef mutex, const char *mutexName = NULL);
- explicit StackLock(const Mutex &mutex, const char *mutexName = NULL);
+ explicit StackLock(MutexRef mutex, const char *mutexName = nullptr);
+ explicit StackLock(const Mutex &mutex, const char *mutexName = nullptr);
~StackLock();
};
diff --git a/common/osd_message_queue.cpp b/common/osd_message_queue.cpp
index b8abf18bb5..d150737165 100644
--- a/common/osd_message_queue.cpp
+++ b/common/osd_message_queue.cpp
@@ -26,18 +26,18 @@
namespace Common {
DECLARE_SINGLETON(OSDMessageQueue);
-
+
OSDMessageQueue::OSDMessageQueue() : _lastUpdate(0) {
}
OSDMessageQueue::~OSDMessageQueue() {
g_system->getEventManager()->getEventDispatcher()->unregisterSource(this);
}
-
+
void OSDMessageQueue::registerEventSource() {
g_system->getEventManager()->getEventDispatcher()->registerSource(this, false);
}
-
+
void OSDMessageQueue::addMessage(const char *msg) {
_mutex.lock();
_messages.push(msg);
diff --git a/common/osd_message_queue.h b/common/osd_message_queue.h
index 7aa7cf4792..10fe96bc6a 100644
--- a/common/osd_message_queue.h
+++ b/common/osd_message_queue.h
@@ -38,9 +38,9 @@ class OSDMessageQueue : public Singleton<OSDMessageQueue>, public EventSource {
public:
OSDMessageQueue();
~OSDMessageQueue();
-
+
void registerEventSource();
-
+
enum {
kMinimumDelay = 1000 /** < Minimum delay between two OSD messages (in milliseconds) */
};
@@ -49,7 +49,7 @@ public:
* Add a message to the OSD message queue.
*/
void addMessage(const char *msg);
-
+
/**
* Common::EventSource interface
*
diff --git a/common/platform.cpp b/common/platform.cpp
index 6898993b33..0049666912 100644
--- a/common/platform.cpp
+++ b/common/platform.cpp
@@ -56,7 +56,7 @@ const PlatformDescription g_platforms[] = {
{ "os2", "os2", "os2", "OS/2", kPlatformOS2 },
{ "beos", "beos", "beos", "BeOS", kPlatformBeOS },
- { 0, 0, 0, "Default", kPlatformUnknown }
+ { nullptr, nullptr, nullptr, "Default", kPlatformUnknown }
};
Platform parsePlatform(const String &str) {
@@ -88,7 +88,7 @@ const char *getPlatformCode(Platform id) {
if (l->id == id)
return l->code;
}
- return 0;
+ return nullptr;
}
const char *getPlatformAbbrev(Platform id) {
@@ -97,7 +97,7 @@ const char *getPlatformAbbrev(Platform id) {
if (l->id == id)
return l->abbrev;
}
- return 0;
+ return nullptr;
}
const char *getPlatformDescription(Platform id) {
diff --git a/common/ptr.h b/common/ptr.h
index f3b2f3cbfa..49a38e48bd 100644
--- a/common/ptr.h
+++ b/common/ptr.h
@@ -109,7 +109,7 @@ public:
typedef T *PointerType;
typedef T &ReferenceType;
- SharedPtr() : _refCount(0), _deletion(0), _pointer(0) {}
+ SharedPtr() : _refCount(nullptr), _deletion(nullptr), _pointer(nullptr) {}
template<class T2>
explicit SharedPtr(T2 *p) : _refCount(new RefValue(1)), _deletion(new SharedPtrDeletionImpl<T2>(p)), _pointer(p) {}
@@ -206,9 +206,9 @@ private:
if (!*_refCount) {
delete _refCount;
delete _deletion;
- _deletion = 0;
- _refCount = 0;
- _pointer = 0;
+ _deletion = nullptr;
+ _refCount = nullptr;
+ _pointer = nullptr;
}
}
}
diff --git a/common/quicktime.cpp b/common/quicktime.cpp
index ecbf021e45..1c1690bc13 100644
--- a/common/quicktime.cpp
+++ b/common/quicktime.cpp
@@ -45,7 +45,7 @@ namespace Common {
QuickTimeParser::QuickTimeParser() {
_beginOffset = 0;
- _fd = 0;
+ _fd = nullptr;
_scaleFactorX = 1;
_scaleFactorY = 1;
_resFork = new MacResManager();
@@ -166,7 +166,7 @@ void QuickTimeParser::initParseTable() {
{ &QuickTimeParser::readSMI, MKTAG('S', 'M', 'I', ' ') },
{ &QuickTimeParser::readDefault, MKTAG('g', 'm', 'h', 'd') },
{ &QuickTimeParser::readLeaf, MKTAG('g', 'm', 'i', 'n') },
- { 0, 0 }
+ { nullptr, 0 }
};
_parseTable = p;
@@ -805,13 +805,13 @@ void QuickTimeParser::close() {
if (_disposeFileHandle == DisposeAfterUse::YES)
delete _fd;
- _fd = 0;
+ _fd = nullptr;
}
QuickTimeParser::SampleDesc::SampleDesc(Track *parentTrack, uint32 codecTag) {
_parentTrack = parentTrack;
_codecTag = codecTag;
- _extraData = 0;
+ _extraData = nullptr;
_objectTypeMP4 = 0;
}
@@ -821,16 +821,16 @@ QuickTimeParser::SampleDesc::~SampleDesc() {
QuickTimeParser::Track::Track() {
chunkCount = 0;
- chunkOffsets = 0;
+ chunkOffsets = nullptr;
timeToSampleCount = 0;
- timeToSample = 0;
+ timeToSample = nullptr;
sampleToChunkCount = 0;
- sampleToChunk = 0;
+ sampleToChunk = nullptr;
sampleSize = 0;
sampleCount = 0;
- sampleSizes = 0;
+ sampleSizes = nullptr;
keyframeCount = 0;
- keyframes = 0;
+ keyframes = nullptr;
timeScale = 0;
width = 0;
height = 0;
diff --git a/common/quicktime.h b/common/quicktime.h
index 3f82fc0431..26fc44ac71 100644
--- a/common/quicktime.h
+++ b/common/quicktime.h
@@ -79,7 +79,7 @@ public:
void setChunkBeginOffset(uint32 offset) { _beginOffset = offset; }
/** Find out if this parser has an open file handle */
- bool isOpen() const { return _fd != 0; }
+ bool isOpen() const { return _fd != nullptr; }
protected:
// This is the file handle from which data is read from. It can be the actual file handle or a decompressed stream.
diff --git a/common/rdft.cpp b/common/rdft.cpp
index 89d39112e6..b6af6cb4cd 100644
--- a/common/rdft.cpp
+++ b/common/rdft.cpp
@@ -28,7 +28,7 @@
namespace Common {
-RDFT::RDFT(int bits, TransformType trans) : _bits(bits), _sin(bits), _cos(bits), _fft(0) {
+RDFT::RDFT(int bits, TransformType trans) : _bits(bits), _sin(bits), _cos(bits), _fft(nullptr) {
assert((_bits >= 4) && (_bits <= 16));
_inverse = trans == IDFT_C2R || trans == DFT_C2R;
diff --git a/common/recorderfile.cpp b/common/recorderfile.cpp
index 1f283715d0..3db017ea8b 100644
--- a/common/recorderfile.cpp
+++ b/common/recorderfile.cpp
@@ -335,7 +335,7 @@ RecorderEvent PlaybackFile::getNextEvent() {
case kScreenShotTag:
_readStream->seek(-4, SEEK_CUR);
header.len = _readStream->readUint32BE();
- _readStream->skip(header.len-8);
+ _readStream->skip(header.len - 8);
break;
case kMD5Tag:
checkRecordedMD5();
@@ -575,7 +575,7 @@ int PlaybackFile::getScreensCount() {
int result = 0;
while (skipToNextScreenshot()) {
uint32 size = _readStream->readUint32BE();
- _readStream->skip(size-8);
+ _readStream->skip(size - 8);
++result;
}
return result;
@@ -608,10 +608,11 @@ Graphics::Surface *PlaybackFile::getScreenShot(int number) {
if (screenCount == number) {
screenCount++;
_readStream->seek(-4, SEEK_CUR);
- return Graphics::loadThumbnail(*_readStream);
+ Graphics::Surface *thumbnail;
+ return Graphics::loadThumbnail(*_readStream, thumbnail) ? thumbnail : NULL;
} else {
uint32 size = _readStream->readUint32BE();
- _readStream->skip(size-8);
+ _readStream->skip(size - 8);
screenCount++;
}
}
diff --git a/common/rect.h b/common/rect.h
index 6c4292c7af..135076bf1e 100644
--- a/common/rect.h
+++ b/common/rect.h
@@ -40,10 +40,10 @@ struct Point {
Point() : x(0), y(0) {}
Point(int16 x1, int16 y1) : x(x1), y(y1) {}
- bool operator==(const Point &p) const { return x == p.x && y == p.y; }
- bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
- Point operator+(const Point &delta) const { return Point(x + delta.x, y + delta.y); }
- Point operator-(const Point &delta) const { return Point(x - delta.x, y - delta.y); }
+ bool operator==(const Point &p) const { return x == p.x && y == p.y; }
+ bool operator!=(const Point &p) const { return x != p.x || y != p.y; }
+ Point operator+(const Point &delta) const { return Point(x + delta.x, y + delta.y); }
+ Point operator-(const Point &delta) const { return Point(x - delta.x, y - delta.y); }
void operator+=(const Point &delta) {
x += delta.x;
diff --git a/common/rendermode.cpp b/common/rendermode.cpp
index e07cac4b4e..ab345a7b36 100644
--- a/common/rendermode.cpp
+++ b/common/rendermode.cpp
@@ -44,7 +44,7 @@ const RenderModeDescription g_renderModes[] = {
{ "2gs", "Apple IIgs", kRenderApple2GS },
{ "atari", "Atari ST", kRenderAtariST },
{ "macintosh", "Macintosh", kRenderMacintosh },
- {0, 0, kRenderDefault}
+ {nullptr, nullptr, kRenderDefault}
};
struct RenderGUIOMapping {
@@ -92,7 +92,7 @@ const char *getRenderModeCode(RenderMode id) {
if (l->id == id)
return l->code;
}
- return 0;
+ return nullptr;
}
const char *getRenderModeDescription(RenderMode id) {
@@ -101,7 +101,7 @@ const char *getRenderModeDescription(RenderMode id) {
if (l->id == id)
return l->description;
}
- return 0;
+ return nullptr;
}
String renderMode2GUIO(RenderMode id) {
diff --git a/common/safe-bool.h b/common/safe-bool.h
index 7cbe29931c..92c8af51aa 100644
--- a/common/safe-bool.h
+++ b/common/safe-bool.h
@@ -52,7 +52,7 @@ namespace Common {
public:
operator bool_type() const {
return static_cast<const DerivedT *>(this)->operator_bool() ?
- &impl_t::stub : 0;
+ &impl_t::stub : nullptr;
}
operator bool_type() {
diff --git a/common/scummsys.h b/common/scummsys.h
index 5486ba27c6..ce54f3b50e 100644
--- a/common/scummsys.h
+++ b/common/scummsys.h
@@ -398,6 +398,18 @@
#endif
#endif
+#ifndef WARN_UNUSED_RESULT
+ #if __cplusplus >= 201703L
+ #define WARN_UNUSED_RESULT [[nodiscard]]
+ #elif GCC_ATLEAST(3, 4)
+ #define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
+ #elif defined(_Check_return_)
+ #define WARN_UNUSED_RESULT _Check_return_
+ #else
+ #define WARN_UNUSED_RESULT
+ #endif
+#endif
+
#ifndef STRINGBUFLEN
#if defined(__N64__) || defined(__DS__) || defined(__3DS__)
#define STRINGBUFLEN 256
diff --git a/common/serializer.h b/common/serializer.h
index e8db40923a..18fb38563b 100644
--- a/common/serializer.h
+++ b/common/serializer.h
@@ -34,7 +34,7 @@ namespace Common {
template<typename T> \
void syncAs ## SUFFIX(T &val, Version minVersion = 0, Version maxVersion = kLastVersion) { \
if (_version < minVersion || _version > maxVersion) \
- return; \
+ return; \
if (_loadStream) \
val = static_cast<T>(_loadStream->read ## SUFFIX()); \
else { \
@@ -178,7 +178,7 @@ public:
*/
void skip(uint32 size, Version minVersion = 0, Version maxVersion = kLastVersion) {
if (_version < minVersion || _version > maxVersion)
- return; // Ignore anything which is not supposed to be present in this save game version
+ return; // Ignore anything which is not supposed to be present in this save game version
_bytesSynced += size;
if (isLoading())
@@ -194,7 +194,7 @@ public:
*/
void syncBytes(byte *buf, uint32 size, Version minVersion = 0, Version maxVersion = kLastVersion) {
if (_version < minVersion || _version > maxVersion)
- return; // Ignore anything which is not supposed to be present in this save game version
+ return; // Ignore anything which is not supposed to be present in this save game version
if (isLoading())
_loadStream->read(buf, size);
@@ -217,7 +217,7 @@ public:
*/
bool matchBytes(const char *magic, byte size, Version minVersion = 0, Version maxVersion = kLastVersion) {
if (_version < minVersion || _version > maxVersion)
- return true; // Ignore anything which is not supposed to be present in this save game version
+ return true; // Ignore anything which is not supposed to be present in this save game version
bool match;
if (isSaving()) {
@@ -238,7 +238,7 @@ public:
*/
void syncString(String &str, Version minVersion = 0, Version maxVersion = kLastVersion) {
if (_version < minVersion || _version > maxVersion)
- return; // Ignore anything which is not supposed to be present in this save game version
+ return; // Ignore anything which is not supposed to be present in this save game version
if (isLoading()) {
char c;
diff --git a/common/singleton.h b/common/singleton.h
index 9bcd590183..7deb1dd7dc 100644
--- a/common/singleton.h
+++ b/common/singleton.h
@@ -59,6 +59,10 @@ public:
public:
+ static bool hasInstance() {
+ return _singleton != 0;
+ }
+
static T& instance() {
// TODO: We aren't thread safe. For now we ignore it since the
// only thing using this singleton template is the config manager,
diff --git a/common/str.cpp b/common/str.cpp
index 2ef67175cd..468d1a6f53 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -28,7 +28,7 @@
namespace Common {
-MemoryPool *g_refCountPool = 0; // FIXME: This is never freed right now
+MemoryPool *g_refCountPool = nullptr; // FIXME: This is never freed right now
static uint32 computeCapacity(uint32 len) {
// By default, for the capacity we use the next multiple of 32
@@ -36,7 +36,7 @@ static uint32 computeCapacity(uint32 len) {
}
String::String(const char *str) : _size(0), _str(_storage) {
- if (str == 0) {
+ if (str == nullptr) {
_storage[0] = 0;
_size = 0;
} else
@@ -63,10 +63,10 @@ void String::initWithCStr(const char *str, uint32 len) {
if (len >= _builtinCapacity) {
// Not enough internal storage, so allocate more
- _extern._capacity = computeCapacity(len+1);
- _extern._refCount = 0;
+ _extern._capacity = computeCapacity(len + 1);
+ _extern._refCount = nullptr;
_str = new char[_extern._capacity];
- assert(_str != 0);
+ assert(_str != nullptr);
}
// Copy the string into the storage area
@@ -87,7 +87,7 @@ String::String(const String &str)
_extern._capacity = str._extern._capacity;
_str = str._str;
}
- assert(_str != 0);
+ assert(_str != nullptr);
}
String::String(char c)
@@ -165,15 +165,15 @@ void String::ensureCapacity(uint32 new_size, bool keep_old) {
// Set the ref count & capacity if we use an external storage.
// It is important to do this *after* copying any old content,
// else we would override data that has not yet been copied!
- _extern._refCount = 0;
+ _extern._refCount = nullptr;
_extern._capacity = newCapacity;
}
}
void String::incRefCount() const {
assert(!isStorageIntern());
- if (_extern._refCount == 0) {
- if (g_refCountPool == 0) {
+ if (_extern._refCount == nullptr) {
+ if (g_refCountPool == nullptr) {
g_refCountPool = new MemoryPool(sizeof(int));
assert(g_refCountPool);
}
@@ -290,7 +290,7 @@ bool String::hasPrefix(const String &x) const {
}
bool String::hasPrefix(const char *x) const {
- assert(x != 0);
+ assert(x != nullptr);
// Compare x with the start of _str.
const char *y = c_str();
while (*x && *x == *y) {
@@ -302,12 +302,29 @@ bool String::hasPrefix(const char *x) const {
return *x == 0;
}
+bool String::hasPrefixIgnoreCase(const String &x) const {
+ return hasPrefixIgnoreCase(x.c_str());
+}
+
+bool String::hasPrefixIgnoreCase(const char *x) const {
+ assert(x != nullptr);
+ // Compare x with the start of _str.
+ const char *y = c_str();
+ while (*x && tolower(*x) == tolower(*y)) {
+ ++x;
+ ++y;
+ }
+ // It's a prefix, if and only if all letters in x are 'used up' before
+ // _str ends.
+ return *x == 0;
+}
+
bool String::hasSuffix(const String &x) const {
return hasSuffix(x.c_str());
}
bool String::hasSuffix(const char *x) const {
- assert(x != 0);
+ assert(x != nullptr);
// Compare x with the end of _str.
const uint32 x_size = strlen(x);
if (x_size > _size)
@@ -322,17 +339,37 @@ bool String::hasSuffix(const char *x) const {
return *x == 0;
}
+bool String::hasSuffixIgnoreCase(const String &x) const {
+ return hasSuffixIgnoreCase(x.c_str());
+}
+
+bool String::hasSuffixIgnoreCase(const char *x) const {
+ assert(x != nullptr);
+ // Compare x with the end of _str.
+ const uint32 x_size = strlen(x);
+ if (x_size > _size)
+ return false;
+ const char *y = c_str() + _size - x_size;
+ while (*x && tolower(*x) == tolower(*y)) {
+ ++x;
+ ++y;
+ }
+ // It's a suffix, if and only if all letters in x are 'used up' before
+ // _str ends.
+ return *x == 0;
+}
+
bool String::contains(const String &x) const {
- return strstr(c_str(), x.c_str()) != NULL;
+ return strstr(c_str(), x.c_str()) != nullptr;
}
bool String::contains(const char *x) const {
- assert(x != 0);
- return strstr(c_str(), x) != NULL;
+ assert(x != nullptr);
+ return strstr(c_str(), x) != nullptr;
}
bool String::contains(char x) const {
- return strchr(c_str(), x) != NULL;
+ return strchr(c_str(), x) != nullptr;
}
uint64 String::asUint64() const {
@@ -593,7 +630,7 @@ String String::vformat(const char *fmt, va_list args) {
// vsnprintf didn't have enough space, so grow buffer
output.ensureCapacity(len, false);
scumm_va_copy(va, args);
- int len2 = vsnprintf(output._str, len+1, fmt, va);
+ int len2 = vsnprintf(output._str, len + 1, fmt, va);
va_end(va);
assert(len == len2);
output._size = len2;
@@ -610,7 +647,7 @@ bool String::operator==(const String &x) const {
}
bool String::operator==(const char *x) const {
- assert(x != 0);
+ assert(x != nullptr);
return equals(x);
}
@@ -619,7 +656,7 @@ bool String::operator!=(const String &x) const {
}
bool String::operator !=(const char *x) const {
- assert(x != 0);
+ assert(x != nullptr);
return !equals(x);
}
@@ -656,7 +693,7 @@ bool String::equals(const String &x) const {
}
bool String::equals(const char *x) const {
- assert(x != 0);
+ assert(x != nullptr);
return (0 == compareTo(x));
}
@@ -665,7 +702,7 @@ bool String::equalsIgnoreCase(const String &x) const {
}
bool String::equalsIgnoreCase(const char *x) const {
- assert(x != 0);
+ assert(x != nullptr);
return (0 == compareToIgnoreCase(x));
}
@@ -674,7 +711,7 @@ int String::compareTo(const String &x) const {
}
int String::compareTo(const char *x) const {
- assert(x != 0);
+ assert(x != nullptr);
return strcmp(c_str(), x);
}
@@ -683,7 +720,7 @@ int String::compareToIgnoreCase(const String &x) const {
}
int String::compareToIgnoreCase(const char *x) const {
- assert(x != 0);
+ assert(x != nullptr);
return scumm_stricmp(c_str(), x);
}
@@ -741,7 +778,7 @@ String lastPathComponent(const String &path, const char sep) {
const char *last = str + path.size();
// Skip over trailing slashes
- while (last > str && *(last-1) == sep)
+ while (last > str && *(last - 1) == sep)
--last;
// Path consisted of only slashes -> return empty string
@@ -815,13 +852,13 @@ bool matchString(const char *str, const char *pat, bool ignoreCase, bool pathMod
assert(str);
assert(pat);
- const char *p = 0;
- const char *q = 0;
+ const char *p = nullptr;
+ const char *q = nullptr;
for (;;) {
if (pathMode && *str == '/') {
- p = 0;
- q = 0;
+ p = nullptr;
+ q = nullptr;
if (*pat == '?')
return false;
}
@@ -837,8 +874,8 @@ bool matchString(const char *str, const char *pat, bool ignoreCase, bool pathMod
// NB: We can't simply check if pat also ended here, because
// the pattern might end with any number of *s.
++pat;
- p = 0;
- q = 0;
+ p = nullptr;
+ q = nullptr;
}
// If pattern ended with * -> match
if (!*pat)
@@ -1010,7 +1047,7 @@ int scumm_strnicmp(const char *s1, const char *s2, uint n) {
byte l1, l2;
do {
if (n-- == 0)
- return 0; // no difference found so far -> signal equality
+ return 0; // no difference found so far -> signal equality
// Don't use ++ inside tolower, in case the macro uses its
// arguments more than once.
diff --git a/common/str.h b/common/str.h
index fd77fa90c8..7a1706b7e1 100644
--- a/common/str.h
+++ b/common/str.h
@@ -154,9 +154,13 @@ public:
bool hasSuffix(const String &x) const;
bool hasSuffix(const char *x) const;
+ bool hasSuffixIgnoreCase(const String &x) const;
+ bool hasSuffixIgnoreCase(const char *x) const;
bool hasPrefix(const String &x) const;
bool hasPrefix(const char *x) const;
+ bool hasPrefixIgnoreCase(const String &x) const;
+ bool hasPrefixIgnoreCase(const char *x) const;
bool contains(const String &x) const;
bool contains(const char *x) const;
@@ -285,7 +289,7 @@ public:
* except that it stores the result in (variably sized) String
* instead of a fixed size buffer.
*/
- static String format(const char *fmt, ...) GCC_PRINTF(1,2);
+ static String format(const char *fmt, ...) GCC_PRINTF(1, 2);
/**
* Print formatted data into a String object. Similar to vsprintf,
diff --git a/common/stream.cpp b/common/stream.cpp
index 8d93888020..5c9b571af4 100644
--- a/common/stream.cpp
+++ b/common/stream.cpp
@@ -99,7 +99,7 @@ bool MemoryReadStream::seek(int32 offs, int whence) {
// Reset end-of-stream flag on a successful seek
_eos = false;
- return true; // FIXME: STREAM REWRITE
+ return true; // FIXME: STREAM REWRITE
}
bool MemoryWriteStreamDynamic::seek(int32 offs, int whence) {
@@ -124,7 +124,7 @@ bool MemoryWriteStreamDynamic::seek(int32 offs, int whence) {
// Post-Condition
assert(_pos <= _size);
- return true; // FIXME: STREAM REWRITE
+ return true; // FIXME: STREAM REWRITE
}
#pragma mark -
@@ -135,7 +135,7 @@ enum {
};
char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
- assert(buf != 0 && bufSize > 1);
+ assert(buf != nullptr && bufSize > 1);
char *p = buf;
size_t len = 0;
char c = 0;
@@ -143,7 +143,7 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
// If end-of-file occurs before any characters are read, return NULL
// and the buffer contents remain unchanged.
if (eos() || err()) {
- return 0;
+ return nullptr;
}
// Loop as long as there is still free space in the buffer,
@@ -155,7 +155,7 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
// If end-of-file occurs before any characters are read, return
// NULL and the buffer contents remain unchanged.
if (len == 0)
- return 0;
+ return nullptr;
break;
}
@@ -163,7 +163,7 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
// If an error occurs, return NULL and the buffer contents
// are indeterminate.
if (err())
- return 0;
+ return nullptr;
// Check for CR or CR/LF
// * DOS and Windows use CRLF line breaks
@@ -174,7 +174,7 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
c = readByte();
if (err()) {
- return 0; // error: the buffer contents are indeterminate
+ return nullptr; // error: the buffer contents are indeterminate
}
if (eos()) {
// The CR was the last character in the file.
@@ -382,7 +382,7 @@ uint32 BufferedReadStream::read(void *dataPtr, uint32 dataSize) {
ReadStream *wrapBufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream) {
if (parentStream)
return new BufferedReadStream(parentStream, bufSize, disposeParentStream);
- return 0;
+ return nullptr;
}
#pragma mark -
@@ -413,7 +413,7 @@ BufferedSeekableReadStream::BufferedSeekableReadStream(SeekableReadStream *paren
bool BufferedSeekableReadStream::seek(int32 offset, int whence) {
// If it is a "local" seek, we may get away with "seeking" around
// in the buffer only.
- _eos = false; // seeking always cancels EOS
+ _eos = false; // seeking always cancels EOS
int relOffset = 0;
switch (whence) {
@@ -459,7 +459,7 @@ bool BufferedSeekableReadStream::seek(int32 offset, int whence) {
SeekableReadStream *wrapBufferedSeekableReadStream(SeekableReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream) {
if (parentStream)
return new BufferedSeekableReadStream(parentStream, bufSize, disposeParentStream);
- return 0;
+ return nullptr;
}
#pragma mark -
@@ -543,7 +543,7 @@ public:
WriteStream *wrapBufferedWriteStream(WriteStream *parentStream, uint32 bufSize) {
if (parentStream)
return new BufferedWriteStream(parentStream, bufSize);
- return 0;
+ return nullptr;
}
} // End of namespace Common
diff --git a/common/system.cpp b/common/system.cpp
index 131a7d2580..f4568c2240 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -35,47 +35,47 @@
#include "backends/fs/fs-factory.h"
#include "backends/timer/default/default-timer.h"
-OSystem *g_system = 0;
+OSystem *g_system = nullptr;
OSystem::OSystem() {
- _audiocdManager = 0;
- _eventManager = 0;
- _timerManager = 0;
- _savefileManager = 0;
+ _audiocdManager = nullptr;
+ _eventManager = nullptr;
+ _timerManager = nullptr;
+ _savefileManager = nullptr;
#if defined(USE_TASKBAR)
- _taskbarManager = 0;
+ _taskbarManager = nullptr;
#endif
#if defined(USE_UPDATES)
- _updateManager = 0;
+ _updateManager = nullptr;
#endif
- _fsFactory = 0;
+ _fsFactory = nullptr;
}
OSystem::~OSystem() {
delete _audiocdManager;
- _audiocdManager = 0;
+ _audiocdManager = nullptr;
delete _eventManager;
- _eventManager = 0;
+ _eventManager = nullptr;
delete _timerManager;
- _timerManager = 0;
+ _timerManager = nullptr;
#if defined(USE_TASKBAR)
delete _taskbarManager;
- _taskbarManager = 0;
+ _taskbarManager = nullptr;
#endif
#if defined(USE_UPDATES)
delete _updateManager;
- _updateManager = 0;
+ _updateManager = nullptr;
#endif
delete _savefileManager;
- _savefileManager = 0;
+ _savefileManager = nullptr;
delete _fsFactory;
- _fsFactory = 0;
+ _fsFactory = nullptr;
}
void OSystem::initBackend() {
@@ -138,7 +138,7 @@ Common::SeekableReadStream *OSystem::createConfigReadStream() {
Common::WriteStream *OSystem::createConfigWriteStream() {
#ifdef __DC__
- return 0;
+ return nullptr;
#else
Common::FSNode file(getDefaultConfigFileName());
return file.createWriteStream();
diff --git a/common/system.h b/common/system.h
index 206c3134c4..8866a4dcd2 100644
--- a/common/system.h
+++ b/common/system.h
@@ -324,8 +324,8 @@ public:
kFeatureDisplayLogFile,
/**
- * The presence of this feature indicates whether the hasTextInClipboard()
- * and getTextFromClipboard() calls are supported.
+ * The presence of this feature indicates whether the hasTextInClipboard(),
+ * getTextFromClipboard() and setTextInClipboard() calls are supported.
*
* This feature has no associated state.
*/
@@ -587,7 +587,7 @@ public:
* @return a list of supported shaders
*/
virtual const GraphicsMode *getSupportedShaders() const {
- static const OSystem::GraphicsMode no_shader[2] = {{"NONE", "Normal (no shader)", 0}, {0, 0, 0}};
+ static const OSystem::GraphicsMode no_shader[2] = {{"NONE", "Normal (no shader)", 0}, {nullptr, nullptr, 0}};
return no_shader;
}
@@ -632,7 +632,7 @@ public:
* @param height the new virtual screen height
* @param format the new virtual screen pixel format
*/
- virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) = 0;
+ virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = nullptr) = 0;
/**
* Send a list of graphics modes to the backend so it can make a decision
@@ -964,7 +964,7 @@ public:
* would be too small to notice otherwise, these are allowed to scale the cursor anyway.
* @param format pointer to the pixel format which cursor graphic uses (0 means CLUT8)
*/
- virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) = 0;
+ virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = nullptr) = 0;
/**
* Replace the specified range of cursor the palette with new colors.
@@ -1028,7 +1028,7 @@ public:
*
* See keymapper documentation for further reference.
*/
- virtual Common::HardwareInputSet *getHardwareInputSet() { return 0; }
+ virtual Common::HardwareInputSet *getHardwareInputSet() { return nullptr; }
/**
* Return a platform-specific global keymap
@@ -1041,7 +1041,7 @@ public:
*
* See keymapper documentation for further reference.
*/
- virtual Common::Keymap *getGlobalKeymap() { return 0; }
+ virtual Common::Keymap *getGlobalKeymap() { return nullptr; }
/**
* Return platform-specific default keybindings
@@ -1052,7 +1052,7 @@ public:
*
* See keymapper documentation for further reference.
*/
- virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() { return 0; }
+ virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() { return nullptr; }
#endif
//@}
@@ -1336,6 +1336,17 @@ public:
virtual Common::String getTextFromClipboard() { return ""; }
/**
+ * Set the content of the clipboard to the given string.
+ *
+ * The kFeatureClipboardSupport feature flag can be used to
+ * test whether this call has been implemented by the active
+ * backend.
+ *
+ * @return true if the text was properly set in the clipboard, false otherwise
+ */
+ virtual bool setTextInClipboard(const Common::String &text) { return false; }
+
+ /**
* Open the given Url in the default browser (if available on the target
* system).
*
diff --git a/common/textconsole.cpp b/common/textconsole.cpp
index 5c69e42379..d533c4b7e4 100644
--- a/common/textconsole.cpp
+++ b/common/textconsole.cpp
@@ -28,13 +28,13 @@
namespace Common {
-static OutputFormatter s_errorOutputFormatter = 0;
+static OutputFormatter s_errorOutputFormatter = nullptr;
void setErrorOutputFormatter(OutputFormatter f) {
s_errorOutputFormatter = f;
}
-static ErrorHandler s_errorHandler = 0;
+static ErrorHandler s_errorHandler = nullptr;
void setErrorHandler(ErrorHandler handler) {
s_errorHandler = handler;
diff --git a/common/translation.cpp b/common/translation.cpp
index 01665bf876..35e5b6e4c3 100644
--- a/common/translation.cpp
+++ b/common/translation.cpp
@@ -46,7 +46,7 @@ bool operator<(const TLanguage &l, const TLanguage &r) {
return strcmp(l.name, r.name) < 0;
}
-TranslationManager::TranslationManager() : _currentLang(-1), _charmap(0) {
+TranslationManager::TranslationManager() : _currentLang(-1), _charmap(nullptr) {
loadTranslationsInfoDat();
// Set the default language
@@ -110,7 +110,7 @@ void TranslationManager::setLanguage(const String &lang) {
}
const char *TranslationManager::getTranslation(const char *message) const {
- return getTranslation(message, NULL);
+ return getTranslation(message, nullptr);
}
const char *TranslationManager::getTranslation(const char *message, const char *context) const {
@@ -144,7 +144,7 @@ const char *TranslationManager::getTranslation(const char *message, const char *
++rightIndex;
}
// Find the context we want
- if (context == NULL || *context == '\0' || leftIndex == rightIndex)
+ if (context == nullptr || *context == '\0' || leftIndex == rightIndex)
return _currentTranslationMessages[leftIndex].msgstr.c_str();
// We could use again binary search, but there should be only a small number of contexts.
while (rightIndex > leftIndex) {
@@ -416,7 +416,7 @@ void TranslationManager::loadLanguageDat(int index) {
// Setup the new charset mapping
if (charmapNum == -1) {
delete[] _charmap;
- _charmap = 0;
+ _charmap = nullptr;
} else {
if (!_charmap)
_charmap = new uint32[256];
diff --git a/common/translation.h b/common/translation.h
index e316507fdb..3dd7039cf3 100644
--- a/common/translation.h
+++ b/common/translation.h
@@ -44,7 +44,7 @@ struct TLanguage {
const char *name;
int id;
- TLanguage() : name(0), id(0) {}
+ TLanguage() : name(nullptr), id(0) {}
TLanguage(const char *n, int i) : name(n), id(i) {}
};
diff --git a/common/unarj.cpp b/common/unarj.cpp
index e8aed7cbd1..9737521245 100644
--- a/common/unarj.cpp
+++ b/common/unarj.cpp
@@ -95,8 +95,8 @@ class ArjDecoder {
public:
ArjDecoder(const ArjHeader *hdr) {
_compsize = hdr->compSize;
- _compressed = 0;
- _outstream = 0;
+ _compressed = nullptr;
+ _outstream = nullptr;
_bitbuf = 0;
_bytebuf = 0;
_bitcount = 0;
@@ -251,16 +251,16 @@ ArjHeader *readHeader(SeekableReadStream &stream) {
if (header.id != HEADER_ID) {
warning("ArjFile::readHeader(): Bad header ID (%x)", header.id);
- return NULL;
+ return nullptr;
}
header.headerSize = stream.readUint16LE();
if (header.headerSize == 0)
- return NULL; // end of archive
+ return nullptr; // end of archive
if (header.headerSize > HEADERSIZE_MAX) {
warning("ArjFile::readHeader(): Bad header");
- return NULL;
+ return nullptr;
}
int rSize = stream.read(headData, header.headerSize);
@@ -270,7 +270,7 @@ ArjHeader *readHeader(SeekableReadStream &stream) {
header.headerCrc = stream.readUint32LE();
if (CRC32::checksum(headData, header.headerSize) != header.headerCrc) {
warning("ArjFile::readHeader(): Bad header CRC");
- return NULL;
+ return nullptr;
}
header.firstHdrSize = readS.readByte();
@@ -292,7 +292,7 @@ ArjHeader *readHeader(SeekableReadStream &stream) {
// static int check_file_size()
if (header.origSize < 0 || header.compSize < 0) {
warning("ArjFile::readHeader(): Wrong file size");
- return NULL;
+ return nullptr;
}
strlcpy(header.filename, (const char *)&headData[header.firstHdrSize], ARJ_FILENAME_MAX);
@@ -723,14 +723,14 @@ ArjArchive::ArjArchive(const String &filename) : _arjFilename(filename) {
return;
}
- ArjHeader *header = NULL;
+ ArjHeader *header = nullptr;
arjFile.seek(firstHeaderOffset, SEEK_SET);
- if ((header = readHeader(arjFile)) == NULL)
+ if ((header = readHeader(arjFile)) == nullptr)
return;
delete header;
- while ((header = readHeader(arjFile)) != NULL) {
+ while ((header = readHeader(arjFile)) != nullptr) {
_headers[header->filename] = header;
arjFile.seek(header->compSize, SEEK_CUR);
}
@@ -771,7 +771,7 @@ const ArchiveMemberPtr ArjArchive::getMember(const String &name) const {
SeekableReadStream *ArjArchive::createReadStreamForMember(const String &name) const {
if (!_headers.contains(name)) {
- return 0;
+ return nullptr;
}
ArjHeader *hdr = _headers[name];
diff --git a/common/unzip.cpp b/common/unzip.cpp
index 1f4e601989..2e7a3f8b81 100644
--- a/common/unzip.cpp
+++ b/common/unzip.cpp
@@ -480,18 +480,18 @@ static uLong unzlocal_SearchCentralDir(Common::SeekableReadStream &fin) {
uMaxBack = uSizeFile;
buf = (unsigned char*)malloc(BUFREADCOMMENT+4);
- if (buf==NULL)
+ if (buf==nullptr)
return 0;
uBackRead = 4;
while (uBackRead<uMaxBack) {
- uLong uReadSize,uReadPos ;
+ uLong uReadSize,uReadPos;
int i;
if (uBackRead+BUFREADCOMMENT>uMaxBack)
uBackRead = uMaxBack;
else
uBackRead+=BUFREADCOMMENT;
- uReadPos = uSizeFile-uBackRead ;
+ uReadPos = uSizeFile-uBackRead;
uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
(BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
@@ -528,7 +528,7 @@ static uLong unzlocal_SearchCentralDir(Common::SeekableReadStream &fin) {
*/
unzFile unzOpen(Common::SeekableReadStream *stream) {
if (!stream)
- return NULL;
+ return nullptr;
unz_s *us = new unz_s;
uLong central_pos,uL;
@@ -597,21 +597,21 @@ unzFile unzOpen(Common::SeekableReadStream *stream) {
if (err != UNZ_OK) {
delete us->_stream;
delete us;
- return NULL;
+ return nullptr;
}
us->byte_before_the_zipfile = central_pos -
(us->offset_central_dir+us->size_central_dir);
us->central_pos = central_pos;
- us->pfile_in_zip_read = NULL;
+ us->pfile_in_zip_read = nullptr;
err = unzGoToFirstFile((unzFile)us);
while (err == UNZ_OK) {
// Get the file details
char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
- unzGetCurrentFileInfo(us, NULL, szCurrentFileName, sizeof(szCurrentFileName) - 1,
- NULL, 0, NULL, 0);
+ unzGetCurrentFileInfo(us, nullptr, szCurrentFileName, sizeof(szCurrentFileName) - 1,
+ nullptr, 0, nullptr, 0);
// Save details into the hash
cached_file_in_zip fe;
@@ -637,11 +637,11 @@ unzFile unzOpen(Common::SeekableReadStream *stream) {
return UNZ_OK if there is no problem. */
int unzClose(unzFile file) {
unz_s *s;
- if (file == NULL)
+ if (file == nullptr)
return UNZ_PARAMERROR;
s = (unz_s *)file;
- if (s->pfile_in_zip_read != NULL)
+ if (s->pfile_in_zip_read != nullptr)
unzCloseCurrentFile(file);
delete s->_stream;
@@ -656,7 +656,7 @@ int unzClose(unzFile file) {
return UNZ_OK if there is no problem. */
int unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info) {
unz_s *s;
- if (file == NULL)
+ if (file == nullptr)
return UNZ_PARAMERROR;
s = (unz_s *)file;
*pglobal_info = s->gi;
@@ -670,13 +670,13 @@ int unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info) {
static void unzlocal_DosDateToTmuDate(uLong ulDosDate, tm_unz* ptm) {
uLong uDate;
uDate = (uLong)(ulDosDate>>16);
- ptm->tm_mday = (uInt)(uDate&0x1f) ;
- ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
- ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+ ptm->tm_mday = (uInt)(uDate&0x1f);
+ ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1);
+ ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980);
ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
- ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
- ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
+ ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20);
+ ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f));
}
/*
@@ -707,7 +707,7 @@ static int unzlocal_GetCurrentFileInfoInternal(unzFile file,
uLong uMagic;
long lSeek=0;
- if (file==NULL)
+ if (file==nullptr)
return UNZ_PARAMERROR;
s=(unz_s*)file;
s->_stream->seek(s->pos_in_central_dir+s->byte_before_the_zipfile, SEEK_SET);
@@ -771,8 +771,8 @@ static int unzlocal_GetCurrentFileInfoInternal(unzFile file,
err=UNZ_ERRNO;
lSeek+=file_info.size_filename;
- if ((err==UNZ_OK) && (szFileName!=NULL)) {
- uLong uSizeRead ;
+ if ((err==UNZ_OK) && (szFileName!=nullptr)) {
+ uLong uSizeRead;
if (file_info.size_filename<fileNameBufferSize) {
*(szFileName+file_info.size_filename)='\0';
uSizeRead = file_info.size_filename;
@@ -786,8 +786,8 @@ static int unzlocal_GetCurrentFileInfoInternal(unzFile file,
}
- if ((err==UNZ_OK) && (extraField!=NULL)) {
- uLong uSizeRead ;
+ if ((err==UNZ_OK) && (extraField!=nullptr)) {
+ uLong uSizeRead;
if (file_info.size_file_extra<extraFieldBufferSize)
uSizeRead = file_info.size_file_extra;
else
@@ -809,8 +809,8 @@ static int unzlocal_GetCurrentFileInfoInternal(unzFile file,
lSeek+=file_info.size_file_extra;
- if ((err==UNZ_OK) && (szComment!=NULL)) {
- uLong uSizeRead ;
+ if ((err==UNZ_OK) && (szComment!=nullptr)) {
+ uLong uSizeRead;
if (file_info.size_file_comment<commentBufferSize) {
*(szComment+file_info.size_file_comment)='\0';
uSizeRead = file_info.size_file_comment;
@@ -831,10 +831,10 @@ static int unzlocal_GetCurrentFileInfoInternal(unzFile file,
} else
lSeek+=file_info.size_file_comment;
- if ((err==UNZ_OK) && (pfile_info!=NULL))
+ if ((err==UNZ_OK) && (pfile_info!=nullptr))
*pfile_info=file_info;
- if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+ if ((err==UNZ_OK) && (pfile_info_internal!=nullptr))
*pfile_info_internal=file_info_internal;
return err;
@@ -853,7 +853,7 @@ int unzGetCurrentFileInfo(unzFile file,
void *extraField, uLong extraFieldBufferSize,
char *szComment, uLong commentBufferSize)
{
- return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+ return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,nullptr,
szFileName,fileNameBufferSize,
extraField,extraFieldBufferSize,
szComment,commentBufferSize);
@@ -866,14 +866,14 @@ int unzGetCurrentFileInfo(unzFile file,
int unzGoToFirstFile(unzFile file) {
int err=UNZ_OK;
unz_s* s;
- if (file==NULL)
+ if (file==nullptr)
return UNZ_PARAMERROR;
s=(unz_s*)file;
s->pos_in_central_dir=s->offset_central_dir;
s->num_file=0;
err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
&s->cur_file_info_internal,
- NULL,0,NULL,0,NULL,0);
+ nullptr,0,nullptr,0,nullptr,0);
s->current_file_ok = (err == UNZ_OK);
return err;
}
@@ -888,7 +888,7 @@ int unzGoToNextFile(unzFile file) {
unz_s* s;
int err;
- if (file==NULL)
+ if (file==nullptr)
return UNZ_PARAMERROR;
s=(unz_s*)file;
if (!s->current_file_ok)
@@ -897,11 +897,11 @@ int unzGoToNextFile(unzFile file) {
return UNZ_END_OF_LIST_OF_FILE;
s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
- s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+ s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
s->num_file++;
err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
&s->cur_file_info_internal,
- NULL,0,NULL,0,NULL,0);
+ nullptr,0,nullptr,0,nullptr,0);
s->current_file_ok = (err == UNZ_OK);
return err;
}
@@ -917,7 +917,7 @@ int unzGoToNextFile(unzFile file) {
int unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) {
unz_s* s;
- if (file==NULL)
+ if (file==nullptr)
return UNZ_PARAMERROR;
if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
@@ -1047,13 +1047,13 @@ int unzOpenCurrentFile (unzFile file) {
uLong offset_local_extrafield; /* offset of the local extra field */
uInt size_local_extrafield; /* size of the local extra field */
- if (file==NULL)
+ if (file==nullptr)
return UNZ_PARAMERROR;
s=(unz_s*)file;
if (!s->current_file_ok)
return UNZ_PARAMERROR;
- if (s->pfile_in_zip_read != NULL)
+ if (s->pfile_in_zip_read != nullptr)
unzCloseCurrentFile(file);
if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
@@ -1062,7 +1062,7 @@ int unzOpenCurrentFile (unzFile file) {
pfile_in_zip_read_info = (file_in_zip_read_info_s*) malloc(sizeof(file_in_zip_read_info_s));
- if (pfile_in_zip_read_info==NULL)
+ if (pfile_in_zip_read_info==nullptr)
return UNZ_INTERNALERROR;
pfile_in_zip_read_info->read_buffer=(char *)malloc(UNZ_BUFSIZE);
@@ -1070,7 +1070,7 @@ int unzOpenCurrentFile (unzFile file) {
pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
pfile_in_zip_read_info->pos_local_extrafield=0;
- if (pfile_in_zip_read_info->read_buffer==NULL)
+ if (pfile_in_zip_read_info->read_buffer==nullptr)
{
free(pfile_in_zip_read_info);
return UNZ_INTERNALERROR;
@@ -1093,9 +1093,9 @@ int unzOpenCurrentFile (unzFile file) {
if (!Store) {
#ifdef USE_ZLIB
- pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
- pfile_in_zip_read_info->stream.zfree = (free_func)0;
- pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)nullptr;
+ pfile_in_zip_read_info->stream.zfree = (free_func)nullptr;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)nullptr;
err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
if (err == Z_OK)
@@ -1140,16 +1140,16 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
uInt iRead = 0;
unz_s* s;
file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==NULL)
+ if (file==nullptr)
return UNZ_PARAMERROR;
s=(unz_s*)file;
pfile_in_zip_read_info=s->pfile_in_zip_read;
- if (pfile_in_zip_read_info==NULL)
+ if (pfile_in_zip_read_info==nullptr)
return UNZ_PARAMERROR;
- if (pfile_in_zip_read_info->read_buffer == NULL)
+ if (pfile_in_zip_read_info->read_buffer == nullptr)
return UNZ_END_OF_LIST_OF_FILE;
if (len==0)
return 0;
@@ -1185,11 +1185,11 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
}
if (pfile_in_zip_read_info->compression_method==0) {
- uInt uDoCopy,i ;
+ uInt uDoCopy,i;
if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in)
- uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+ uDoCopy = pfile_in_zip_read_info->stream.avail_out;
else
- uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+ uDoCopy = pfile_in_zip_read_info->stream.avail_in;
for (i=0;i<uDoCopy;i++)
*(pfile_in_zip_read_info->stream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i);
@@ -1258,12 +1258,12 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
z_off_t unztell(unzFile file) {
unz_s* s;
file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==NULL)
+ if (file==nullptr)
return UNZ_PARAMERROR;
s=(unz_s*)file;
pfile_in_zip_read_info=s->pfile_in_zip_read;
- if (pfile_in_zip_read_info==NULL)
+ if (pfile_in_zip_read_info==nullptr)
return UNZ_PARAMERROR;
return (z_off_t)pfile_in_zip_read_info->stream.total_out;
@@ -1276,12 +1276,12 @@ z_off_t unztell(unzFile file) {
int unzeof(unzFile file) {
unz_s* s;
file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file==NULL)
+ if (file==nullptr)
return UNZ_PARAMERROR;
s=(unz_s*)file;
pfile_in_zip_read_info=s->pfile_in_zip_read;
- if (pfile_in_zip_read_info==NULL)
+ if (pfile_in_zip_read_info==nullptr)
return UNZ_PARAMERROR;
if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
@@ -1310,24 +1310,24 @@ int unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) {
uInt read_now;
uLong size_to_read;
- if (file==NULL)
+ if (file==nullptr)
return UNZ_PARAMERROR;
s=(unz_s*)file;
pfile_in_zip_read_info=s->pfile_in_zip_read;
- if (pfile_in_zip_read_info==NULL)
+ if (pfile_in_zip_read_info==nullptr)
return UNZ_PARAMERROR;
size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
pfile_in_zip_read_info->pos_local_extrafield);
- if (buf==NULL)
+ if (buf==nullptr)
return (int)size_to_read;
if (len>size_to_read)
read_now = (uInt)size_to_read;
else
- read_now = (uInt)len ;
+ read_now = (uInt)len;
if (read_now==0)
return 0;
@@ -1352,12 +1352,12 @@ int unzCloseCurrentFile(unzFile file) {
unz_s* s;
file_in_zip_read_info_s* pfile_in_zip_read_info;
- if (file == NULL)
+ if (file == nullptr)
return UNZ_PARAMERROR;
s = (unz_s*)file;
pfile_in_zip_read_info = s->pfile_in_zip_read;
- if (pfile_in_zip_read_info == NULL)
+ if (pfile_in_zip_read_info == nullptr)
return UNZ_PARAMERROR;
@@ -1374,12 +1374,12 @@ int unzCloseCurrentFile(unzFile file) {
free(pfile_in_zip_read_info->read_buffer);
- pfile_in_zip_read_info->read_buffer = NULL;
+ pfile_in_zip_read_info->read_buffer = nullptr;
pfile_in_zip_read_info->stream_initialized = 0;
free(pfile_in_zip_read_info);
- s->pfile_in_zip_read=NULL;
+ s->pfile_in_zip_read=nullptr;
return err;
}
@@ -1392,8 +1392,8 @@ int unzCloseCurrentFile(unzFile file) {
*/
int unzGetGlobalComment(unzFile file, char *szComment, uLong uSizeBuf) {
unz_s* s;
- uLong uReadThis ;
- if (file==NULL)
+ uLong uReadThis;
+ if (file==nullptr)
return UNZ_PARAMERROR;
s=(unz_s*)file;
@@ -1411,7 +1411,7 @@ int unzGetGlobalComment(unzFile file, char *szComment, uLong uSizeBuf) {
return UNZ_ERRNO;
}
- if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+ if ((szComment != nullptr) && (uSizeBuf > s->gi.size_comment))
*(szComment+s->gi.size_comment)='\0';
return (int)uReadThis;
}
@@ -1487,26 +1487,26 @@ const ArchiveMemberPtr ZipArchive::getMember(const String &name) const {
SeekableReadStream *ZipArchive::createReadStreamForMember(const String &name) const {
if (unzLocateFile(_zipFile, name.c_str(), 2) != UNZ_OK)
- return 0;
+ return nullptr;
unz_file_info fileInfo;
if (unzOpenCurrentFile(_zipFile) != UNZ_OK)
- return 0;
+ return nullptr;
- if (unzGetCurrentFileInfo(_zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0) != UNZ_OK)
- return 0;
+ if (unzGetCurrentFileInfo(_zipFile, &fileInfo, nullptr, 0, nullptr, 0, nullptr, 0) != UNZ_OK)
+ return nullptr;
byte *buffer = (byte *)malloc(fileInfo.uncompressed_size);
assert(buffer);
if (unzReadCurrentFile(_zipFile, buffer, fileInfo.uncompressed_size) != (int)fileInfo.uncompressed_size) {
free(buffer);
- return 0;
+ return nullptr;
}
if (unzCloseCurrentFile(_zipFile) != UNZ_OK) {
free(buffer);
- return 0;
+ return nullptr;
}
return new MemoryReadStream(buffer, fileInfo.uncompressed_size, DisposeAfterUse::YES);
@@ -1527,12 +1527,12 @@ Archive *makeZipArchive(const FSNode &node) {
Archive *makeZipArchive(SeekableReadStream *stream) {
if (!stream)
- return 0;
+ return nullptr;
unzFile zipFile = unzOpen(stream);
if (!zipFile) {
// stream gets deleted by unzOpen() call if something
// goes wrong.
- return 0;
+ return nullptr;
}
return new ZipArchive(zipFile);
}
diff --git a/common/updates.cpp b/common/updates.cpp
index 087002a7d3..4e4ed53b8f 100644
--- a/common/updates.cpp
+++ b/common/updates.cpp
@@ -47,7 +47,7 @@ int UpdateManager::normalizeInterval(int interval) {
val++;
}
- return val[-1]; // Return maximal acceptable value
+ return val[-1]; // Return maximal acceptable value
}
const char *UpdateManager::updateIntervalToString(int interval) {
diff --git a/common/updates.h b/common/updates.h
index 3a3049d4df..812aac718e 100644
--- a/common/updates.h
+++ b/common/updates.h
@@ -50,7 +50,7 @@ public:
kUpdateIntervalNotSupported = 0,
kUpdateIntervalOneDay = 86400,
kUpdateIntervalOneWeek = 604800,
- kUpdateIntervalOneMonth = 2628000 // average seconds per month (60*60*24*365)/12
+ kUpdateIntervalOneMonth = 2628000 // average seconds per month (60*60*24*365)/12
};
UpdateManager() {}
diff --git a/common/ustr.cpp b/common/ustr.cpp
index 35b5502a6d..85946cda46 100644
--- a/common/ustr.cpp
+++ b/common/ustr.cpp
@@ -34,7 +34,7 @@ static uint32 computeCapacity(uint32 len) {
}
U32String::U32String(const value_type *str) : _size(0), _str(_storage) {
- if (str == 0) {
+ if (str == nullptr) {
_storage[0] = 0;
_size = 0;
} else {
@@ -69,7 +69,7 @@ U32String::U32String(const U32String &str)
_extern._capacity = str._extern._capacity;
_str = str._str;
}
- assert(_str != 0);
+ assert(_str != nullptr);
}
U32String::~U32String() {
@@ -239,7 +239,7 @@ void U32String::ensureCapacity(uint32 new_size, bool keep_old) {
if (new_size < curCapacity)
newCapacity = curCapacity;
else
- newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1));
+ newCapacity = MAX(curCapacity * 2, computeCapacity(new_size + 1));
// Allocate new storage
newStorage = new value_type[newCapacity];
@@ -265,15 +265,15 @@ void U32String::ensureCapacity(uint32 new_size, bool keep_old) {
// Set the ref count & capacity if we use an external storage.
// It is important to do this *after* copying any old content,
// else we would override data that has not yet been copied!
- _extern._refCount = 0;
+ _extern._refCount = nullptr;
_extern._capacity = newCapacity;
}
}
void U32String::incRefCount() const {
assert(!isStorageIntern());
- if (_extern._refCount == 0) {
- if (g_refCountPool == 0) {
+ if (_extern._refCount == nullptr) {
+ if (g_refCountPool == nullptr) {
g_refCountPool = new MemoryPool(sizeof(int));
assert(g_refCountPool);
}
@@ -316,10 +316,10 @@ void U32String::initWithCStr(const value_type *str, uint32 len) {
if (len >= _builtinCapacity) {
// Not enough internal storage, so allocate more
- _extern._capacity = computeCapacity(len+1);
- _extern._refCount = 0;
+ _extern._capacity = computeCapacity(len + 1);
+ _extern._refCount = nullptr;
_str = new value_type[_extern._capacity];
- assert(_str != 0);
+ assert(_str != nullptr);
}
// Copy the string into the storage area
diff --git a/common/util.h b/common/util.h
index a098a6a437..2d6a36d086 100644
--- a/common/util.h
+++ b/common/util.h
@@ -123,7 +123,7 @@ bool isAlnum(int c);
* false is returned.
*
* @param c the character to test
- * @return true if the character is TODO, false otherwise.
+ * @return true if the character is alphabetic, false otherwise.
*/
bool isAlpha(int c);
diff --git a/common/winexe_ne.cpp b/common/winexe_ne.cpp
index ccf1fd17e5..2d46cb2554 100644
--- a/common/winexe_ne.cpp
+++ b/common/winexe_ne.cpp
@@ -30,7 +30,7 @@
namespace Common {
NEResources::NEResources() {
- _exe = 0;
+ _exe = nullptr;
}
NEResources::~NEResources() {
@@ -40,7 +40,7 @@ NEResources::~NEResources() {
void NEResources::clear() {
if (_exe) {
delete _exe;
- _exe = 0;
+ _exe = nullptr;
}
_resources.clear();
@@ -270,14 +270,14 @@ const NEResources::Resource *NEResources::findResource(const WinResourceID &type
if (it->type == type && it->id == id)
return &*it;
- return 0;
+ return nullptr;
}
SeekableReadStream *NEResources::getResource(const WinResourceID &type, const WinResourceID &id) {
const Resource *res = findResource(type, id);
if (!res)
- return 0;
+ return nullptr;
_exe->seek(res->offset);
return _exe->readStream(res->size);
diff --git a/common/winexe_pe.cpp b/common/winexe_pe.cpp
index 969ea5d923..042c347c47 100644
--- a/common/winexe_pe.cpp
+++ b/common/winexe_pe.cpp
@@ -31,7 +31,7 @@
namespace Common {
PEResources::PEResources() {
- _exe = 0;
+ _exe = nullptr;
}
PEResources::~PEResources() {
@@ -41,7 +41,7 @@ PEResources::~PEResources() {
void PEResources::clear() {
_sections.clear();
_resources.clear();
- delete _exe; _exe = 0;
+ delete _exe; _exe = nullptr;
}
bool PEResources::loadFromEXE(const String &fileName) {
@@ -224,7 +224,7 @@ SeekableReadStream *PEResources::getResource(const WinResourceID &type, const Wi
Array<WinResourceID> langList = getLangList(type, name);
if (langList.empty())
- return 0;
+ return nullptr;
const Resource &resource = _resources[type][name][langList[0]];
_exe->seek(resource.offset);
@@ -233,17 +233,17 @@ SeekableReadStream *PEResources::getResource(const WinResourceID &type, const Wi
SeekableReadStream *PEResources::getResource(const WinResourceID &type, const WinResourceID &name, const WinResourceID &lang) {
if (!_exe || !_resources.contains(type))
- return 0;
+ return nullptr;
const NameMap &nameMap = _resources[type];
if (!nameMap.contains(name))
- return 0;
+ return nullptr;
const LangMap &langMap = nameMap[name];
if (!langMap.contains(lang))
- return 0;
+ return nullptr;
const Resource &resource = langMap[lang];
_exe->seek(resource.offset);
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index 4470180710..48203e8fe5 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -74,7 +74,7 @@ bool XMLParser::loadStream(SeekableReadStream *stream) {
void XMLParser::close() {
delete _stream;
- _stream = 0;
+ _stream = nullptr;
}
bool XMLParser::parserError(const String &errStr) {
@@ -299,13 +299,13 @@ bool XMLParser::closeKey() {
}
bool XMLParser::parse() {
- if (_stream == 0)
+ if (_stream == nullptr)
return false;
// Make sure we are at the start of the stream.
_stream->seek(0, SEEK_SET);
- if (_XMLkeys == 0)
+ if (_XMLkeys == nullptr)
buildLayout();
while (!_activeKey.empty())
@@ -373,12 +373,12 @@ bool XMLParser::parse() {
break;
}
} else {
- ParserNode *node = allocNode(); //new ParserNode;
+ ParserNode *node = allocNode(); // new ParserNode;
node->name = _token;
node->ignore = false;
node->header = activeHeader;
node->depth = _activeKey.size();
- node->layout = 0;
+ node->layout = nullptr;
_activeKey.push(node);
}
diff --git a/common/xmlparser.h b/common/xmlparser.h
index 1e474b596c..2e4596ac0f 100644
--- a/common/xmlparser.h
+++ b/common/xmlparser.h
@@ -92,7 +92,7 @@ public:
/**
* Parser constructor.
*/
- XMLParser() : _XMLkeys(0), _stream(0) {}
+ XMLParser() : _XMLkeys(nullptr), _stream(nullptr) {}
virtual ~XMLParser();
@@ -195,7 +195,7 @@ public:
if (!_activeKey.empty())
return _activeKey.top();
- return 0;
+ return nullptr;
}
/**
diff --git a/common/zlib.cpp b/common/zlib.cpp
index 39130beb4e..6afffb14d2 100644
--- a/common/zlib.cpp
+++ b/common/zlib.cpp
@@ -71,7 +71,7 @@ bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen,
return false;
// Set the dictionary, if provided
- if (dict != 0) {
+ if (dict != nullptr) {
err = inflateSetDictionary(&stream, const_cast<byte *>(dict), dictLen);
if (err != Z_OK)
return false;
@@ -168,7 +168,7 @@ protected:
public:
GZipReadStream(SeekableReadStream *w, uint32 knownSize = 0) : _wrapped(w), _stream() {
- assert(w != 0);
+ assert(w != nullptr);
// Verify file header is correct
w->seek(0, SEEK_SET);
@@ -281,7 +281,7 @@ public:
_wrapped->seek(0, SEEK_SET);
_zlibErr = inflateReset(&_stream);
if (_zlibErr != Z_OK)
- return false; // FIXME: STREAM REWRITE
+ return false; // FIXME: STREAM REWRITE
_stream.next_in = _buf;
_stream.avail_in = 0;
}
@@ -297,7 +297,7 @@ public:
}
_eos = false;
- return true; // FIXME: STREAM REWRITE
+ return true; // FIXME: STREAM REWRITE
}
};
@@ -335,7 +335,7 @@ protected:
public:
GZipWriteStream(WriteStream *w) : _wrapped(w), _stream(), _pos(0) {
- assert(w != 0);
+ assert(w != nullptr);
// Adding 16 to windowBits indicates to zlib that it is supposed to
// write gzip headers. This feature was added in zlib 1.2.0.4,
@@ -352,7 +352,7 @@ public:
_stream.next_out = _buf;
_stream.avail_out = BUFSIZE;
_stream.avail_in = 0;
- _stream.next_in = 0;
+ _stream.next_in = nullptr;
}
~GZipWriteStream() {
diff --git a/common/zlib.h b/common/zlib.h
index c8877e98a1..eb0548344d 100644
--- a/common/zlib.h
+++ b/common/zlib.h
@@ -75,7 +75,7 @@ bool uncompress(byte *dst, unsigned long *dstLen, const byte *src, unsigned long
*
* @return true on success (Z_OK or Z_STREAM_END), false otherwise.
*/
-bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, const byte *dict = 0, uint dictLen = 0);
+bool inflateZlibHeaderless(byte *dst, uint dstLen, const byte *src, uint srcLen, const byte *dict = nullptr, uint dictLen = 0);
/**
* Wrapper around zlib's inflate functions. This function will call the
diff --git a/configure b/configure
index caaef90e32..7898a44534 100755
--- a/configure
+++ b/configure
@@ -134,6 +134,7 @@ _tremor=auto
_tremolo=no
_flac=auto
_mad=auto
+_opl2lpt=no
_alsa=auto
_seq_midi=auto
_sndio=auto
@@ -187,6 +188,7 @@ _plugin_suffix=
_nasm=auto
_optimization_level=
_default_optimization_level=-O2
+_nuked_opl=yes
# Default commands
_ranlib=ranlib
_strip=strip
@@ -219,6 +221,7 @@ _have_x86=no
# Add (virtual) features
add_feature 16bit "16bit color" "_16bit"
+add_feature bink "Bink" "_bink"
add_feature cloud "cloud" "_cloud"
add_feature faad "libfaad" "_faad"
add_feature flac "FLAC" "_flac"
@@ -381,6 +384,16 @@ define_in_config_if_yes() {
fi
}
+define_in_config_if_no() {
+ if test "$1" = no ; then
+ add_line_to_config_h "#define $2"
+ add_line_to_config_mk "$2 = 1"
+ else
+ add_line_to_config_h "#undef $2"
+ add_line_to_config_mk "# $2 = 1"
+ fi
+}
+
#
# Determine sdl-config
#
@@ -969,6 +982,7 @@ Optional Features:
--enable-plugins enable the support for dynamic plugins
--default-dynamic make plugins dynamic by default
--disable-mt32emu don't enable the integrated MT-32 emulator
+ --disable-nuked-opl don't build Nuked OPL driver
--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
@@ -1037,6 +1051,9 @@ Optional Libraries:
installed (optional)
--disable-fluidsynth disable fluidsynth MIDI driver [autodetect]
+ --with-ieee1284-prefix=DIR prefix where libieee1284 is installed (optional)
+ --enable-opl2lpt enable OPL2LPT support
+
--with-sparkle-prefix=DIR prefix where sparkle is installed
(OS X/Windows only - optional)
--disable-sparkle disable sparkle automatic update support
@@ -1122,6 +1139,8 @@ for ac_option in $@; do
--disable-vorbis) _vorbis=no ;;
--enable-tremor) _tremor=yes ;;
--disable-tremor) _tremor=no ;;
+ --enable-opl2lpt) _opl2lpt=yes ;;
+ --disable-opl2lpt) _opl2lpt=no ;;
--enable-flac) _flac=yes ;;
--disable-flac) _flac=no ;;
--enable-mad) _mad=yes ;;
@@ -1171,6 +1190,8 @@ for ac_option in $@; do
--default-dynamic) _plugins_default=dynamic ;;
--enable-mt32emu) _mt32emu=yes ;;
--disable-mt32emu) _mt32emu=no ;;
+ --enable-nuked-opl) _nuked_opl=yes ;;
+ --disable-nuked-opl) _nuked_opl=no ;;
--enable-translation) _translation=yes ;;
--disable-translation) _translation=no ;;
--enable-vkeybd) _vkeybd=yes ;;
@@ -1216,6 +1237,11 @@ for ac_option in $@; do
TREMOR_CFLAGS="-I$arg/include"
TREMOR_LIBS="-L$arg/lib"
;;
+ --with-ieee1284-prefix=*)
+ arg=`echo $ac_option | cut -d '=' -f 2`
+ IEEE1284_CFLAGS="-I$arg/include"
+ IEEE1284_LIBS="-L$arg/lib"
+ ;;
--with-flac-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
FLAC_CFLAGS="-I$arg/include"
@@ -1476,7 +1502,7 @@ dreamcast)
ds)
_host_os=ds
_host_cpu=arm
- _host_alias=arm-eabi
+ _host_alias=arm-none-eabi
;;
gamecube)
_host_os=gamecube
@@ -2326,6 +2352,7 @@ case $_host_os in
append_var CXXFLAGS "-Wno-format"
add_line_to_config_mk 'AMIGAOS = 1'
_port_mk="backends/platform/sdl/amigaos/amigaos.mk"
+ _nuked_opl=no
;;
android)
case $_host in
@@ -2555,7 +2582,8 @@ case $_host_os in
append_var DEFINES "-DARM"
append_var DEFINES "-DNONSTANDARD_PORT"
append_var CXXFLAGS "-isystem $DEVKITPRO/libnds/include"
- append_var CXXFLAGS "-isystem $DEVKITPRO/devkitARM/arm-eabi/include"
+ append_var CXXFLAGS "-isystem $DEVKITPRO/portlibs/nds/include"
+ append_var CXXFLAGS "-isystem $DEVKITPRO/portlibs/armv5te/include"
append_var CXXFLAGS "-mcpu=arm9tdmi"
append_var CXXFLAGS "-mtune=arm9tdmi"
append_var CXXFLAGS "-fomit-frame-pointer"
@@ -2564,9 +2592,8 @@ case $_host_os in
append_var CXXFLAGS "-fdata-sections"
append_var CXXFLAGS "-fno-strict-aliasing"
append_var CXXFLAGS "-fuse-cxa-atexit"
- append_var LDFLAGS "-specs=ds_arm9.specs"
append_var LDFLAGS "-mthumb-interwork"
- append_var LDFLAGS "-mno-fpu"
+ append_var LDFLAGS "-mfloat-abi=soft"
append_var LDFLAGS "-Wl,-Map,map.txt"
if test "$_dynamic_modules" = no ; then
append_var LDFLAGS "-Wl,--gc-sections"
@@ -2576,6 +2603,9 @@ case $_host_os in
# append_var LDFLAGS "-Wl,--retain-symbols-file,ds.syms"
fi
append_var LDFLAGS "-L$DEVKITPRO/libnds/lib"
+ append_var LDFLAGS "-L$DEVKITPRO/portlibs/nds/lib"
+ append_var LDFLAGS "-L$DEVKITPRO/portlibs/armv5te/lib"
+ append_var LIBS "-specs=ds_arm9.specs"
append_var LIBS "-lnds9"
;;
freebsd*)
@@ -2652,6 +2682,7 @@ case $_host_os in
append_var DEFINES "-DDISABLE_SID"
append_var DEFINES "-DREDUCE_MEMORY_USAGE"
add_line_to_config_mk 'N64 = 1'
+ _nuked_opl=no
;;
ps2)
append_var CXXFLAGS "-G2"
@@ -2880,6 +2911,7 @@ if test -n "$_host"; then
append_var CXXFLAGS "-mips32"
_backend="dingux"
_mt32emu=no
+ _nuked_opl=no
_optimization_level=-O3
# Disable alsa midi to get the port build on OpenDingux toolchain
_alsa=no
@@ -2961,6 +2993,7 @@ if test -n "$_host"; then
_backend="ds"
_build_scalers=no
_mt32emu=no
+ _nuked_opl=no
_port_mk="backends/platform/ds/ds.mk"
;;
gamecube)
@@ -3184,6 +3217,7 @@ if test -n "$_host"; then
_backend="ps2"
_build_scalers=no
_mt32emu=no
+ _nuked_opl=no
# HACK to enable mad & zlib (they are not properly detected due to linker issues).
# This trick doesn't work for tremor right now, as the PS2 port the resulting library
# libtremor, while our code later on expects it to be called libvorbisidec.
@@ -3401,6 +3435,7 @@ case $_backend in
append_var DEFINES "-DDISABLE_DOSBOX_OPL"
append_var LIBS "-lpng"
append_var LIBS "-Wl,-Map,mapfile.txt"
+ _nuked_opl=no
;;
psp2)
append_var LIBS "-lvitashaders -lSDL2 -lvita2d_fbo -lSceCommonDialog_stub"
@@ -3544,7 +3579,7 @@ esac
# Enable High resolution engines (>320x240) support only for backends which support it
#
case $_host in
- gcw0)
+ ds | gcw0)
if test "$_highres" = yes ; then
_highres=yes
else
@@ -3727,7 +3762,7 @@ POST_OBJS_FLAGS := -Wl,--no-whole-archive
append_var DEFINES "-DUNCACHED_PLUGINS"
append_var DEFINES "-DELF_NO_MEM_MANAGER"
_mak_plugins='
-PLUGIN_LDFLAGS += -Wl,-T$(srcdir)/backends/plugins/ds/plugin.ld -mthumb-interwork -mno-fpu
+PLUGIN_LDFLAGS += -Wl,-T$(srcdir)/backends/plugins/ds/plugin.ld -mthumb-interwork -mfloat-abi=soft
'
;;
freebsd*)
@@ -3879,6 +3914,11 @@ fi
define_in_config_if_yes "$_mt32emu" 'USE_MT32EMU'
#
+# Check whether Nuked OPL emulator support is disabled
+#
+define_in_config_if_no "$_nuked_opl" 'DISABLE_NUKED_OPL'
+
+#
# Check whether 16bit color support is requested
#
define_in_config_if_yes "$_16bit" 'USE_RGB_COLOR'
@@ -3995,6 +4035,27 @@ add_to_config_mk_if_yes "$_tremor" 'USE_TREMOR = 1'
echo "$_tremor"
#
+# Check for IEEE1284 for OPL2lPT
+#
+echocheck "OPL2LPT"
+if test "$_opl2lpt" = yes ; then
+ _opl2lpt=no
+ cat > $TMPC << EOF
+#include <ieee1284.h>
+struct parport_list parports;
+int main(void) { ieee1284_find_ports(&parports, 0); return 0; }
+EOF
+ cc_check $IEEE1284_CFLAGS $IEEE1284_LIBS -lieee1284 && \
+ _opl2lpt=yes
+fi
+if test "$_opl2lpt" = yes; then
+ append_var LIBS "$IEEE1284_LIBS -lieee1284"
+ append_var INCLUDES "$IEEE1284_CFLAGS"
+fi
+define_in_config_if_yes "$_opl2lpt" 'ENABLE_OPL2LPT'
+echo "$_opl2lpt"
+
+#
# Check for FLAC
#
echocheck "FLAC >= 1.0.1"
@@ -4024,7 +4085,7 @@ fi
define_in_config_if_yes "$_flac" 'USE_FLAC'
echo "$_flac"
-# Add the link to ogg only after verbs tremor and flac as it might be used by those.
+# Add the link to ogg only after vorbis, tremor and flac as it might be used by those.
if test "$_ogg" = yes ; then
append_var LIBS "$OGG_LIBS -logg"
append_var INCLUDES "$OGG_CFLAGS"
@@ -5017,6 +5078,10 @@ if test "$_mt32emu" = yes ; then
echo_n ", MT-32 emulator"
fi
+if test "$_nuked_opl" = yes ; then
+ echo_n ", Nuked OPL emulator"
+fi
+
if test "$_text_console" = yes ; then
echo_n ", text console"
fi
@@ -5232,6 +5297,7 @@ cat > config.h << EOF
$_config_h_data
/* Data types */
+#ifndef SCUMMVM_DONT_DEFINE_TYPES
typedef unsigned $type_1_byte byte;
typedef unsigned int uint;
typedef unsigned $type_1_byte uint8;
@@ -5242,6 +5308,7 @@ typedef signed $type_1_byte int8;
typedef signed $type_2_byte int16;
typedef signed $type_4_byte int32;
typedef signed $type_8_byte int64;
+#endif
typedef $type_ptr uintptr;
diff --git a/devtools/create_cryo/create_cryo_dat.cpp b/devtools/create_cryo/create_cryo_dat.cpp
index ca6d4bf790..817eda3d20 100644
--- a/devtools/create_cryo/create_cryo_dat.cpp
+++ b/devtools/create_cryo/create_cryo_dat.cpp
@@ -93,7 +93,7 @@ static void emitStatic(FILE *f) {
const int kNumCharacters = 20;
const int kNumActionCursors = 299;
const int kNumAreas = 12;
-
+
for (int i = 0; i < kNumFollowers; i++) {
writeLE<char>(f, followerList[i]._id);
writeLE<char>(f, followerList[i]._spriteNum);
@@ -105,13 +105,13 @@ static void emitStatic(FILE *f) {
writeLE<int16>(f, followerList[i].ff_C);
writeLE<int16>(f, followerList[i].ff_E);
}
-
+
fwrite(kLabyrinthPath, 1, kNumLabyrinthPath, f);
fwrite(kDinoSpeedForCitaLevel, 1, kNumDinoSpeedForCitaLevel, f);
fwrite(kTabletView, 1, kNumTabletView, f);
fwrite(kPersoRoomBankTable, 1, kNumPersoRoomBankTable, f);
fwrite(gotos, 5, kNumGotos, f); // sizeof(Goto)
-
+
for (int i = 0; i < kNumObjects; i++) {
writeLE<byte>(f, _objects[i]._id);
writeLE<byte>(f, _objects[i]._flags);
@@ -120,11 +120,11 @@ static void emitStatic(FILE *f) {
writeLE<uint16>(f, _objects[i]._powerMask);
writeLE<int16>(f, _objects[i]._count);
}
-
+
for (int i = 0; i < kNumObjectLocations; i++) {
writeLE<uint16>(f, kObjectLocations[i]);
}
-
+
for (int i = 0; i < kNumPersons; i++) {
writeLE<uint16>(f, kPersons[i]._roomNum);
writeLE<uint16>(f, kPersons[i]._actionId);
@@ -140,7 +140,7 @@ static void emitStatic(FILE *f) {
writeLE<byte>(f, kPersons[i]._speed);
writeLE<byte>(f, kPersons[i]._steps);
}
-
+
for (int i = 0; i < kNumCitadel; i++) {
writeLE<int16>(f, _citadelList[i]._id);
for (int j = 0; j < 8; j++)
@@ -148,16 +148,16 @@ static void emitStatic(FILE *f) {
for (int j = 0; j < 8; j++)
writeLE<int16>(f, _citadelList[i]._video[j]);
}
-
+
for (int i = 0; i < kNumCharacterRects; i++) {
writeLE<int16>(f, _characterRects[i].left);
writeLE<int16>(f, _characterRects[i].top);
writeLE<int16>(f, _characterRects[i].right);
writeLE<int16>(f, _characterRects[i].bottom);
}
-
+
fwrite(_characterArray, 5, kNumCharacters, f);
-
+
for (int i = 0; i < kNumAreas; i++) {
writeLE<byte>(f, kAreasTable[i]._num);
writeLE<byte>(f, kAreasTable[i]._type);
@@ -168,15 +168,15 @@ static void emitStatic(FILE *f) {
// pointer to _citadelRoomPtr is always initialized to null
writeLE<int16>(f, kAreasTable[i]._visitCount);
}
-
+
for (int i = 0; i < 64; i++) {
writeLE<uint16>(f, tab_2CEF0[i]);
}
-
+
for (int i = 0; i < 64; i++) {
writeLE<uint16>(f, tab_2CF70[i]);
}
-
+
fwrite(kActionCursors, 1, kNumActionCursors, f);
fwrite(mapMode, 1, 12, f);
fwrite(cubeTextureCoords, 6 * 2 * 3 * 2, 3, f);
@@ -193,11 +193,11 @@ static int emitData(char *outputFilename) {
fwrite("CRYODATA", 8, 1, f);
writeLE<uint32>(f, CRYO_DAT_VER);
-
+
emitIcons(f);
emitRooms(f);
emitStatic(f);
-
+
fclose(f);
printf("Done!\n");
diff --git a/devtools/create_cryo/eden_rooms.h b/devtools/create_cryo/eden_rooms.h
index e28bc468f4..08384e7be9 100644
--- a/devtools/create_cryo/eden_rooms.h
+++ b/devtools/create_cryo/eden_rooms.h
@@ -26,7 +26,7 @@
// Note: the following data can be found in the original game's executable
const int kNumRooms = 424;
const room_t gameRooms[kNumRooms] = {
- // Mo
+ // Mo
{ 1, {255, 0, 0, 0}, 0, 66, 0xFFFF,29, 93, 1, 4},
{ 7, { 4, 0, 6, 0}, 4, 72, 0xFFFF, 8,143, 2, 2},
{ 3, { 24, 0, 5, 0}, 6, 99, 1, 6, 6, 3, 0},
diff --git a/devtools/create_project/cmake.cpp b/devtools/create_project/cmake.cpp
index 9be76f9fe8..d1a2be86cc 100644
--- a/devtools/create_project/cmake.cpp
+++ b/devtools/create_project/cmake.cpp
@@ -37,7 +37,7 @@ CMakeProvider::CMakeProvider(StringList &global_warnings, std::map<std::string,
const CMakeProvider::Library *CMakeProvider::getLibraryFromFeature(const char *feature, bool useSDL2) const {
static const Library s_libraries[] = {
{ "sdl", kSDLVersion1, "FindSDL", "SDL", "SDL_INCLUDE_DIR", "SDL_LIBRARY", 0 },
- { "sdl", kSDLVersion2, 0, "SDL2", "SDL2_INCLUDE_DIRS", "SDL2_LIBRARIES", 0 },
+ { "sdl", kSDLVersion2, 0, "SDL2", 0, "SDL2_LIBRARIES", 0 },
{ "freetype", kSDLVersionAny, "FindFreetype", "Freetype", "FREETYPE_INCLUDE_DIRS", "FREETYPE_LIBRARIES", 0 },
{ "libz", kSDLVersionAny, "FindZLIB", "ZLIB", "ZLIB_INCLUDE_DIRS", "ZLIB_LIBRARIES", 0 },
{ "png", kSDLVersionAny, "FindPNG", "PNG", "PNG_INCLUDE_DIRS", "PNG_LIBRARIES", 0 },
@@ -84,8 +84,17 @@ void CMakeProvider::createWorkspace(const BuildSetup &setup) {
workspace << "include_directories(${" << setup.projectDescription << "_SOURCE_DIR} ${" << setup.projectDescription << "_SOURCE_DIR}/engines "
"$ENV{"<<LIBS_DEFINE<<"}/include .)\n\n";
- workspace << "# Libraries and features\n";
+ workspace << "# Libraries and features\n\n";
writeFeatureLibSearch(setup, workspace, "sdl");
+
+ workspace << "# Depending on how SDL2 was built, there can be either and imported target or flags variables\n";
+ workspace << "# Define the flags variables from the imported target if necessary\n";
+ workspace << "if (TARGET SDL2::SDL2)\n";
+ workspace << " get_target_property(SDL2_INCLUDE_DIRS SDL2::SDL2 INTERFACE_INCLUDE_DIRECTORIES)\n";
+ workspace << " get_target_property(SDL2_LIBRARIES SDL2::SDL2 LOCATION)\n";
+ workspace << "endif()\n";
+ workspace << "include_directories(${SDL2_INCLUDE_DIRS})\n\n";
+
for (FeatureList::const_iterator i = setup.features.begin(), end = setup.features.end(); i != end; ++i) {
if (!i->enable || featureExcluded(i->name)) continue;
@@ -191,13 +200,16 @@ void CMakeProvider::createProjectFile(const std::string &name, const std::string
addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
- project << ")\n";
+ project << ")\n\n";
if (name != setup.projectName) {
project << "endif()\n";
}
- project << "# Libraries\n";
if (name == setup.projectName) {
+ project << "# Engines libraries handling\n";
+ writeEnginesLibrariesHandling(setup, project);
+
+ project << "# Libraries\n";
const Library *sdlLibrary = getLibraryFromFeature("sdl", setup.useSDL2);
project << "target_link_libraries(" << name << " ${" << sdlLibrary->librariesVar << "})\n";
@@ -219,9 +231,6 @@ void CMakeProvider::createProjectFile(const std::string &name, const std::string
project << "endif()\n";
project << "\n";
- project << "# Engines libraries handling\n";
- writeEnginesLibrariesHandling(setup, project);
-
project << "set_property(TARGET " << name << " PROPERTY CXX_STANDARD 11)\n";
project << "set_property(TARGET " << name << " PROPERTY CXX_STANDARD_REQUIRED ON)\n";
}
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index c0cc8af87c..cbf30adae8 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -300,7 +300,7 @@ int main(int argc, char *argv[]) {
for (EngineDescList::iterator j = setup.engines.begin(); j != setup.engines.end(); ++j)
j->enable = false;
}
-
+
// Disable engines for which we are missing dependencies
for (EngineDescList::const_iterator i = setup.engines.begin(); i != setup.engines.end(); ++i) {
if (i->enable) {
diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h
index 9f662ae806..fc3df8154a 100644
--- a/devtools/create_project/create_project.h
+++ b/devtools/create_project/create_project.h
@@ -86,7 +86,7 @@ struct EngineDesc {
* Whether the engine should be included in the build or not.
*/
bool enable;
-
+
/**
* Features required for this engine.
*/
diff --git a/devtools/create_supernova/po_parser.cpp b/devtools/create_supernova/po_parser.cpp
index f4a9b96388..05a8ac14a7 100644
--- a/devtools/create_supernova/po_parser.cpp
+++ b/devtools/create_supernova/po_parser.cpp
@@ -69,7 +69,7 @@ void PoMessageList::insert(const char *translation, const char *msg, const char
const char *PoMessageList::findTranslation(const char *msg, const char *context) {
if (msg == NULL || *msg == '\0')
- NULL;
+ return NULL;
// binary-search for the message
int leftIndex = 0;
diff --git a/devtools/create_supernova/strings-en.po b/devtools/create_supernova/strings-en.po
index f1c9d2fae2..1d0328982a 100644
--- a/devtools/create_supernova/strings-en.po
+++ b/devtools/create_supernova/strings-en.po
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: Mission Supernova 1.0\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
"POT-Creation-Date: 2017-07-22 19:53+0100\n"
-"PO-Revision-Date: 2018-01-07 18:01+0000\n"
-"Last-Translator: Joseph-Eugene Winzer <Joe.Winzer@gmx.de>\n"
+"PO-Revision-Date: 2018-04-13 21:29+0000\n"
+"Last-Translator: Adrian Frhwirth <bonki@scummvm.org>\n"
"Language-Team: none\n"
"Language: en\n"
"MIME-Version: 1.0\n"
@@ -1629,7 +1629,7 @@ msgstr "Pssst, not so loud, otherwise everyone|will want an autograph from me."
#: ../../msn/msn_r2.c:730
msgid ""
"Ich habe extra eine Maske auf, damit|ich nicht von jedem angelabert werde."
-msgstr "I have an extra mask on so I don't|get yakked on by everyone."
+msgstr "I'm deliberately wearing a mask so I don't|get yakked on by everyone."
#: ../../msn/msn_r2.c:731
msgid "Žh ... ach so."
@@ -1698,7 +1698,7 @@ msgstr "What? Ridiculous!"
#: ../../msn/msn_r2.c:745
msgid "Wie erkl„ren Sie sich dann,|daс ich ihnen gegenbersitze?"
-msgstr "How do you explain then that|I am seated opposite you?"
+msgstr "Then how do you explain the fact that|I am seated opposite you?"
#: ../../msn/msn_r2.c:746
msgid "Ja, das ist in der Tat seltsam."
@@ -1721,7 +1721,8 @@ msgid ""
"Na gut, ich glaube Ihnen. Lassen wir jetzt|dieses Thema, langsam wird es mir "
"zu bunt!"
msgstr ""
-"OK. I believe you. Let's move away from|this topic before it goes too far!"
+"Fair enough, I believe you. Let's move away from|this topic before it goes "
+"too far!"
#: ../../msn/msn_r2.c:761
msgid "Eine Partie Schach! Das ist eine gute Idee."
diff --git a/devtools/create_titanic/create_titanic_dat.cpp b/devtools/create_titanic/create_titanic_dat.cpp
index eb87dbb5d3..a5e813a977 100644
--- a/devtools/create_titanic/create_titanic_dat.cpp
+++ b/devtools/create_titanic/create_titanic_dat.cpp
@@ -1152,7 +1152,7 @@ void writeResource(const char *sectionStr, uint32 resId, bool isEnglish = true)
sprintf(nameBuffer, "%s/%u", sectionStr, resId);
if (!isEnglish)
strcat(nameBuffer, "/DE");
-
+
writeResource(nameBuffer, sectionStr, resId, isEnglish);
}
diff --git a/devtools/create_xeen/cc.h b/devtools/create_xeen/cc.h
index 47a5112573..db1bd1f0de 100644
--- a/devtools/create_xeen/cc.h
+++ b/devtools/create_xeen/cc.h
@@ -57,7 +57,7 @@ private:
* Convert a resource name to it's equivalent hash key
*/
uint16 convertNameToId(const Common::String &resourceName);
-
+
/**
* Loads an index from the file
*/
@@ -81,6 +81,10 @@ public:
loadIndex();
}
+ ~CCArchive() {
+ _file.close();
+ }
+
/**
* In write mode, finishes the CC file, writing out the resulting content
*/
diff --git a/devtools/create_xeen/constants.cpp b/devtools/create_xeen/constants.cpp
index e895949509..7210759908 100644
--- a/devtools/create_xeen/constants.cpp
+++ b/devtools/create_xeen/constants.cpp
@@ -62,7 +62,7 @@ enum MagicSpell {
const char *const CLOUDS_CREDITS =
"\v012\t000\x3""c\f35Designed and Directed By:\n"
- "\f17Jon Van Caneghem\x3""l\n"
+ "\f17Jon Van Caneghem\x3l\n"
"\n"
"\t025\f35Programming:\n"
"\t035\f17Mark Caldwell\n"
@@ -97,7 +97,7 @@ const char *const CLOUDS_CREDITS =
const char *const DARK_SIDE_CREDITS =
"\v012\t000\x3""c\f35Designed and Directed By:\n"
- "\f17Jon Van Caneghem\x3""l\n"
+ "\f17Jon Van Caneghem\x3l\n"
"\n"
"\t025\f35Programming:\n"
"\t035\f17Mark Caldwell\n"
@@ -169,18 +169,26 @@ const char *const OPTIONS_MENU =
"All Rights Reserved\x1";
const char *const GAME_NAMES[3] = { "Clouds", "Darkside", "World" };
-const char *const THE_PARTY_NEEDS_REST = "\x0B""012The Party needs rest!";
+const char *const THE_PARTY_NEEDS_REST = "\v012The Party needs rest!";
-const char *const WHO_WILL = "\x03""c\x0B""000\x09""000%s\x0A\x0A"
- "Who will\x0A%s?\x0A\x0B""055F1 - F%d";
+const char *const WHO_WILL = "\x3""c\v000\t000%s\n\n"
+ "Who will\n%s?\n\v055F1 - F%d";
const char *const HOW_MUCH = "\x3""cHow Much\n\n";
-const char *const WHATS_THE_PASSWORD = "What's the Password?";
+const char *const WHATS_THE_PASSWORD = "\x3""cWhat's the Password?\n"
+ "\n"
+ "Please turn to page %u, go to\n"
+ "line %u, and type in word %u.\v067\t000Spaces are not counted as words or lines. "
+ "Hyphenated words are treated as one word. Any line that has any text is considered a line."
+ "\x3""c\v040\t000\n";
+
+const char *const PASSWORD_INCORRECT = "\x3""c\v040\n"
+ "\f32Incorrect!\fd";
-const char *const IN_NO_CONDITION = "\x0B""007%s is not in any condition to perform actions!";
+const char *const IN_NO_CONDITION = "\v007%s is not in any condition to perform actions!";
-const char *const NOTHING_HERE = "\x03""c\x0B""010Nothing here.";
+const char *const NOTHING_HERE = "\x3""c\v010Nothing here.";
const char *const TERRAIN_TYPES[6] = {
"town", "cave", "towr", "cstl", "dung", "scfi"
@@ -619,7 +627,7 @@ const int MONSTER_GRID_BITMASK[12] = {
};
const int INDOOR_OBJECT_X[2][12] = {
- { 5, -7, -112, 98, -8, -65, 49, -9, -34, 16, -58, 40 },
+ { -5, -7, -112, 98, -8, -65, 49, -9, -34, 16, -58, 40 },
{ -35, -35, -142, 68, -35, -95, 19, -35, -62, -14, -98, 16 }
};
@@ -865,9 +873,9 @@ const int TOWN_ACTION_FILES[2][7] = {
{ 3, 2, 4, 2, 4, 2, 1 }, { 5, 3, 7, 5, 4, 6, 1 }
};
-const char *const BANK_TEXT = "\xD\x2\x3""c\xB""122\t013"
- "\xC""37D\xC""dep\t040\xC""37W\xC""dith\t067ESC"
- "\x1\t000\xB""000Bank of Xeen\xB""015\n"
+const char *const BANK_TEXT = "\r\x2\x3""c\v122\t013"
+ "\f37D\fdep\t040\f37W\fdith\t067ESC"
+ "\x1\t000\v000Bank of Xeen\v015\n"
"Bank\x3l\n"
"Gold\x3r\t000%s\x3l\n"
"Gems\x3r\t000%s\x3""c\n"
@@ -876,31 +884,31 @@ const char *const BANK_TEXT = "\xD\x2\x3""c\xB""122\t013"
"Gold\x3r\t000%s\x3l\n"
"Gems\x3r\t000%s";
-const char *const BLACKSMITH_TEXT = "\x01\x0D\x03""c\x0B""000\x09""000"
- "Store Options for\x09""039\x0B""027%s\x03""l\x0B""046\n"
- "\x09""011\x0C""37B\x0C""drowse\n"
- "\x09""000\x0B""090Gold\x03r\x09""000%s"
- "\x02\x03""c\x0B""122\x09""040ESC\x01";
+const char *const BLACKSMITH_TEXT = "\x1\r\x3""c\v000\t000"
+ "Store Options for\t039\v027%s\x3l\v046\n"
+ "\t011\f37B\fdrowse\n"
+ "\t000\v090Gold\x3r\t000%s"
+ "\x2\x3""c\v122\t040ESC\x1";
const char *const GUILD_NOT_MEMBER_TEXT =
"\n\nYou have to be a member to shop here.";
-const char *const GUILD_TEXT = "\x03""c\x0B""027\x09""039%s"
- "\x03l\x0B""046\n"
- "\x09""012\x0C""37B\x0C""duy Spells\n"
- "\x09""012\x0C""37S\x0C""dpell Info";
+const char *const GUILD_TEXT = "\x3""c\v027\t039%s"
+ "\x3l\v046\n"
+ "\t012\f37B\fduy Spells\n"
+ "\t012\f37S\fdpell Info";
const char *const TAVERN_TEXT =
- "\x0D\x03""c\x0B""000\x09""000Tavern Options for\x09""039"
- "\x0B""027%s%s\x03l\x09""000"
- "\x0B""090Gold\x03r\x09""000%s\x02\x03""c\x0B""122"
- "\x09""021\x0C""37S\x0C""dign in\x09""060ESC\x01";
+ "\r\x3""c\v000\t000Tavern Options for\t039"
+ "\v027%s%s\x3l\t000"
+ "\v090Gold\x3r\t000%s\x2\x3""c\v122"
+ "\t021\f37S\fdign in\t060ESC\x1";
const char *const FOOD_AND_DRINK =
- "\x03l\x09""017\x0B""046\x0C""37D\x0C""drink\n"
- "\x09""017\x0C""37F\x0C""dood\n"
- "\x09""017\x0C""37T\x0C""dip\n"
- "\x09""017\x0C""37R\x0C""dumors";
+ "\x3l\t017\v046\f37D\fdrink\n"
+ "\t017\f37F\fdood\n"
+ "\t017\f37T\fdip\n"
+ "\t017\f37R\fdumors";
const char *const GOOD_STUFF = "\n"
"\n"
@@ -931,49 +939,47 @@ const int TAVERN_EXIT_LIST[2][6][5][2] = {
};
const char *const TEMPLE_TEXT =
- "\x0D\x03""c\x0B""000\x09""000Temple Options for"
- "\x09""039\x0B""027%s\x03l\x09""000\x0B""046"
- "\x0C""37H\x0C""deal\x03r\x09""000%lu\x03l\n"
- "\x0C""37D\x0C""donation\x03r\x09""000%lu\x03l\n"
- "\x0C""37U\x0C""dnCurse\x03r\x09""000%s"
- "\x03l\x09""000\x0B""090Gold\x03r\x09""000%s"
- "\x02\x03""c\x0B""122\x09""040ESC\x01";
+ "\r\x3""c\v000\t000Temple Options for"
+ "\t039\v027%s\x3l\t000\v046"
+ "\f37H\fdeal\x3r\t000%lu\x3l\n"
+ "\f37D\fdonation\x3r\t000%lu\x3l\n"
+ "\f37U\fdnCurse\x3r\t000%s"
+ "\x3l\t000\v090Gold\x3r\t000%s"
+ "\x2\x3""c\v122\t040ESC\x1";
const char *const EXPERIENCE_FOR_LEVEL =
"%s needs %lu experience for level %u.";
-const char *const LEARNED_ALL = "%s has learned all we can teach!";
+const char *const TRAINING_LEARNED_ALL = "%s has learned all we can teach!";
-const char *const ELIGIBLE_FOR_LEVEL = "%s is eligible for level %d.";
+const char *const ELIGIBLE_FOR_LEVEL = "%s is eligible for level %u.\x3l\n"
+ "\v081Cost\x3r\t000%u";
const char *const TRAINING_TEXT =
- "\x0D\x03""cTraining Options\n"
+ "\r\x3""cTraining Options\n"
"\n"
- "%s\x03l\x0B""090\x09""000Gold\x03r\x09"
- "000%s\x02\x03""c\x0B""122\x09""021"
- "\x0C""37T\x0C""drain\x09""060ESC\x01";
+ "%s\x3l\v090\t000Gold\x3r\t000%s\x2\x3""c\v122\t021"
+ "\f37T\fdrain\t060ESC\x1";
const char *const GOLD_GEMS =
- "\x03""c\x0B""000\x09""000%s\x03l\n"
+ "\x3""c\v000\t000%s\x3l\n"
"\n"
- "Gold\x03r\x09""000%s\x03l\n"
- "Gems\x03r\x09""000%s\x02\x03""c\x0B""096\x09""013G"
- "\x0C""37o\x0C""dld\x09""040G\x0C\x03""7e"
- "\x0C""dms\x09""067ESC\x01";
+ "Gold\x3r\t000%s\x3l\n"
+ "Gems\x3r\t000%s\x2\x3""c\v096\t013G\f37o\fdld\t040G\f37e\fdms\t067ESC\x1";
const char *const GOLD_GEMS_2 =
- "\x09""000\x0B""000\x03""c%s\x03l\n"
+ "\x3""c\v000\t000%s\x3l\n"
"\n"
- "\x04""077Gold\x03r\x09""000%s\x03l\n"
- "\x04""077Gems\x03r\x09""000%s\x03l\x09""000\x0B""051\x04""077\n"
- "\x04""077";
+ "\x4""077Gold\x3r\t000%s\x3l\n"
+ "\x4""077Gems\x3r\t000%s\x3l\t000\v051\x4""077\n"
+ "\x4""077";
const char *const DEPOSIT_WITHDRAWL[2] = { "Deposit", "Withdrawl" };
const char *const NOT_ENOUGH_X_IN_THE_Y =
- "\x03""c\x0B""012Not enough %s in the %s!\x03l";
+ "\x3""c\v012Not enough %s in the %s!\x3l";
-const char *const NO_X_IN_THE_Y = "\x03""c\x0B""012No %s in the %s!\x03l";
+const char *const NO_X_IN_THE_Y = "\x3""c\v012No %s in the %s!\x3l";
const char *const STAT_NAMES[16] = {
"Might", "Intellect", "Personality", "Endurance", "Speed",
@@ -985,19 +991,19 @@ const char *const CONSUMABLE_NAMES[4] = { "Gold", "Gems", "Food", "Condition" };
const char *const WHERE_NAMES[2] = { "Party", "Bank" };
-const char *const AMOUNT = "\x03""c\x09""000\x0B""051Amount\x03l\n";
+const char *const AMOUNT = "\x3""c\t000\v051Amount\x3l\n";
const char *const FOOD_PACKS_FULL = "\v007Your food packs are already full!";
const char *const BUY_SPELLS =
- "\x03""c\x0B""027\x09""039%s\x03l\x0B""046\n"
- "\x09""012\x0C""37B\x0C""duy Spells\n"
- "\x09""012\x0C""37S\x0C""dpell Info";
+ "\x3""c\v027\t039%s\x3l\v046\n"
+ "\t012\f37B\fduy Spells\n"
+ "\t012\f37S\fdpell Info";
const char *const GUILD_OPTIONS =
- "\x0D\x0C""00\x03""c\x0B""000\x09""000Guild Options for%s"
- "\x03l\x09""000\x0B""090Gold"
- "\x03r\x09""000%s\x02\x03""c\x0B""122\x09""040ESC\x01";
+ "\r\f00\x3""c\v000\t000Guild Options for%s"
+ "\x3l\t000\v090Gold"
+ "\x3r\t000%s\x2\x3""c\v122\t040ESC\x1";
const int MISC_SPELL_INDEX[74] = {
NO_SPELL, MS_Light, MS_Awaken, MS_MagicArrow,
@@ -1037,7 +1043,13 @@ const int DARK_SPELL_RANGES[12][2] = {
{ 0, 20 }, { 16, 35 }, { 27, 37 }, { 29, 39 }
};
-const int CLOUDS_SPELL_OFFSETS[5][20] = {
+const int SWORDS_SPELL_RANGES[12][2] = {
+ { 0, 20 },{ 16, 35 },{ 27, 39 },{ 29, 39 },
+ { 0, 17 },{ 14, 34 },{ 26, 39 },{ 29, 39 },
+ { 0, 20 },{ 16, 35 },{ 27, 39 },{ 29, 39 }
+};
+
+const int CLOUDS_GUILD_SPELLS[5][20] = {
{
1, 10, 20, 26, 27, 38, 40, 42, 45, 50,
55, 59, 60, 61, 62, 68, 72, 75, 77, 77
@@ -1081,40 +1093,43 @@ const int SPELL_GEM_COST[77] = {
const char *const NOT_A_SPELL_CASTER = "Not a spell caster...";
-const char *const SPELLS_FOR = "\xD\xC""d%s\x2\x3""c\x9""000\xB""002Spells for %s";
+const char *const SPELLS_LEARNED_ALL = "You have learned all we\n"
+ "\t010can teach you.";
+
+const char *const SPELLS_FOR = "\r\fd%s\x2\x3""c\t000\v002Spells for %s";
const char *const SPELL_LINES_0_TO_9 =
- "\x2\x3l\xB""015\x9""0011\n2\n3\n4\n5\n6\n7\n8\n9\n0";
-
-const char *const SPELLS_DIALOG_SPELLS = "\x3l\xB""015"
- "\x9""010\xC""%2u%s\xC""d\x3l\n"
- "\x9""010\xC""%2u%s\xC""d\x3l\n"
- "\x9""010\xC""%2u%s\xC""d\x3l\n"
- "\x9""010\xC""%2u%s\xC""d\x3l\n"
- "\x9""010\xC""%2u%s\xC""d\x3l\n"
- "\x9""010\xC""%2u%s\xC""d\x3l\n"
- "\x9""010\xC""%2u%s\xC""d\x3l\n"
- "\x9""010\xC""%2u%s\xC""d\x3l\n"
- "\x9""010\xC""%2u%s\xC""d\x3l\n"
- "\x9""010\xC""%2u%s\xC""d\x3l"
- "\x9""004\xB""110%s - %lu\x1";
+ "\x2\x3l\v015\t0011\n2\n3\n4\n5\n6\n7\n8\n9\n0";
+
+const char *const SPELLS_DIALOG_SPELLS = "\x3l\v015"
+ "\t010\f%2u%s\fd\x3l\n"
+ "\t010\f%2u%s\fd\x3l\n"
+ "\t010\f%2u%s\fd\x3l\n"
+ "\t010\f%2u%s\fd\x3l\n"
+ "\t010\f%2u%s\fd\x3l\n"
+ "\t010\f%2u%s\fd\x3l\n"
+ "\t010\f%2u%s\fd\x3l\n"
+ "\t010\f%2u%s\fd\x3l\n"
+ "\t010\f%2u%s\fd\x3l\n"
+ "\t010\f%2u%s\fd\x3l"
+ "\t004\v110%s - %lu\x1";
const char *const SPELL_PTS = "Spell Pts";
const char *const GOLD = "Gold";
-const char *const SPELLS_PRESS_A_KEY =
- "\x3""c\xC""09%s\xC""d\x3l\n"
+const char *const SPELL_INFO =
+ "\x3""c\f09%s\fd\x3l\n"
"\n"
- "%s\x3""c\x9""000\xB""100Press a Key!";
+ "%s\x3""c\t000\v100Press a Key!";
-const char *const SPELLS_PURCHASE =
- "\x3l\xB""000\x9""000\xC""d%s Do you wish to purchase "
- "\xC""09%s\xC""d for %u?";
+const char *const SPELL_PURCHASE =
+ "\x3l\v000\t000\fd%s Do you wish to purchase "
+ "\f09%s\fd for %u?";
const char *const MAP_TEXT =
- "\x3""c\xB""000\x9""000%s\x3l\xB""139"
- "\x9""000X = %d\x3r\x9""000Y = %d\x3""c\x9""000%s";
+ "\x3""c\v000\t000%s\x3l\v139"
+ "\t000X = %d\x3r\t000Y = %d\x3""c\t000%s";
const char *const LIGHT_COUNT_TEXT = "\x3l\n\n\t024Light\x3r\t124%d";
@@ -1122,7 +1137,7 @@ const char *const FIRE_RESISTENCE_TEXT = "%c%sFire%s%u";
const char *const ELECRICITY_RESISTENCE_TEXT = "%c%sElectricity%s%u";
-const char *const COLD_RESISTENCE_TEXT = "c%sCold%s%u";
+const char *const COLD_RESISTENCE_TEXT = "%c%sCold%s%u";
const char *const POISON_RESISTENCE_TEXT = "%c%sPoison/Acid%s%u";
@@ -1133,13 +1148,13 @@ const char *const LEVITATE_TEXT = "%c%sLevitate%s";
const char *const WALK_ON_WATER_TEXT = "%c%sWalk on Water";
const char *const GAME_INFORMATION =
- "\xD\x3""c\x9""000\xB""001\xC""37%s of Xeen\xC""d\n"
+ "\r\x3""c\t000\v001\f37%s of Xeen\fd\n"
"Game Information\n"
"\n"
- "Today is \xC""37%ssday\xC""d\n"
+ "Today is \f37%ssday\fd\n"
"\n"
- "\x9""032Time\x9""072Day\x9""112Year\n"
- "\x9""032\xC""37%d:%02d%c\x9""072%u\x9""112%u\xC""d%s";
+ "\t032Time\t072Day\t112Year\n"
+ "\t032\f37%d:%02d%c\t072%u\t112%u\fd%s";
const char *const WORLD_GAME_TEXT = "World";
const char *const DARKSIDE_GAME_TEXT = "Darkside";
@@ -1151,41 +1166,41 @@ const char *const WEEK_DAY_STRINGS[10] = {
};
const char *const CHARACTER_DETAILS =
- "\x3l\xB""041\x9""196%s\x9""000\xB""002%s : %s %s %s"
- "\x3r\x9""053\xB""028\xC%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
- "\x3l\x9""131\xC""%02u%d\xC""d\x9""196\xC""15%lu\xC""d\x3r"
- "\x9""053\xB""051\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
- "\x3l\x9""131\xC""%02u%u\xC""d\x9""196\xC""15%lu\xC""d"
- "\x3r\x9""053\xB""074\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
- "\x3l\x9""131\xC""15%u\xC""d\x9""196\xC""15%lu\xC""d"
- "\x3r\x9""053\xB""097\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
- "\x3l\x9""131\xC""15%u\xC""d\x9""196\xC""15%u day%c\xC""d"
- "\x3r\x9""053\xB""120\xC""%02u%u\xC""d\x9""103\xC""%02u%u\xC""d"
- "\x3l\x9""131\xC""15%u\xC""d\x9""196\xC""%02u%s\xC""d"
- "\x9""230%s%s%s%s\xC""d";
+ "\x3l\v041\t196%s\t000\v002%s : %s %s %s"
+ "\x3r\t053\v028\f%02u%u\fd\t103\f%02u%u\fd"
+ "\x3l\t131\f%02u%d\fd\t196\f15%lu\fd\x3r"
+ "\t053\v051\f%02u%u\fd\t103\f%02u%u\fd"
+ "\x3l\t131\f%02u%u\fd\t196\f15%lu\fd"
+ "\x3r\t053\v074\f%02u%u\fd\t103\f%02u%u\fd"
+ "\x3l\t131\f15%u\fd\t196\f15%lu\fd"
+ "\x3r\t053\v097\f%02u%u\fd\t103\f%02u%u\fd"
+ "\x3l\t131\f15%u\fd\t196\f15%u day%c\fd"
+ "\x3r\t053\v120\f%02u%u\fd\t103\f%02u%u\fd"
+ "\x3l\t131\f15%u\fd\t196\f%02u%s\fd"
+ "\t230%s%s%s%s\fd";
const char *const PARTY_GOLD = "Party Gold";
-const char *const PLUS_14 = "14+";
+const char *const PLUS_14 = "\f14+";
const char *const CHARACTER_TEMPLATE =
- "\x1\xC""00\xD\x3l\x9""029\xB""018Mgt\x9""080Acy\x9""131H.P.\x9""196Experience"
- "\x9""029\xB""041Int\x9""080Lck\x9""131S.P.\x9""029\xB""064Per\x9""080Age"
- "\x9""131Resis\x9""196Party Gems\x9""029\xB""087End\x9""080Lvl\x9""131Skills"
- "\x9""196Party Food\x9""029\xB""110Spd\x9""080AC\x9""131Awrds\x9""196Condition\x3""c"
- "\x9""290\xB""025\xC""37I\xC""dtem\x9""290\xB""057\xC""37Q"
- "\xC""duick\x9""290\xB""089\xC""37E\xC""dxch\x9""290\xB""121Exit\x3l%s";
+ "\x1\f00\r\x3l\t029\v018Mgt\t080Acy\t131H.P.\t196Experience"
+ "\t029\v041Int\t080Lck\t131S.P.\t029\v064Per\t080Age"
+ "\t131Resis\t196Party Gems\t029\v087End\t080Lvl\t131Skills"
+ "\t196Party Food\t029\v110Spd\t080AC\t131Awrds\t196Condition\x3""c"
+ "\t290\v025\f37I\fdtem\t290\v057\f37Q"
+ "\fduick\t290\v089\f37E\fdxch\t290\v121Exit\x3l%s";
-const char *const EXCHANGING_IN_COMBAT = "\x3""c\xB""007\x9""000Exchanging in combat is not allowed!";
+const char *const EXCHANGING_IN_COMBAT = "\x3""c\v007\t000Exchanging in combat is not allowed!";
const char *const CURRENT_MAXIMUM_RATING_TEXT = "\x2\x3""c%s\n"
"Current / Maximum\n"
- "\x3r\x9""054%lu\x3l\x9""058/ %lu\n"
+ "\x3r\t054%lu\x3l\t058/ %lu\n"
"\x3""cRating: %s";
const char *const CURRENT_MAXIMUM_TEXT = "\x2\x3""c%s\n"
"Current / Maximum\n"
- "\x3r\x9""054%u\x3l\x9""058/ %u";
+ "\x3r\t054%u\x3l\t058/ %u";
const char *const RATING_TEXT[24] = {
"Nonexistant", "Very Poor", "Poor", "Very Low", "Low", "Averarage", "Good",
@@ -1196,31 +1211,31 @@ const char *const RATING_TEXT[24] = {
const char *const AGE_TEXT = "\x2\x3""c%s\n"
"Current / Natural\n"
- "\x3r\x9""057%u\x3l\x9""061/ %u\n"
+ "\x3r\t057%u\x3l\t061/ %u\n"
"\x3""cBorn: %u / %u\x1";
const char *const LEVEL_TEXT =
"\x2\x3""c%s\n"
"Current / Maximum\n"
- "\x3r\x9""054%u\x3l\x9""058/ %u\n"
+ "\x3r\t054%u\x3l\t058/ %u\n"
"\x3""c%u Attack%s/Round\x1";
const char *const RESISTENCES_TEXT =
"\x2\x3""c%s\x3l\n"
- "\x9""020Fire\x9""100%u\n"
- "\x9""020Cold\x9""100%u\n"
- "\x9""020Electricity\x9""100%u\n"
- "\x9""020Poison\x9""100%u\n"
- "\x9""020Energy\x9""100%u\n"
- "\x9""020Magic\x9""100%u";
+ "\t020Fire\t100%u\n"
+ "\t020Cold\t100%u\n"
+ "\t020Electricity\t100%u\n"
+ "\t020Poison\t100%u\n"
+ "\t020Energy\t100%u\n"
+ "\t020Magic\t100%u";
-const char *const NONE = "\n\x9""020";
+const char *const NONE = "\n\t020None";
const char *const EXPERIENCE_TEXT = "\x2\x3""c%s\x3l\n"
- "\x9""010Current:\x9""070%lu\n"
- "\x9""010Next Level:\x9""070%s\x1";
+ "\t010Current:\t070%lu\n"
+ "\t010Next Level:\t070%s\x1";
-const char *const ELIGIBLE = "\xC""12Eligible\xC""d";
+const char *const ELIGIBLE = "\f12Eligible\fd";
const char *const IN_PARTY_IN_BANK =
"\x2\x3""cParty %s\n"
@@ -1235,17 +1250,17 @@ const char *const FOOD_TEXT =
const char *const EXCHANGE_WITH_WHOM = "\t010\v005Exchange with whom?";
const char *const QUICK_REF_LINE =
- "\xB%3d\x9""007%u)\x9""027%s\x9""110%c%c%c\x3r\x9""160\xC%02u%u\xC""d"
- "\x3l\x9""170\xC%02u%d\xC""d\x9""208\xC%02u%u\xC""d\x9""247\xC"
- "%02u%u\xC""d\x9""270\xC%02u%c%c%c%c\xC""d";
+ "\v%3d\t007%u)\t027%s\t110%c%c%c\x3r\t160\f%02u%u\fd"
+ "\x3l\t170\f%02u%d\fd\t208\f%02u%u\fd\t247\f"
+ "%02u%u\fd\t270\f%02u%c%c%c%c\fd";
const char *const QUICK_REFERENCE =
- "\xD\x3""cQuick Reference Chart\xB""012\x3l"
- "\x9""007#\x9""027Name\x9""110Cls\x9""140Lvl\x9""176H.P."
- "\x9""212S.P.\x9""241A.C.\x9""270Cond"
+ "\r\x3""cQuick Reference Chart\v012\x3l"
+ "\t007#\t027Name\t110Cls\t140Lvl\t176H.P."
+ "\t212S.P.\t241A.C.\t270Cond"
"%s%s%s%s%s%s%s%s"
- "\xB""110\x9""064\x3""cGold\x9""144Gems\x9""224Food\xB""119"
- "\x9""064\xC""15%lu\x9""144%lu\x9""224%u day%s\xC""d";
+ "\v110\t064\x3""cGold\t144Gems\t224Food\v119"
+ "\t064\f15%lu\t144%lu\t224%u day%s\fd";
const int BLACKSMITH_MAP_IDS[2][4] = { { 28, 30, 73, 49 }, { 29, 31, 37, 43 } };
@@ -1274,18 +1289,22 @@ const char *const BTN_GOLD = "G\fdold";
const char *const ITEM_BROKEN = "\f32broken ";
const char *const ITEM_CURSED = "\f09cursed ";
+const char *const ITEM_OF = "of ";
+
const char *const BONUS_NAMES[7] = {
"", "Dragon Slayer", "Undead Eater", "Golem Smasher",
"Bug Zapper", "Monster Masher", "Beast Bopper"
};
-const char *const WEAPON_NAMES[35] = {
+const char *const WEAPON_NAMES[41] = {
nullptr, "long sword ", "short sword ", "broad sword ", "scimitar ",
"cutlass ", "sabre ", "club ", "hand axe ", "katana ", "nunchakas ",
"wakazashi ", "dagger ", "mace ", "flail ", "cudgel ", "maul ", "spear ",
"bardiche ", "glaive ", "halberd ", "pike ", "flamberge ", "trident ",
"staff ", "hammer ", "naginata ", "battle axe ", "grand axe ", "great axe ",
- "short bow ", "long bow ", "crossbow ", "sling ", "Xeen Slayer Sword"
+ "short bow ", "long bow ", "crossbow ", "sling ", "Xeen Slayer Sword",
+ "Elder LongSword", "Elder Dagger ", "Elder Mace ", "Elder Spear ",
+ "Elder Staff ", "Elder LongBow "
};
const char *const ARMOR_NAMES[14] = {
@@ -1301,9 +1320,22 @@ const char *const ACCESSORY_NAMES[11] = {
const char *const MISC_NAMES[22] = {
nullptr, "rod ", "jewel ", "gem ", "box ", "orb ", "horn ", "coin ",
- "wand ", "whistle ", "potion ", "scroll ", "RogueVM",
- "bogusg", "bogus", "bogus", "bogus", "bogus",
- "bogus", "bogus", "bogus", "bogus"
+ "wand ", "whistle ", "potion ", "scroll ", "bogus", "bogus", "bogus",
+ "bogus", "bogus", "bogus", "bogus", "bogus", "bogus", "bogus"
+};
+
+const char *const SPECIAL_NAMES[74] = {
+ nullptr, "light", "awakening", "magic arrows", "first aid", "fists", "energy blasts", "sleeping",
+ "revitalization", "curing", "sparking", "shrapmetal", "insect repellent", "toxic clouds", "elemental protection",
+ "pain", "jumping", "beast control", "clairvoyance", "undead turning", "levitation", "wizard eyes", "blessing",
+ "monster identification", "lightning", "holy bonuses", "power curing", "nature's cures", "beacons",
+ "shielding", "heroism", "hypnotism", "water walking", "frost biting", "monster finding", "fireballs",
+ "cold rays", "antidotes", "acid spraying", "time distortion", "dragon sleep", "vaccination", "teleportation",
+ "death", "free movement", "golem stopping", "poison volleys", "deadly swarms", "shelter", "daily protection",
+ "daily sorcerery", "feasting", "fiery flails", "recharging", "freezing", "town portals", "stone to flesh",
+ "raising the dead", "etherealization", "dancing swords", "moon rays", "mass distortion", "prismatic light",
+ "enchant item", "incinerating", "holy words", "resurrection", "storms", "megavoltage", "infernos",
+ "sun rays", "implosions", "star bursts", "the GODS!"
};
const char *const ELEMENTAL_NAMES[6] = {
@@ -1407,6 +1439,21 @@ const char *const QUEST_ITEM_NAMES[85] = {
"Energy Disk"
};
+const char *QUEST_ITEM_NAMES_SWORDS[51] = {
+ "Pass to Hart", "Pass to Impery", "Pass to town3", "Pass to town4", "Pass to town5",
+ "Key to Hart Sewers", "Key to Rettig's Pyramid", "Key to the Old Temple",
+ "Key to Canegtut's Pyramid", "Key to Ascihep's Pyramid", "Key to Dragon Tower",
+ "Key to Darkstone Tower", "Key to Temple of Bark", "Key to Dungeon of Lost Souls",
+ "Key to Ancient Pyramid", "Key to Dungeon of Death", "Red Magic Hammer",
+ "Green Magic Hammer", "Golden Magic Wand", "Silver Magic Hammer", "Magic Coin",
+ "Ruby", "Diamond Mineral", "Emerald", "Sapphire", "Treasure Map (Goto E1 x1, y11)",
+ "NOTUSED", "Melon", "Princess Crown", "Emerald Wand", "Druid Carving", "High Sign",
+ "Holy Wheel", "Double Cross", "Sky Hook", "Sacred Cow", "Staff of the Mountain",
+ "Hard Rock", "Soft Rock", "Rock Candy", "Ivy Plant", "Spirit Gem", "Temple of Sun holy lamp oil",
+ "Noams Hammer", "Positive Orb", "Negative Orb", "FireBane Staff", "Diamond Edged Pick",
+ "Monga Melon", "Energy Disk", "Old XEEN Quest Item"
+};
+
const int WEAPON_BASE_COSTS[35] = {
0, 50, 15, 100, 80, 40, 60, 1, 10, 150, 30, 60, 8, 50,
100, 15, 30, 15, 200, 80, 250, 150, 400, 100, 40, 120,
@@ -1459,7 +1506,7 @@ const char *const X_FOR_THE_Y =
"\x1\fd\r%s\v000\t000%s for %s the %s%s\v011\x2%s%s%s%s%s%s%s%s%s\x1\fd";
const char *const X_FOR_Y =
- "\x1\xC""d\r\x3l\v000\t000%s for %s\x3r\t000%s\x3l\v011\x2%s%s%s%s%s%s%s%s%s\x1\xC""d";
+ "\x1\fd\r\x3l\v000\t000%s for %s\x3r\t000%s\x3l\v011\x2%s%s%s%s%s%s%s%s%s\x1\fd";
const char *const X_FOR_Y_GOLD =
"\x1\fd\r\x3l\v000\t000%s for %s\t150Gold - %lu%s\x3l\v011"
@@ -1469,7 +1516,7 @@ const char *const FMT_CHARGES = "\x3rr\t000Charges\x3l";
const char *const AVAILABLE_GOLD_COST =
"\x1\fd\r\x3l\v000\t000Available %s\t150Gold - %lu\x3r\t000Cost"
- "\x3l\v011\x2%s%s%s%s%s%s%s%s%s\x1\xC""d";
+ "\x3l\v011\x2%s%s%s%s%s%s%s%s%s\x1\fd";
const char *const CHARGES = "Charges";
@@ -1491,7 +1538,7 @@ const char *const NO_SPECIAL_ABILITIES = "\v005\x3""c%s\fdhas no special abiliti
const char *const CANT_CAST_WHILE_ENGAGED = "\x3""c\v007Can't cast %s while engaged!";
const char *const EQUIPPED_ALL_YOU_CAN = "\x3""c\v007You have equipped all the %ss you can!";
-const char *const REMOVE_X_TO_EQUIP_Y = "\x3""c\v007You must remove %sto equip %s\x8!";
+const char *const REMOVE_X_TO_EQUIP_Y = "\x3""c\v007You must remove %sto equip %s\b!";
const char *const RING = "ring";
const char *const MEDAL = "medal";
@@ -1499,7 +1546,7 @@ const char *const CANNOT_REMOVE_CURSED_ITEM = "\x3""You cannot remove a cursed i
const char *const CANNOT_DISCARD_CURSED_ITEM = "\3x""cYou cannot discard a cursed item!";
-const char *const PERMANENTLY_DISCARD = "\v000\t000\x03lPermanently discard %s\fd?";
+const char *const PERMANENTLY_DISCARD = "\v000\t000\x3lPermanently discard %s\fd?";
const char *const BACKPACK_IS_FULL = "\v005\x3""c\fd%s's backpack is full.";
@@ -1557,6 +1604,7 @@ const char *const QUESTS_DIALOG_TEXT =
"\t289Exit";
const char *const CLOUDS_OF_XEEN_LINE = "\b \b*-- \f04Clouds of Xeen\fd --";
const char *const DARKSIDE_OF_XEEN_LINE = "\b \b*-- \f04Darkside of Xeen\fd --";
+const char *const SWORDS_OF_XEEN_LINE = "\b \b*-- \f04Swords of Xeen\fd --";
const char *const NO_QUEST_ITEMS =
"\r\x3""c\v000 000Quest Items\x3l\x2\n"
@@ -1609,6 +1657,8 @@ const char *const SOME_CHARS_MAY_DIE = "Some Chars may die. Rest anyway?";
const char *const CANT_DISMISS_LAST_CHAR = "You cannot dismiss your last character!";
+const char *const DELETE_CHAR_WITH_ELDER_WEAPON = "\v000\t000This character has an Elder Weapon and cannot be deleted!";
+
const char *const REMOVE_DELETE[2] = { "Remove", "Delete" };
const char *const REMOVE_OR_DELETE_WHICH = "\x3l\t010\v005%s which character?";
@@ -1644,6 +1694,7 @@ const char *const SELECT_CLASS_BEFORE_SAVING =
const char *const EXCHANGE_ATTR_WITH = "Exchange %s with...";
const int NEW_CHAR_SKILLS[10] = { 1, 5, -1, -1, 4, 0, 0, -1, 6, 11 };
+const int NEW_CHAR_SKILLS_OFFSET[10] = { 0, 0, 0, 5, 0, 0, 0, 0, 0, 0 };
const int NEW_CHAR_SKILLS_LEN[10] = { 11, 8, 0, 0, 12, 8, 8, 0, 9, 11 };
const int NEW_CHAR_RACE_SKILLS[10] = { 14, -1, 17, 16, -1, 0, 0, 0, 0, 0 };
@@ -1693,7 +1744,7 @@ const char *const BACKPACKS_FULL_PRESS_KEY =
"\v007\f12Warning! BackPacks Full!\fd\n"
"Press a Key";
-const char *const HIT_A_KEY = "\x3l\v120\t000\x4""077\x3""c\f37Hit a key\xC""d";
+const char *const HIT_A_KEY = "\x3l\v120\t000\x4""077\x3""c\f37Hit a key\fd";
const char *const GIVE_TREASURE_FORMATTING =
"\x3l\v060\t000\x4""077\n"
@@ -1712,7 +1763,7 @@ const char *const WHICH_ELEMENT1 =
"\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1";
const char *const WHICH_ELEMENT2 =
- "\r\x3""cWhich Element?', 2, 0Bh, '034\t014\f15F\fdire\t044"
+ "\r\x3""cWhich Element?\x2\v034\t014\f15F\fdire\t044"
"\f15E\fdlec\t074\f15C\fdold\t104\f15A\fdcid\x1";
const char *const DETECT_MONSTERS = "\x3""cDetect Monsters";
@@ -1725,7 +1776,7 @@ const char *const LLOYDS_BEACON =
"%s\x3l\n"
"x = %d\x3r\t000y = %d\x3""c\x2\v122\t021\f15S\fdet\t060\f15R\fdeturn\x1";
-const char *const HOW_MANY_SQUARES = "\x3""cTeleport\nHow many squares %s (1-9)";
+const char *const HOW_MANY_SQUARES = "\x3""cTeleport\nHow many squares %s (1-9)\n";
const char *const TOWN_PORTAL =
"\x3""cTown Portal\x3l\n"
@@ -1739,8 +1790,18 @@ const char *const TOWN_PORTAL =
"To which Town (1-5)\n"
"\n";
-const int TOWN_MAP_NUMBERS[2][5] = {
- { 28, 29, 30, 31, 32 }, { 29, 31, 33, 35, 37 }
+const char *const TOWN_PORTAL_SWORDS =
+ "\x3""cTown Portal\x3l\n"
+ "\n"
+ "\t0101. %s\n"
+ "\t0102. %s\n"
+ "\t0103. %s\x3""c\n"
+ "\n"
+ "To which Town (1-3)\n"
+ "\n";
+
+const int TOWN_MAP_NUMBERS[3][5] = {
+ { 28, 29, 30, 31, 32 }, { 29, 31, 33, 35, 37 }, { 53, 92, 63, 0, 0 }
};
const char *const MONSTER_DETAILS =
@@ -1761,14 +1822,14 @@ const char *const EVENT_SAMPLES[6] = {
};
const char *const MOONS_NOT_ALIGNED =
-"\x3""c\xB""012\t000The moons are not aligned. Passage to the %s is unavailable";
+"\x3""c\v012\t000The moons are not aligned. Passage to the %s is unavailable";
const char *const AWARDS_FOR =
- "\r\x1\fd\x3""c\v000\t000Awards for %s the %s\x3""l\x2\n"
+ "\r\x1\fd\x3""c\v000\t000Awards for %s the %s\x3l\x2\n"
"%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\x1";
const char *const AWARDS_TEXT =
- "\r\x2\x3""c\xB""021\t221\xC""37U\xC""dp\t255\xC""37D\xC""down\t289Exit";
+ "\r\x2\x3""c\v021\t221\f37U\fdp\t255\f37D\fdown\t289Exit";
const char *const NO_AWARDS = "\x3""cNo Awards";
@@ -1780,22 +1841,22 @@ const char *const WARZONE_LEVEL = "What level of monsters? (1-10)\n";
const char *const WARZONE_HOW_MANY = "How many monsters? (1-20)\n";
-const char *const PICKS_THE_LOCK = "\x3""c\xB""010%s picks the lock!\nPress any key.";
+const char *const PICKS_THE_LOCK = "\x3""c\v010%s picks the lock!\nPress any key.";
const char *const UNABLE_TO_PICK_LOCK = "\x3""c\v010%s was unable to pick the lock!\nPress any key.";
const char *const CONTROL_PANEL_TEXT =
- "\x1\xC""00\x3""c\xB""000\t000Control Panel\x3r"
- "\xB""022\t045\xC""06L\xC""doad:\t124\xC""06E\xC""dfx:"
- "\xB""041\t045\xC""06S\xC""dave:\t124\xC""06M\xC""dusic:"
- "\xB""060\t045\xC""06Q\xC""duit:"
- "\xB""080\t084Mr \xC""06W\xC""dizard:%s\t000\x1";
+ "\x1\f00\x3""c\v000\t000Control Panel\x3r"
+ "\v022\t045\f06L\fdoad:\t124\f06E\fdfx:"
+ "\v041\t045\f06S\fdave:\t124\f06M\fdusic:"
+ "\v060\t045\f06Q\fduit:"
+ "\v080\t084Mr \f06W\fdizard:%s\t000\x1";
const char *const CONTROL_PANEL_BUTTONS =
"\x3""c\f11"
- "\xB""022\t062load\t141%s"
- "\xB""041\t062save\t141%s"
- "\xB""060\t062exit"
- "\xB""079\t102Help\xC""d";
+ "\v022\t062load\t141%s"
+ "\v041\t062save\t141%s"
+ "\v060\t062exit"
+ "\v079\t102Help\fd";
const char *const ON = "\f15on\f11";
const char *const OFF = "\f32off\f11";
const char *const CONFIRM_QUIT = "Are you sure you want to quit?";
@@ -1818,11 +1879,11 @@ const char *const WORLD_END_TEXT[9] = {
"And so the call went out to the people throughout the lands of Xeen"
" that the prophecy was nearing completion.",
"They came in great numbers to witness the momentous occasion.",
- "\xB""026The Dragon Pharoah presided over the ceremony.",
- "\xB""026Queen Kalindra presented the Cube of Power.",
- "\xB""026Prince Roland presented the Xeen Sceptre.",
- "\xB""026Together, they placed the Cube of Power...",
- "\xB""026and the Sceptre, onto the Altar of Joining.",
+ "\v026The Dragon Pharoah presided over the ceremony.",
+ "\v026Queen Kalindra presented the Cube of Power.",
+ "\v026Prince Roland presented the Xeen Sceptre.",
+ "\v026Together, they placed the Cube of Power...",
+ "\v026and the Sceptre, onto the Altar of Joining.",
"With the prophecy complete, the two sides of Xeen were united as one",
};
@@ -1845,17 +1906,17 @@ const char *const WORLD_CONGRATULATIONS2 =
"\"%s\"\n"
"with your final score and receive a special bonus.";
const char *const CLOUDS_CONGRATULATIONS1 =
- "\xC""23\x3l"
- "\xB""000\t000Please send this score to the Ancient's Headquarters "
- "where you'll be added to the Hall of Legends!\xC""33\x3""c"
- "\xB""070\t000Press a Key";
+ "\f23\x3l"
+ "\v000\t000Please send this score to the Ancient's Headquarters "
+ "where you'll be added to the Hall of Legends!\f33\x3""c"
+ "\v070\t000Press a Key";
const char *const CLOUDS_CONGRATULATIONS2 =
- "\xC""23\x3l"
- "\xB""000\t000Ancient's Headquarters\n"
+ "\f23\x3l"
+ "\v000\t000Ancient's Headquarters\n"
"New World Computing, Inc.\n"
"P.O. Box 4302\n"
- "Hollywood, CA 90078-4302\xC""33\x3""c"
- "\xB""070\t000Press a Key";
+ "Hollywood, CA 90078-4302\f33\x3""c"
+ "\v070\t000Press a Key";
const char *const GOOBER[3] = {
"", "I am a Goober!", "I am a Super Goober!"
};
@@ -1879,6 +1940,40 @@ const char *const MUSIC_FILES2[6][7] = {
};
const char *const DIFFICULTY_TEXT = "\v000\t000\x3""cSelect Game Preference";
+const char *const SAVE_OFF_LIMITS = "\x3""c\v002\t000The Gods of Game Restoration deem this area off limits!\n"
+ "Sorry, no saving in this maze.";
+
+const char *const CLOUDS_INTRO1 = "\f00\v082\t040\x3"
+ "cKing Burlock\v190\t040Peasants\v082\t247"
+ "Lord Xeen\v190\t258Xeen's Pet\v179\t150Crodo";
+
+const char *const DARKSIDE_ENDING1 = "\n\x3" "cCongratulations\n"
+ "\n"
+ "Your Final Score is:\n"
+ "\n"
+ "%010lu\n"
+ "\x3" "l\n"
+ "Please send this score to the Ancient's Headquarters "
+ "where you'll be added to the Hall of Legends!\n"
+ "\n"
+ "Ancient's Headquarters\n"
+ "New World Computing, Inc.\n"
+ "P.O. Box 4302\n"
+ "Hollywood, CA 90078";
+
+const char *const DARKSIDE_ENDING2 = "\n"
+ "Adventurers,\n"
+ "\n"
+ "I will save your game in Castleview.\n"
+ "\n"
+ "The World of Xeen still needs you!\n"
+ "\n"
+ "Load your game afterwards and come visit me in the "
+ "Great Pyramid for further instructions";
+
+const char *const PHAROAH_ENDING_TEXT1 = "\fd\v001\t001%s\x3" "c\t000\v180Press a Key!\x3" "l";
+const char *const PHAROAH_ENDING_TEXT2 = "\f04\v000\t000%s\x3" "c\t000\v180Press a Key!\x3" "l\fd";
+
void writeConstants(CCArchive &cc) {
Common::MemFile file;
@@ -1892,6 +1987,7 @@ void writeConstants(CCArchive &cc) {
file.syncString(WHO_WILL);
file.syncString(HOW_MUCH);
file.syncString(WHATS_THE_PASSWORD);
+ file.syncString(PASSWORD_INCORRECT);
file.syncString(IN_NO_CONDITION);
file.syncString(NOTHING_HERE);
file.syncStrings(TERRAIN_TYPES, 6);
@@ -1985,7 +2081,7 @@ void writeConstants(CCArchive &cc) {
file.syncString(FOOD_AND_DRINK);
file.syncString(TEMPLE_TEXT);
file.syncString(EXPERIENCE_FOR_LEVEL);
- file.syncString(LEARNED_ALL);
+ file.syncString(TRAINING_LEARNED_ALL);
file.syncString(ELIGIBLE_FOR_LEVEL);
file.syncString(TRAINING_TEXT);
file.syncString(GOLD_GEMS);
@@ -2002,18 +2098,20 @@ void writeConstants(CCArchive &cc) {
file.syncString(GUILD_OPTIONS);
file.syncNumbers((const int *)MISC_SPELL_INDEX, 74);
file.syncNumbers((const int *)SPELL_COSTS, 77);
- file.syncNumbers2D((const int *)CLOUDS_SPELL_OFFSETS, 5, 20);
+ file.syncNumbers2D((const int *)CLOUDS_GUILD_SPELLS, 5, 20);
file.syncNumbers2D((const int *)DARK_SPELL_OFFSETS, 3, 39);
file.syncNumbers2D((const int *)DARK_SPELL_RANGES, 12, 2);
+ file.syncNumbers2D((const int *)SWORDS_SPELL_RANGES, 12, 2);
file.syncNumbers((const int *)SPELL_GEM_COST, 77);
file.syncString(NOT_A_SPELL_CASTER);
+ file.syncString(SPELLS_LEARNED_ALL);
file.syncString(SPELLS_FOR);
file.syncString(SPELL_LINES_0_TO_9);
file.syncString(SPELLS_DIALOG_SPELLS);
file.syncString(SPELL_PTS);
file.syncString(GOLD);
- file.syncString(SPELLS_PRESS_A_KEY);
- file.syncString(SPELLS_PURCHASE);
+ file.syncString(SPELL_INFO);
+ file.syncString(SPELL_PURCHASE);
file.syncString(MAP_TEXT);
file.syncString(LIGHT_COUNT_TEXT);
file.syncString(FIRE_RESISTENCE_TEXT);
@@ -2067,15 +2165,18 @@ void writeConstants(CCArchive &cc) {
file.syncString(BTN_GOLD);
file.syncString(ITEM_BROKEN);
file.syncString(ITEM_CURSED);
+ file.syncString(ITEM_OF);
file.syncStrings(BONUS_NAMES, 7);
- file.syncStrings(WEAPON_NAMES, 35);
+ file.syncStrings(WEAPON_NAMES, 41);
file.syncStrings(ARMOR_NAMES, 14);
file.syncStrings(ACCESSORY_NAMES, 11);
file.syncStrings(MISC_NAMES, 22);
+ file.syncStrings(SPECIAL_NAMES, 74);
file.syncStrings(ELEMENTAL_NAMES, 6);
file.syncStrings(ATTRIBUTE_NAMES, 10);
file.syncStrings(EFFECTIVENESS_NAMES, 7);
file.syncStrings(QUEST_ITEM_NAMES, 85);
+ file.syncStrings(QUEST_ITEM_NAMES_SWORDS, 51);
file.syncNumbers((const int *)WEAPON_BASE_COSTS, 35);
file.syncNumbers((const int *)ARMOR_BASE_COSTS, 14);
file.syncNumbers((const int *)ACCESSORY_BASE_COSTS, 11);
@@ -2130,6 +2231,7 @@ void writeConstants(CCArchive &cc) {
file.syncString(QUESTS_DIALOG_TEXT);
file.syncString(CLOUDS_OF_XEEN_LINE);
file.syncString(DARKSIDE_OF_XEEN_LINE);
+ file.syncString(SWORDS_OF_XEEN_LINE);
file.syncString(NO_QUEST_ITEMS);
file.syncString(NO_CURRENT_QUESTS);
file.syncString(NO_AUTO_NOTES);
@@ -2142,6 +2244,7 @@ void writeConstants(CCArchive &cc) {
file.syncString(TOO_DANGEROUS_TO_REST);
file.syncString(SOME_CHARS_MAY_DIE);
file.syncString(CANT_DISMISS_LAST_CHAR);
+ file.syncString(DELETE_CHAR_WITH_ELDER_WEAPON);
file.syncStrings(REMOVE_DELETE, 2);
file.syncString(REMOVE_OR_DELETE_WHICH);
file.syncString(YOUR_PARTY_IS_FULL);
@@ -2153,6 +2256,7 @@ void writeConstants(CCArchive &cc) {
file.syncString(SELECT_CLASS_BEFORE_SAVING);
file.syncString(EXCHANGE_ATTR_WITH);
file.syncNumbers((const int *)NEW_CHAR_SKILLS, 10);
+ file.syncNumbers((const int *)NEW_CHAR_SKILLS_OFFSET, 10);
file.syncNumbers((const int *)NEW_CHAR_SKILLS_LEN, 10);
file.syncNumbers((const int *)NEW_CHAR_RACE_SKILLS, 10);
file.syncNumbers((const int *)RACE_MAGIC_RESISTENCES, 5);
@@ -2178,7 +2282,8 @@ void writeConstants(CCArchive &cc) {
file.syncString(LLOYDS_BEACON);
file.syncString(HOW_MANY_SQUARES);
file.syncString(TOWN_PORTAL);
- file.syncNumbers2D((const int *)TOWN_MAP_NUMBERS, 2, 5);
+ file.syncString(TOWN_PORTAL_SWORDS);
+ file.syncNumbers2D((const int *)TOWN_MAP_NUMBERS, 3, 5);
file.syncString(MONSTER_DETAILS);
file.syncStrings(MONSTER_SPECIAL_ATTACKS, 23);
file.syncString(IDENTIFY_MONSTERS);
@@ -2212,6 +2317,12 @@ void writeConstants(CCArchive &cc) {
file.syncStrings(MUSIC_FILES1, 5);
file.syncStrings2D((const char *const *)MUSIC_FILES2, 6, 7);
file.syncString(DIFFICULTY_TEXT);
+ file.syncString(SAVE_OFF_LIMITS);
+ file.syncString(CLOUDS_INTRO1);
+ file.syncString(DARKSIDE_ENDING1);
+ file.syncString(DARKSIDE_ENDING2);
+ file.syncString(PHAROAH_ENDING_TEXT1);
+ file.syncString(PHAROAH_ENDING_TEXT2);
cc.add("CONSTANTS", file);
}
diff --git a/devtools/create_xeen/create_xeen.cpp b/devtools/create_xeen/create_xeen.cpp
index 5b66870be4..d579fc2665 100644
--- a/devtools/create_xeen/create_xeen.cpp
+++ b/devtools/create_xeen/create_xeen.cpp
@@ -35,6 +35,7 @@
#include "cc.h"
#include "file.h"
#include "clouds.h"
+#include "swords.h"
#include "constants.h"
#include "map.h"
@@ -54,7 +55,12 @@ void writeVersion(CCArchive &cc) {
}
int main(int argc, char *argv[]) {
- if (!outputFile.open(argc == 1 ? "xeen.ccs" : argv[1], Common::kFileWriteMode)) {
+ if (argc != 3) {
+ printf("Format: %s dark.cc \"swords xeen.dat\"\n", argv[0]);
+ exit(0);
+ }
+
+ if (!outputFile.open("xeen.ccs", Common::kFileWriteMode)) {
error("Could not open input file");
}
@@ -63,9 +69,12 @@ int main(int argc, char *argv[]) {
writeConstants(cc);
writeMap(cc);
- const char *darkName = argc > 2 ? argv[2] : "dark.cc";
+ const char *darkName = argv[1];
writeCloudsData(cc, darkName);
+ const char *swordsDatName = argv[2];
+ writeSwordsData(cc, swordsDatName);
+
cc.close();
return 0;
}
diff --git a/devtools/create_xeen/file.h b/devtools/create_xeen/file.h
index 3d10825711..2d87ff3da9 100644
--- a/devtools/create_xeen/file.h
+++ b/devtools/create_xeen/file.h
@@ -197,7 +197,7 @@ public:
case SEEK_CUR: _offset += whence; break;
case SEEK_END: _offset = _size + whence; break;
}
-
+
return _offset;
}
virtual long read(void *buffer, size_t len) {
diff --git a/devtools/create_xeen/map.cpp b/devtools/create_xeen/map.cpp
index 6ca1987a7a..35435426b9 100644
--- a/devtools/create_xeen/map.cpp
+++ b/devtools/create_xeen/map.cpp
@@ -125,7 +125,7 @@ void writeMazeName(CCArchive &cc) {
memset(mazeName, 0, 33);
strcpy(mazeName, "ScummVM");
f.write(mazeName, 33);
-
+
cc.add("xeenx255.txt", f);
}
@@ -134,7 +134,7 @@ void writeMazeName(CCArchive &cc) {
*/
void writeMazeEvents(CCArchive &cc) {
Common::MemFile f;
-
+
// Mirror events
const byte MIRROR_EVENTS[32] = {
6, 7, 0, 2, 0, 40, 1, // Play VOC: "Where to?"
@@ -143,7 +143,7 @@ void writeMazeEvents(CCArchive &cc) {
8, 7, 0, 2, 3, 7, 0, 0, 0 // Teleport and exit
};
f.write(MIRROR_EVENTS, 32);
-
+
// Bench 1 events
const byte BENCH1_EVENTS[32] = {
10, 7, 8, 0, 0, 5, 1, 2, 3, 1, 2, // NPC
diff --git a/devtools/create_xeen/module.mk b/devtools/create_xeen/module.mk
index 29f2f3027f..eabd739b4f 100644
--- a/devtools/create_xeen/module.mk
+++ b/devtools/create_xeen/module.mk
@@ -8,7 +8,8 @@ MODULE_OBJS := \
hashmap.o \
map.o \
memorypool.o \
- str.o
+ str.o \
+ swords.o
# Set the name of the executable
TOOL_EXECUTABLE := create_xeen
diff --git a/devtools/create_xeen/swords.cpp b/devtools/create_xeen/swords.cpp
new file mode 100644
index 0000000000..838bfc87e6
--- /dev/null
+++ b/devtools/create_xeen/swords.cpp
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+ // Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+// HACK to allow building with the SDL backend on MinGW
+// see bug #1800764 "TOOLS: MinGW tools building broken"
+#ifdef main
+#undef main
+#endif // main
+
+#include "file.h"
+#include "swords.h"
+
+#define MONSTERS_COUNT 150
+
+void writeSwordsData(CCArchive &cc, const char *swordsDatName) {
+ Common::File f;
+ Common::MemFile monsters;
+ byte buffer[MONSTERS_COUNT * 60];
+
+ if (!f.open(swordsDatName, Common::kFileReadMode))
+ error("Could not open Swords xeen.dat");
+
+ f.seek(0x44200);
+ f.read(buffer, MONSTERS_COUNT * 60);
+
+ if (strcmp((const char *)buffer + 0x33, "Slime"))
+ error("Invalid Swords xeen.dat");
+
+ monsters.write(buffer, MONSTERS_COUNT * 60);
+ cc.add("monsters.swd", monsters);
+}
diff --git a/engines/sludge/transition.h b/devtools/create_xeen/swords.h
index 5ce556870d..105b30b44e 100644
--- a/engines/sludge/transition.h
+++ b/devtools/create_xeen/swords.h
@@ -19,14 +19,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
-#ifndef SLUDGE_TRANSITION_H
-#define SLUDGE_TRANSITION_H
-namespace Sludge {
+#ifndef SWORDS_H
+#define SWORDS_H
-void fixBrightness();
-void resetRandW();
+#include "common/scummsys.h"
+#include "cc.h"
-} // End of namespace Sludge
+extern void writeSwordsData(CCArchive &cc, const char *swordsDatName);
#endif
diff --git a/devtools/credits.pl b/devtools/credits.pl
index e86ea0e854..0cbd549f74 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -137,15 +137,16 @@ sub html_entities_to_rtf {
$text =~ s/&oacute;/\\'97/g;
$text =~ s/&oslash;/\\'bf/g;
$text =~ s/&aring;/\\'8c/g;
- # The following numerical values are octal!
+ # The following numerical values are decimal!
$text =~ s/&#322;/\\uc0\\u322 /g;
- $text =~ s/&Scaron;/\\uc0\\u540 /g;
+ $text =~ s/&#347;/\\uc0\\u347 /g;
+ $text =~ s/&Scaron;/\\uc0\\u352 /g;
# Back to hex numbers
$text =~ s/&ntilde;/\\'96/g;
$text =~ s/&auml;/\\'8a/g;
- $text =~ s/&euml;/\\'eb/g;
+ $text =~ s/&euml;/\\'91/g;
$text =~ s/&ouml;/\\'9a/g;
$text =~ s/&uuml;/\\'9f/g;
@@ -154,31 +155,6 @@ sub html_entities_to_rtf {
return $text;
}
-# Convert HTML entities to TeX codes
-sub html_entities_to_tex {
- my $text = shift;
-
- $text =~ s/&aacute;/\\'a/g;
- $text =~ s/&eacute;/\\'e/g;
- $text =~ s/&iacute;/\\'i/g;
- $text =~ s/&igrave;/\\`\\i/g;
- $text =~ s/&oacute;/\\'o/g;
- $text =~ s/&oslash;/{\\o}/g;
- $text =~ s/&aring;/\\aa /g;
- $text =~ s/&#322;/{\\l}/g;
- $text =~ s/&Scaron;/{\\v S}/g;
- $text =~ s/&ntilde;/\\Ыœn/g;
-
- $text =~ s/&auml;/\\"a/g;
- $text =~ s/&ouml;/\\"o/g;
- $text =~ s/&euml;/\\"e/g;
- $text =~ s/&uuml;/\\"u/g;
-
- $text =~ s/&amp;/\\&/g;
-
- return $text;
-}
-
#
# Small reference of the RTF commands used here:
#
@@ -829,6 +805,12 @@ begin_credits("Credits");
add_person("Tobia Tesan", "t0by", "");
end_section();
+ begin_section("Xeen");
+ add_person("Paul Gilbert", "dreammaster", "");
+ add_person("David Goldsmith", "WizardStan", "(analysis)");
+ add_person("Matt Taylor", "", "(analysis)");
+ end_section();
+
begin_section("Z-Vision");
add_person("Adrian Astley", "RichieSams", "");
add_person("Filippos Karapetis", "[md5]", "");
diff --git a/dists/engine-data/supernova.dat b/dists/engine-data/supernova.dat
index 74d9092aef..b4638c2717 100644
--- a/dists/engine-data/supernova.dat
+++ b/dists/engine-data/supernova.dat
Binary files differ
diff --git a/dists/engine-data/xeen.ccs b/dists/engine-data/xeen.ccs
index 3c7bcbc2cf..88671fb669 100644
--- a/dists/engine-data/xeen.ccs
+++ b/dists/engine-data/xeen.ccs
Binary files differ
diff --git a/doc/QuickStart b/doc/QuickStart
index 82c723a197..c9209b965d 100644
--- a/doc/QuickStart
+++ b/doc/QuickStart
@@ -5,7 +5,7 @@ English README file.
For more information, compatibility lists, details on donating, the
latest release, progress reports and more, please visit the ScummVM home
-page at: http://www.scummvm.org/
+page at: https://www.scummvm.org/
Table of Contents:
------------------
@@ -75,7 +75,7 @@ to follow the guide from the English REAMDE file.
For the impatient among you, here is how to get ScummVM running in five
simple steps.
-1. Download ScummVM from <http://www.scummvm.org/downloads.php> and
+1. Download ScummVM from <https://www.scummvm.org/downloads/> and
install it.
2. Create a directory on your hard drive and copy the game datafiles
@@ -134,7 +134,7 @@ reproducible, and still occurs in the latest git/Daily build version.
Also check the known problems list (below) and the compatibility list on
our website for that game, to ensure the issue is not already known:
- http://www.scummvm.org/compatibility_stable.php
+ https://www.scummvm.org/compatibility/
Please do not report bugs on games that are not listed as being
completeable in the 'Supported Games' section, or compatibility list. We
diff --git a/doc/cz/PrectiMe b/doc/cz/PrectiMe
index 67980e1256..2d9afb7bd6 100644
--- a/doc/cz/PrectiMe
+++ b/doc/cz/PrectiMe
@@ -2,7 +2,7 @@ P՘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: <https://www.scummvm.org/>
Obsah:
@@ -112,7 +112,7 @@ Pokud mУЁte ScummVM rУЁdi, mХЏХОete ho podpoХ™it dotacУ­ pomocУ­ tlaФУ­tka PayP
---- -------------
Pro ty netrpФ›livУЉ zТ VУЁs je tu nУЁvod, jak ScummVM spustit vТ nФ›kolika krocУ­ch.
-1. StУЁhnФ›te si ScummVM z <http://www.scummvm.org/downloads.php> a nainstalujte ho.
+1. StУЁhnФ›te si ScummVM z <https://www.scummvm.org/downloads/> a nainstalujte ho.
2. Na VaХЁem pevnУЉm disku vytvoХ™te sloХОku a zkopУ­rujte datovУЉ soubory zТ pХЏvodnУ­ho mУЉdia do tУЉto sloХОky. Zopakujte pro vХЁechny hry, kterУЉ chcete hrУЁt
@@ -130,7 +130,7 @@ Rada: Pokud chcete pХ™idat vУ­ce her najednou, zkuste stisknout a drХОet klУЁves
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У­.
+Na <https://www.scummvm.org/faq/> jsme pro VУЁs pХ™ipravili seznam nejФastФ›jХЁУ­ch otУЁzek a jejich odpovФ›dУ­.
2.0) Kontakt:
@@ -142,7 +142,7 @@ MХЏХОete se takУЉ pХ™ipojit a odesУ­lat a e-maily na korespondenФnУ­ seznam scu
---- -------------
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>
+ <https://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.
@@ -163,7 +163,7 @@ Nakonec prosУ­me, abyste kaХОdou chybu nahlaХЁovali samostatnФ›; neohlaХЁujte nФ
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/>)
+ <https://www.scummvm.org/compatibility/>)
Hry od LucasArts (SCUMM):
@@ -579,7 +579,7 @@ Ve verzУ­ch pro PlayStation, mХЏХОete pХЏvodnУ­ videa vypsat z disku. KaХОdУН so
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>
+ <https://www.scummvm.org/downloads/>
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.
@@ -716,7 +716,7 @@ 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>
+ <https://www.scummvm.org/games/#feeble>
Windows:
Pokud mУЁte verzi pro Windows, je tХ™eba si uvФ›domit pУЁr vФ›cУ­.
@@ -831,7 +831,7 @@ 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
+<https://www.thezorklibrary.com/installguides/znpatch.zip> a rozbalte adresУЁХ™ addon pХ™У­mo do koХ™enovУЉho adresУЁХ™e hry
Verze z GoG
@@ -864,7 +864,7 @@ 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>
+<https://releases.pagure.org/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Ф›
@@ -888,7 +888,7 @@ 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>,
+<https://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
@@ -1023,7 +1023,7 @@ ScummVM mХЏХОe takУЉ hru spustit pХ™У­mo pomocУ­ argumentХЏ pХ™У­kazovУЉ Х™УЁdky
--native-mt32 PravУН Roland MT-32 (zakУЁХОe emulaci GM)
--enable-gs PovolУ­ reХОim Roland GS pro pХ™ehrУЁvУЁnУ­ MIDI
--output-rate=FREKVENCE VУНstupnУ­ vzorkovacУ­ kmitoФet v Hz (napХ™. 22050)
- --opl-driver=OVLADAФŒ Vybere emulУЁtor AdLib (OPL) (db, mame)
+ --opl-driver=OVLADAФŒ Vybere emulУЁtor AdLib (OPL) (db, mame, nuked)
--aspect-ratio PovolУ­ korekci pomФ›ru stran
--render-mode=REХНIM PovolУ­ dodateФnУЉ reХОimy vykreslenУ­ (hercGreen, hercAmber,
cga, ega, vga, amiga, fmtowns, pc9821, pc9801, 2gs,
@@ -2020,9 +2020,9 @@ Pro aktuУЁlnУ­ pХ™ehled o tom, jak ScummVM sestavit pro rХЏznУЉ platformy, prohl
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://www.nasm.us/). NezapomeХˆte, ХОe vТ souФasnosti mУЁme pouze verze optimalizovanУЉ pro x86 MMX, a nebudou sestaveny pro jinУЉ procesory.
+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 https://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)>.
+Na Windows mХЏХОete urФit USE_WINDBG a pХ™ipojit WinDbg pro prochУЁzenУ­ ladУ­cУ­ch zprУЁv (viz <https://docs.microsoft.com/cs-cz/windows-hardware/drivers/debugger/index>).
Windows:
* Dev-C++
@@ -2126,7 +2126,7 @@ Na Win9x/NT/XP mХЏХОete urФit USE_WINDBG a pХ™ipojit WinDbg pro prochУЁzenУ­ la
----- ----------
ProsУ­m pХ™eФtФ›te si nУЁХЁ rozsУЁhlУН seznam lidУ­, kterУНm chceme podФ›kovat na
-<http://www.scummvm.org/credits/>
+<https://www.scummvm.org/credits/>
@@ -2134,5 +2134,5 @@ ProsУ­m pХ™eФtФ›te si nУЁХЁ rozsУЁhlУН seznam lidУ­, kterУНm chceme podФ›kovat
------------------------------------------------------------------------
HodnФ› Х tФ›stУ­ a Х ХЅastnУЉ AdventurovУЁnУ­!
TУНm ScummVM.
-<http://www.scummvm.org/>
+<https://www.scummvm.org/>
------------------------------------------------------------------------
diff --git a/doc/da/HurtigStart b/doc/da/HurtigStart
index b54590bba3..bd528e450f 100644
--- a/doc/da/HurtigStart
+++ b/doc/da/HurtigStart
@@ -5,7 +5,7 @@ at se i den Engelske README-fil.
For mere information, kompatibilitet lister, detaljer om donering, den
seneste udgivelse, statusrapporter og mere, kan du besУИge ScummVMs hjemme-
-side pУЅ: http://www.scummvm.org/
+side pУЅ: https://www.scummvm.org/
Indholdsfortegnelse:
--------------------
@@ -73,7 +73,7 @@ fУИlge vejledning fra den engelske README fil.
For de utУЅlmodige blandt jer, er her hvordan du fУЅr ScummVM op at kУИre
i fem enkle trin.
-1. Hent ScummVM fra <http://www.scummvm.org/downloads.php> og
+1. Hent ScummVM fra <https://www.scummvm.org/downloads/> og
installere det.
2. Opret en mappe pУЅ din harddisk og kopiere spillets datafiler fra de
@@ -128,7 +128,7 @@ og stadig forekommer i den seneste git/Daglig byggede version.
Kontroller ogsУЅ listen med kendte problemer (nedenfor) og kompatibilitetslisten
pУЅ vores hjemmeside for spillet, for at sikre, at problemet ikke allerede er kendt:
- http://www.scummvm.org/compatibility_stable.php
+ https://www.scummvm.org/compatibility/
VУІr venlig ikke at rapportere fejl pУЅ spil, der ikke er anfУИrt som vУІrende
mulige at gennemfУИre i 'understУИttede spil' sektionen, eller kompatibilitetslisten.
diff --git a/doc/de/LIESMICH b/doc/de/LIESMICH
index 532160aa25..f5a1079bf9 100644
--- a/doc/de/LIESMICH
+++ b/doc/de/LIESMICH
@@ -3,7 +3,7 @@ ScummVM т€“ Liesmich-Datei
FУМr weitere Informationen, KompatibilitУЄtslisten, Einzelheiten zu Spenden, die
neusten verУЖffentlichten Versionen, Fortschrittsberichte und mehr besuchen Sie
-bitte die ScummVM-Website unter der Adresse: http://www.scummvm.org/
+bitte die ScummVM-Website unter der Adresse: https://www.scummvm.org/
Inhaltsverzeichnis:
@@ -65,10 +65,10 @@ Inhaltsverzeichnis:
* 7.3 MT-32-Emulation
* 7.4 MIDI-Emulation
* 7.5 Native MIDI-UnterstУМtzung
- * 7.5.1 Native MIDI-Ausgabe mithilfe der MIDI-Optionen anpassen
+ * * 7.5.1 Native MIDI-Ausgabe mithilfe der MIDI-Optionen anpassen
* 7.6 UNIX-eigene, ALSA- und dmedia-Sequenzer-UnterstУМtzung
- * 7.6.1 ALSA-Sequencer [NUR UNIX]
- * 7.6.2 IRIX dmedia-Sequencer [NUR UNIX]
+ * * 7.6.1 ALSA-Sequencer [NUR UNIX]
+ * * 7.6.2 IRIX dmedia-Sequencer [NUR UNIX]
* 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
@@ -155,7 +155,7 @@ bitte die Anleitung in der englischen README-Datei.
FУМr die ungeduldigen unter den Anwendern ist hier in fУМnf einfachen Schritten
kurz beschrieben, wie man ScummVM lauffУЄhig macht und das Programm verwendet.
-1. Laden Sie ScummVM unter der Adresse http://www.scummvm.org/downloads.php
+1. Laden Sie ScummVM unter der Adresse https://www.scummvm.org/downloads/
herunter und installieren Sie es.
2. Erstellen Sie ein Verzeichnis auf Ihrer Festplatte und kopieren Sie die
@@ -222,7 +222,7 @@ auftritt. Bitte sehen Sie auch auf der KompatibilitУЄtsliste der ScummVM-Website
fУМr dieses Spiel nach, um sicherzustellen, dass das Problem nicht bereits
bekannt ist:
- <http://scummvm.org/compatibility/>
+ <https://www.scummvm.org/compatibility/>
Bitte melden Sie keine Fehler zu Spielen, die nicht als durchspielbar im
Bereich т€žUnterstУМtzte Spieleт€œ oder der KompatibilitУЄtsliste aufgelistet sind.
@@ -771,7 +771,7 @@ keine Smacker-Videos. Revolution Software hat uns freundlicherweise erlaubt, die
Zwischensequenzen umgewandelt auf unserer Website als Download zur VerfУМgung zu
stellen. Siehe hierfУМr:
- http://www.scummvm.org/downloads.php
+ https://www.scummvm.org/downloads/
Diese Zwischensequenzen werden im DXA-Format mit FLAC-Audio zur VerfУМgung
gestellt. Ihre QualitУЄt ist durch die Verwendung verlustfreier Kompression
@@ -1059,7 +1059,7 @@ Amiga- als auch in der Macintosh-Version fehlen. Es heiУŸt
versionsт€œ
und kann hier heruntergeladen werden:
- http://www.scummvm.org/games/#feeble
+ https://www.scummvm.org/games/#feeble
Windows:
Wenn Sie die Windows-Version von Floyd т€“ Es gibt noch Helden haben, sind einige
@@ -1281,15 +1281,14 @@ Zork Nemesis: Das verbotene Land
Alle Versionen
Laden Sie das Liberation(tm)-Schriftartenpaket unter
-https://fedorahosted.org/releases/l/i/liberation-fonts/liberation-fonts-ttf-
-2.00.1.tar.gz
+https://releases.pagure.org/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
+https://www.thezorklibrary.com/installguides/znpatch.zip
herunter und entpacken Sie das Verzeichnis "addon" in das Hauptverzeichnis des
Spiels.
@@ -1360,7 +1359,7 @@ 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
+https://www.thezorklibrary.com/installguides/Zpatch.exe
MУЖglicherweise mУМssen Sie das Spiel zuvor normal installieren, da der Patch ein
eigenes Installationsprogramm besitzt.
@@ -1589,7 +1588,7 @@ gestartet werden -- siehe nУЄchster Abschnitt.
(GM-Emulation deaktiviert)
--enable-gs Aktiviert Roland-GS-Modus fУМr MIDI-Wiedergabe.
--output-rate=FREQUENZ WУЄhlt Ausgabefrequenz in Hz (z. B. 22050).
- --opl-driver=TREIBER WУЄhlt AdLib-(OPL-)Emulator (db, mame).
+ --opl-driver=TREIBER WУЄhlt AdLib-(OPL-)Emulator (db, mame, nuked).
--aspect-ratio Aktiviert SeitenverhУЄltniskorrektur.
--render-mode=MODUS Aktiviert zusУЄtzlichen Render-Modus (hercGreen,
hercAmber, cga, ega, vga, amiga, fmtowns, pc9821,
@@ -3039,13 +3038,13 @@ 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
verwenden mУЖchten, mУМssen Sie den Assembler nasm installieren
-(siehe http://nasm.sf.net). Beachten Sie, dass wir momentan nur fУМr x86 MMX
+(siehe https://nasm.us/). Beachten Sie, dass wir momentan nur fУМr x86 MMX
optimierte Versionen haben und diese auf keinem anderen Prozessor kompiliert
werden kУЖnnen.
-Bei Win9x/NT/XP kУЖnnen Sie USE_WINDBG definieren und WinDbg anhУЄngen, um
+Unter Windows kУЖnnen Sie USE_WINDBG definieren und WinDbg anhУЄngen, um
Debug-Nachrichten zu durchsuchen
-(siehe http://www.sysinternals.com/ntw2k/freeware/debugview.shtml).
+(siehe https://docs.microsoft.com/de-de/windows-hardware/drivers/debugger/index).
Windows:
@@ -3137,11 +3136,11 @@ http://wiki.scummvm.org/index.php/Compiling_ScummVM/Mac_OS_X_Crosscompiling
Eine ausfУМhrliche Liste derjenigen, die ScummVM ermУЖglicht haben, finden Sie
unter:
- http://www.scummvm.org/credits
+ https://www.scummvm.org/credits/
------------------------------------------------------------------------
Viel GlУМck und viel SpaУŸ beim Spielen wУМnscht
das ScummVM-Team.
-http://www.scummvm.org/
+https://www.scummvm.org/
------------------------------------------------------------------------
diff --git a/doc/de/NEUES b/doc/de/NEUES
index 6d3a1eef4c..1ee2283242 100644
--- a/doc/de/NEUES
+++ b/doc/de/NEUES
@@ -543,7 +543,7 @@ Programmcodes finden Sie auf Englisch unter:
KQ6, LB2, LSL2, LSL5, Pharkas, PQ1VGA, SQ4 und SQ5 beseitigt.
- MIDI-Parser verbessert, sodass Musikereignisse genauer verarbeitet werden.
-SCUMM:
+ SCUMM:
- Spielstandsbenennungsschema von HE-Spielen geУЄndert, sodass immer der
Zielname des Spiels enthalten ist.
- Fehler beseitigt, durch den man mehrere Trainer in Backyard Football hatte.
diff --git a/doc/de/Schnellstart b/doc/de/Schnellstart
index 6340a3bee4..bb996fc45c 100644
--- a/doc/de/Schnellstart
+++ b/doc/de/Schnellstart
@@ -5,7 +5,7 @@ sich die englische README-Datei ansehen.
FУМr weitere Informationen, KompatibilitУЄtslisten, Einzelheiten zu Spenden, die
neusten verУЖffentlichten Versionen, Fortschrittsberichte und mehr besuchen Sie
-bitte die ScummVM-Website unter der Adresse: http://www.scummvm.org/
+bitte die ScummVM-Website unter der Adresse: https://www.scummvm.org/
Inhaltsverzeichnis:
@@ -83,7 +83,7 @@ bitte die Anleitung in der englischen README-Datei.
FУМr die ungeduldigen unter den Anwendern ist hier in fУМnf einfachen Schritten
kurz beschrieben, wie man ScummVM lauffУЄhig macht und das Programm verwendet.
-1. Laden Sie ScummVM unter der Adresse http://www.scummvm.org/downloads.php
+1. Laden Sie ScummVM unter der Adresse https://www.scummvm.org/downloads/
herunter und installieren Sie es.
2. Erstellen Sie ein Verzeichnis auf Ihrer Festplatte und kopieren Sie die
@@ -149,7 +149,7 @@ Version von git oder des Daily Builds auftritt. Bitte sehen Sie auch auf der
KompatibilitУЄtsliste der ScummVM-Website fУМr dieses Spiel nach, um
sicherzustellen, dass das Problem nicht bereits bekannt ist:
- http://www.scummvm.org/compatibility_stable.php
+ https://www.scummvm.org/compatibility/
Bitte berichten Sie keine Fehler zu Spielen, die nicht als durchspielbar im
Bereich т€žSupported Gamesт€œ oder der KompatibilitУЄtsliste aufgelistet sind.
diff --git a/doc/es/InicioRapido b/doc/es/InicioRapido
index 3848b049f1..b3fa4ccb32 100644
--- a/doc/es/InicioRapido
+++ b/doc/es/InicioRapido
@@ -5,7 +5,7 @@ buscar en el README original.
Para conseguir mУЁs informaciУГn, listas de compatibilidad, instrucciones para
colaborar econУГmicamente, la УКltima actualizaciУГn, informes de progreso,
-etcУЉtera, por favor, visita la pУЁgina oficial de ScummVM: http://www.scummvm.org/
+etcУЉtera, por favor, visita la pУЁgina oficial de ScummVM: https://www.scummvm.org/
Contenidos:
------------------
@@ -74,7 +74,7 @@ prefieras seguir la guУ­a del archivo README inglУЉs.
Para los impacientes, estos son los cinco pasos bУЁsicos para
hacer funcionar ScummVM:
-1. Descarga ScummVM desde <http://www.scummvm.org/downloads.php> e
+1. Descarga ScummVM desde <https://www.scummvm.org/downloads/> e
instУЁlalo.
2. Crea una carpeta en tu disco duro y copia los archivos originales
@@ -137,7 +137,7 @@ tambiУЉn la lista de problemas conocidos (mУЁs abajo), y la lista
de compatibilidad de ese juego concreto, para confirmar que
no se trata de un fallo ya conocido:
- http://www.scummvm.org/compatibility_stable.php
+ https://www.scummvm.org/compatibility/
Por favor, no informes de fallos en juegos que no aparezcan como
completables en la secciУГn de juegos compatibles. Ya sabemos que
diff --git a/doc/fr/DemarrageRapide b/doc/fr/DemarrageRapide
index bf8ddf28e0..8d820fb3a4 100644
--- a/doc/fr/DemarrageRapide
+++ b/doc/fr/DemarrageRapide
@@ -5,7 +5,7 @@ un peu l'anglais, jetez un coup d'oeil au fichier README anglais.
Pour plus d'informations, liste des jeux compatibles, dУЉtails pour
faire un don, la derniУЈre version disponibles et bien plus encore,
-visitez le site web de ScummVM У  l'adresse http://www.scummvm.org/
+visitez le site web de ScummVM У  l'adresse https://www.scummvm.org/
Table des matiУЈres:
-------------------
@@ -81,7 +81,7 @@ il est sans doute prУЉfУЉrable de lire le fichier README Anglais.
Pour les plus impatients, voici comment obtenir ScummVM en cinq УЉtapes
simples.
-1. TУЉlУЉcharger ScummVM sur <http://www.scummvm.org/downloads.php> et
+1. TУЉlУЉcharger ScummVM sur <https://www.scummvm.org/downloads/> et
installer l'application.
2. CrУЉez un rУЉpertoire sur votre disque dur et copier les fichiers de
@@ -145,7 +145,7 @@ vУЉrifiez que le bogue est reproductible, et se produit encore dans la
connus (ci-dessous) et la liste de compatibilitУЉ sur notre site Web pour
ce jeu, pour s'assurer que le problУЈme n'est pas dУЉjУ  connue:
- http://www.scummvm.org/compatibility_stable.php
+ https://www.scummvm.org/compatibility/
Veuillez ne pas rapporter de bogues sur les jeux qui ne sont pas
rУЉpertoriУЉs comme УЉtant finissable sur la liste de compatibilitУЉ. Nous
diff --git a/doc/it/GuidaRapida b/doc/it/GuidaRapida
index 82059b0342..9ed9d92deb 100644
--- a/doc/it/GuidaRapida
+++ b/doc/it/GuidaRapida
@@ -5,7 +5,7 @@ file README inglese.
Per maggiori informazioni, liste di compatibilitУ , dettagli sulle
donazioni, ultime versioni, resoconti sui progressi e altro, ti
-consigliamo di visitare il sito di ScummVM: http://www.scummvm.org/
+consigliamo di visitare il sito di ScummVM: https://www.scummvm.org/
Indice dei contenuti:
---------------------
@@ -77,7 +77,7 @@ preferire la guida in inglese nel file README.
Per chi non puУВ aspettare, di seguito УЈ spiegato come far partire
ScummVM in cinque semplici passi.
-1. Scarica ScummVM da <http://www.scummvm.org/downloads.php> e
+1. Scarica ScummVM da <https://www.scummvm.org/downloads/> e
installalo.
2. Crea una cartella sul disco rigido e copia i file di gioco dal
@@ -137,7 +137,7 @@ riproducibile e che si verifichi nell'ultima versione giornaliera SVN.
Controlla anche la lista dei problemi noti e la lista di compatibilitУ 
sul nostro sito, per assicurarti che il problema non sia giУ  noto:
- http://www.scummvm.org/compatibility_stable.php
+ https://www.scummvm.org/compatibility/
Per favore non segnalare bug di giochi che non sono segnati come
completabili nella sezione "Supported Games" o nella lista di
diff --git a/doc/no-nb/HurtigStart b/doc/no-nb/HurtigStart
index be59253945..e25ad8d3e0 100644
--- a/doc/no-nb/HurtigStart
+++ b/doc/no-nb/HurtigStart
@@ -5,7 +5,7 @@ i den engelske README-filen.
For mer informasjon, kompatibilitetslister, donasjonsdetaljer, nyeste versjon
av ScummVM, fremdriftsoversikt med mer, besУИk ScummVMs hjemmeside pУЅ:
-http://www.scummvm.org/
+https://www.scummvm.org/
Innholdsfortegnelse:
-------------------
@@ -75,7 +75,7 @@ i den engelske README-filen.
For de rastlУИse; en enkel femstegs-gaid til УЅ fУЅ ScummVM opp og kjУИre:
-1. Last ned ScummVM fra <http://www.scummvm.org/downloads.php> og installer.
+1. Last ned ScummVM fra <https://www.scummvm.org/downloads/> og installer.
2. Lag en mappe pУЅ harddisken din, og kopier spill-datafilene fra original-
mediene til denne mappen. Gjenta dette for alle spillene du УИnsker УЅ spille.
@@ -132,7 +132,7 @@ lenger ned i dette dokumentet, og kompatibilitetslisten pУЅ hjemmesiden
vУЅr angУЅende spillet det gjelder, for УЅ forsikre deg om at problemet ikke
allerede har blitt rapportert:
- http://www.scummvm.org/compatibility_stable.php
+ https://www.scummvm.org/compatibility/
Vennligst ikke rapporter bugs om spill som ikke stУЅr listet som
ТЋcompletableТЛ i ТЋSupported GamesТЛ-seksjonen, eller pУЅ kompatibilitetslisten.
diff --git a/doc/se/LasMig b/doc/se/LasMig
index d47918d1f4..d61d16ed6b 100644
--- a/doc/se/LasMig
+++ b/doc/se/LasMig
@@ -1,7 +1,7 @@
ScummVM LУ„S MIG
------------------------------------------------------------------------
-FУЖr ytterligare information, kompatibilitetslistor, donationsdetaljer, den senaste programversionen, utvecklingsrapporter med mera, var god besУЖk ScummVM:s hemsida pУЅ http://www.scummvm.org/
+FУЖr ytterligare information, kompatibilitetslistor, donationsdetaljer, den senaste programversionen, utvecklingsrapporter med mera, var god besУЖk ScummVM:s hemsida pУЅ https://www.scummvm.org/
InnehУЅll:
---------
@@ -83,7 +83,7 @@ VIKTIGT: Den hУЄr korta guiden fУЖrutsУЄtter att du anvУЄnder ScummVM pУЅ svensk
FУЖr de otУЅliga fУЖljer hУЄr instruktioner fУЖr att kУЖra igУЅng ScummVM i fem enkla steg.
-1. Ladda hem ScummVM frУЅn http://www.scummvm.org/downloads.php och installera programmet.
+1. Ladda hem ScummVM frУЅn https://www.scummvm.org/downloads/ och installera programmet.
2. Skapa en filkatalog pУЅ din hУЅrddisk och kopiera spelets datafiler frУЅn dess ursprungliga plats till den nya katalogen. Upprepa det hУЄr steget fУЖr varje spel du vill spela (det УЄr bУЄttre att anvУЄnda separata kataloger fУЖr vaje spel).
@@ -115,7 +115,7 @@ Det enklaste sУЄttet att kontakta ScummVM-teamet УЄr att skicka in bugg-rapporte
---- ----------------------
FУЖr att rapportera en bugg mУЅste du skapa ett konto hos SourceForge och fУЖlja т€œBug Trackerт€-lУЄnken frУЅn vУЅran hemsida. Var god se till att buggen kan reproduceras med sУЄkerhet och att den fortfarande УЄr aktiv i den senaste git/Daily build-versionen. Se УЄven till att kontrollera att felet inte redan rapporterats genom att lУЄsa listan av kУЄnda fel fУЖr spelet pУЅ vУЅran kompatibilitetssida:
- http://www.scummvm.org/compatibility_stable.php
+ https://www.scummvm.org/compatibility/
Var god rapportera inte buggar fУЖr spel som inte УЄr mУЖjliga att avklara enligt т€œSupported Gamesт€-avdelningen, eller i kompatibilitetslistan. Vi vet redan att dessa spel УЄr buggiga.
@@ -408,7 +408,7 @@ FУЖr PlayStation-versionerna kan du dumpa originalfilmerna frУЅn CD:n. Dumpa var
Vissa nyutgУЅvor av spelen, tillika PlayStation-versionen, har inga Smacker videos. Revolution Software har varit goda nog att skapa nykodade filmscener som kan laddas hem frУЅn vУЅran hemsida:
- http://www.scummvm.org/downloads.php
+ https://www.scummvm.org/downloads/
Dessa filmscener УЄr tillgУЄngliga i DXA-format med FLAC-ljud. Kvaliteten УЄr densamma som i originalversionerna av spelet tack vare ickedestruktiv komprimering. FУЖr att se dessa filmscener krУЄvs en version av ScummVM som kompilerats med stУЖd fУЖr bУЅde FLAC och zlib.
@@ -712,7 +712,7 @@ Ordning: scummvm [INSTУ„LLNINGAR]... [SPEL]
--native-mt32 True Roland MT-32 (deaktivera GM-emulation)
--enable-gs Aktivera Roland GS-lУЄge fУЖr MIDI-uppspelning
--output-rate=RATE VУЄlj ljudfrekvens i Hz (t.ex. 22050)
- --opl-driver=DRIVER VУЄlj AdLib (OPL)-emulator (db, mame)
+ --opl-driver=DRIVER VУЄlj AdLib (OPL)-emulator (db, mame, nuked)
--aspect-ratio Aktivera korrektion av bildfУЖrhУЅllande
--render-mode=MODE Aktivera ytterligare renderingslУЄgen (cga, ega,
hercGreen, hercAmber, amiga)
@@ -1724,9 +1724,9 @@ FУЖr en uppdaterad УЖverblick fУЖr hur man kompilerar ScummVM pУЅ diverse plattf
Om du kompilerar fУЖr Windows, Linux eller Mac OS X behУЖver du SDL-1.2.2 eller senare (УЄldre versioner kan fungera, men stУЖds inte) och ett stУЖtt kompileringsprogram. Flera kompileringsprogram inklusive GCC, mingw och senare versioner av Microsoft Visual C++ stУЖds. Om du vill anvУЄnda MP3-komprimerade CD-spУЅr eller .SOU-filer mУЅste du installera MAD-biblioteket; pУЅ samma sУЄtt behУЖver du de nУЖdvУЄndiga biblioteken fУЖr Ogg Vorbis och FLAC-komprimerat ljud. FУЖr komprimerade spardata krУЄvs zlib.
-Vissa delar av ScummVM, speciellt skalningsfilter, har optimerade versioner skrivna i assembler-kod. Om du vill anvУЄnda dem mУЅste du installera nasm-assemblern (se http://nasm.sf.net). MУЄrk att vi fУЖr tillfУЄllet endast har optimerade versioner fУЖr x86 MMX och att de inte kan kompileras med andra processorer.
+Vissa delar av ScummVM, speciellt skalningsfilter, har optimerade versioner skrivna i assembler-kod. Om du vill anvУЄnda dem mУЅste du installera nasm-assemblern (se https://nasm.us/). MУЄrk att vi fУЖr tillfУЄllet endast har optimerade versioner fУЖr x86 MMX och att de inte kan kompileras med andra processorer.
-PУЅ Win9x/NT/XP kan du definiera USE_WINDBG och lУЄgga till WinDbg fУЖr att visa debug-meddelanden (se http://www.sysinternals.com/ntw2k/freeware/debugview.shtml).
+PУЅ Windows kan du definiera USE_WINDBG och lУЄgga till WinDbg fУЖr att visa debug-meddelanden (se https://docs.microsoft.com/sv-se/windows-hardware/drivers/debugger/index).
GCC och MinGW32:
* Skriv "./configure"
@@ -1756,7 +1756,7 @@ PУЅ Win9x/NT/XP kan du definiera USE_WINDBG och lУЄgga till WinDbg fУЖr att visa
* SDL-utvecklingspaketet fУЖr OS X som finns tillgУЄngligt pУЅ SLD:s hemsida
УЄr INTE lУЄmpligt. Du behУЖver istУЄllet en unix-artad kompilation av SDL.
Ett sУЄtt att fУЅ tag i en sУЅdan УЄr att installera SDL via Fink
- (http://fink.sf.net). Annars kan du kompilera SDL manuellt frУЅn kУЄllkoden
+ (http://www.finkproject.org/). Annars kan du kompilera SDL manuellt frУЅn kУЄllkoden
med unix build-systemet (configure && make).
* Skriv "./configure" i ScummVM-katalogen.
* Du kan nu skriva т€makeт€ fУЖr att skapa en kommandorad-binary.
diff --git a/doc/se/Snabbstart b/doc/se/Snabbstart
index bf37de5d2f..b0111f72a2 100644
--- a/doc/se/Snabbstart
+++ b/doc/se/Snabbstart
@@ -1,6 +1,6 @@
Det hУЄr dokumentet УЄr en ofullstУЄndig УЖversУЄttning av den engelska README-filen. Det sistnУЄmnda dokumentet innehУЅller mer information sУЅ om du inte kan hitta vad du behУЖver hУЄr (och pratar lite engelska), ta en titt i den engelska README-filen.
-FУЖr ytterligare information, kompatibilitetslistor, donationsdetaljer, den senaste programversionen, utvecklingsrapporter med mera, var god besУЖk ScummVM:s hemsida pУЅ http://www.scummvm.org/
+FУЖr ytterligare information, kompatibilitetslistor, donationsdetaljer, den senaste programversionen, utvecklingsrapporter med mera, var god besУЖk ScummVM:s hemsida pУЅ https://www.scummvm.org/
InnehУЅll:
---------
@@ -33,7 +33,7 @@ VIKTIGT: Den hУЄr korta guiden fУЖrutsУЄtter att du anvУЄnder ScummVM pУЅ svensk
FУЖr de otУЅliga fУЖljer hУЄr instruktioner fУЖr att kУЖra igУЅng ScummVM i fem enkla steg.
-1. Ladda hem ScummVM frУЅn http://www.scummvm.org/downloads.php och installera programmet.
+1. Ladda hem ScummVM frУЅn https://www.scummvm.org/downloads/ och installera programmet.
2. Skapa en filkatalog pУЅ din hУЅrddisk och kopiera spelets datafiler frУЅn dess ursprungliga plats till den nya katalogen. Upprepa det hУЄr steget fУЖr varje spel du vill spela (det УЄr bУЄttre att anvУЄnda separata kataloger fУЖr vaje spel).
@@ -63,7 +63,7 @@ Det enklaste sУЄttet att kontakta ScummVM-teamet УЄr att skicka in bugg-rapporte
---- ----------------------
FУЖr att rapportera en bugg mУЅste du skapa ett konto hos SourceForge och fУЖlja Т“Bug TrackerТ”-lУЄnken frУЅn vУЅran hemsida. Var god se till att buggen kan reproduceras med sУЄkerhet och att den fortfarande УЄr aktiv i den senaste git/Daily build-versionen. Se УЄven till att kontrollera att felet inte redan rapporterats genom att lУЄsa listan av kУЄnda fel fУЖr spelet pУЅ vУЅran kompatibilitetssida:
- http://www.scummvm.org/compatibility_stable.php
+ https://www.scummvm.org/compatibility/
Var god rapportera inte buggar fУЖr spel som inte УЄr mУЖjliga att avklara enligt Т“Supported GamesТ”-avdelningen, eller i kompatibilitetslistan. Vi vet redan att dessa spel УЄr buggiga.
diff --git a/engines/access/access.cpp b/engines/access/access.cpp
index 1855280a24..c1af19026b 100644
--- a/engines/access/access.cpp
+++ b/engines/access/access.cpp
@@ -488,11 +488,6 @@ Common::Error AccessEngine::loadGameState(int slot) {
if (!readSavegameHeader(saveFile, header))
error("Invalid savegame");
- if (header._thumbnail) {
- header._thumbnail->free();
- delete header._thumbnail;
- }
-
// Load most of the savegame data
synchronize(s);
delete saveFile;
@@ -537,9 +532,8 @@ void AccessEngine::synchronize(Common::Serializer &s) {
const char *const SAVEGAME_STR = "ACCESS";
#define SAVEGAME_STR_SIZE 6
-bool AccessEngine::readSavegameHeader(Common::InSaveFile *in, AccessSavegameHeader &header) {
+WARN_UNUSED_RESULT bool AccessEngine::readSavegameHeader(Common::InSaveFile *in, AccessSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
- header._thumbnail = nullptr;
// Validate the header Id
in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
@@ -557,9 +551,9 @@ bool AccessEngine::readSavegameHeader(Common::InSaveFile *in, AccessSavegameHead
header._saveName += ch;
// Get the thumbnail
- header._thumbnail = Graphics::loadThumbnail(*in);
- if (!header._thumbnail)
+ if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
header._year = in->readSint16LE();
diff --git a/engines/access/access.h b/engines/access/access.h
index 972dd4c380..56646f01c9 100644
--- a/engines/access/access.h
+++ b/engines/access/access.h
@@ -306,7 +306,7 @@ public:
/**
* Read in a savegame header
*/
- static bool readSavegameHeader(Common::InSaveFile *in, AccessSavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, AccessSavegameHeader &header, bool skipThumbnail = true);
/**
* Write out a savegame header
diff --git a/engines/access/detection.cpp b/engines/access/detection.cpp
index 3e70de3635..186fcbdf06 100644
--- a/engines/access/detection.cpp
+++ b/engines/access/detection.cpp
@@ -157,11 +157,9 @@ SaveStateList AccessMetaEngine::listSaves(const char *target) const {
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
- Access::AccessEngine::readSavegameHeader(in, header);
- saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+ if (Access::AccessEngine::readSavegameHeader(in, header))
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
- header._thumbnail->free();
- delete header._thumbnail;
delete in;
}
}
@@ -187,7 +185,11 @@ SaveStateDescriptor AccessMetaEngine::querySaveMetaInfos(const char *target, int
if (f) {
Access::AccessSavegameHeader header;
- Access::AccessEngine::readSavegameHeader(f, header);
+ if (!Access::AccessEngine::readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
+
delete f;
// Create the return descriptor
diff --git a/engines/access/scripts.cpp b/engines/access/scripts.cpp
index 2cebc3e3c6..a0b4ef68ee 100644
--- a/engines/access/scripts.cpp
+++ b/engines/access/scripts.cpp
@@ -152,7 +152,7 @@ void Scripts::searchForSequence() {
_data->seek(0);
int sequenceId;
do {
- while (_data->readByte() != SCRIPT_START_BYTE) ;
+ while (_data->readByte() != SCRIPT_START_BYTE) {}
sequenceId = _data->readUint16LE();
} while (sequenceId != _sequence);
}
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index e63beb2c07..2276576baa 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -332,9 +332,9 @@ public:
int getMaximumSaveSlot() const { return 'O' - 'A'; }
SaveStateList listSaves(const char *target) const;
void removeSaveState(const char *target, int slot) const;
- virtual ADGameDescList detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const;
+ ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const override;
- bool addFileProps(const FileMap &allFiles, Common::String fname, ADFilePropertiesMap &filePropsMap) const;
+ bool addFileProps(const FileMap &allFiles, Common::String fname, FilePropertiesMap &filePropsMap) const;
bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const;
};
@@ -401,7 +401,11 @@ SaveStateDescriptor AdlMetaEngine::querySaveMetaInfos(const char *target, int sl
return SaveStateDescriptor();
}
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*inFile);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*inFile, thumbnail)) {
+ delete inFile;
+ return SaveStateDescriptor();
+ }
sd.setThumbnail(thumbnail);
delete inFile;
@@ -488,14 +492,14 @@ Common::Platform getPlatform(const AdlGameDescription &adlDesc) {
return adlDesc.desc.platform;
}
-bool AdlMetaEngine::addFileProps(const FileMap &allFiles, Common::String fname, ADFilePropertiesMap &filePropsMap) const {
+bool AdlMetaEngine::addFileProps(const FileMap &allFiles, Common::String fname, FilePropertiesMap &filePropsMap) const {
if (filePropsMap.contains(fname))
return true;
if (!allFiles.contains(fname))
return false;
- ADFileProperties fileProps;
+ FileProperties fileProps;
fileProps.size = computeMD5(allFiles[fname], fileProps.md5, 16384);
if (fileProps.size != -1) {
@@ -507,42 +511,39 @@ bool AdlMetaEngine::addFileProps(const FileMap &allFiles, Common::String fname,
}
// Based on AdvancedMetaEngine::detectGame
-ADGameDescList AdlMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
+ADDetectedGames AdlMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
// We run the file-based detector first and then add to the returned list
- ADGameDescList matched = AdvancedMetaEngine::detectGame(parent, allFiles, language, platform, extra);
+ ADDetectedGames matched = AdvancedMetaEngine::detectGame(parent, allFiles, language, platform, extra);
debug(3, "Starting disk image detection in dir '%s'", parent.getPath().c_str());
- ADFilePropertiesMap filesProps;
- ADGameIdList matchedGameIds;
+ FilePropertiesMap filesProps;
bool gotAnyMatchesWithAllFiles = false;
for (uint g = 0; gameDiskDescriptions[g].desc.gameId != 0; ++g) {
- const ADGameDescription &desc = gameDiskDescriptions[g].desc;
+ ADDetectedGame game(&gameDiskDescriptions[g].desc);
// Skip games that don't meet the language/platform/extra criteria
- if (language != Common::UNK_LANG && desc.language != Common::UNK_LANG) {
- if (desc.language != language && !(language == Common::EN_ANY && (desc.flags & ADGF_ADDENGLISH)))
- continue;
+ if (language != Common::UNK_LANG && game.desc->language != Common::UNK_LANG) {
+ if (game.desc->language != language && !(language == Common::EN_ANY && (game.desc->flags & ADGF_ADDENGLISH)))
+ continue;
}
- if (platform != Common::kPlatformUnknown && desc.platform != Common::kPlatformUnknown && desc.platform != platform)
+ if (platform != Common::kPlatformUnknown && game.desc->platform != Common::kPlatformUnknown && game.desc->platform != platform)
continue;
- if ((_flags & kADFlagUseExtraAsHint) && !extra.empty() && desc.extra != extra)
+ if ((_flags & kADFlagUseExtraAsHint) && !extra.empty() && game.desc->extra != extra)
continue;
- bool fileMissing = false;
bool allFilesPresent = true;
- bool hashOrSizeMismatch = false;
- for (uint f = 0; desc.filesDescriptions[f].fileName; ++f) {
- const ADGameFileDescription &fDesc = desc.filesDescriptions[f];
+ for (uint f = 0; game.desc->filesDescriptions[f].fileName; ++f) {
+ const ADGameFileDescription &fDesc = game.desc->filesDescriptions[f];
Common::String fileName;
bool foundDiskImage = false;
for (uint e = 0; e < ARRAYSIZE(diskImageExts); ++e) {
- if (diskImageExts[e].platform == desc.platform) {
+ if (diskImageExts[e].platform == game.desc->platform) {
Common::String testFileName(fDesc.fileName);
testFileName += diskImageExts[e].extension;
@@ -559,49 +560,41 @@ ADGameDescList AdlMetaEngine::detectGame(const Common::FSNode &parent, const Fil
}
if (!foundDiskImage) {
- fileMissing = true;
allFilesPresent = false;
break;
}
- if (hashOrSizeMismatch)
+ game.matchedFiles[fileName] = filesProps[fileName];
+
+ if (game.hasUnknownFiles)
continue;
if (fDesc.md5 && fDesc.md5 != filesProps[fileName].md5) {
debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fDesc.md5, filesProps[fileName].md5.c_str());
- fileMissing = true;
- hashOrSizeMismatch = true;
+ game.hasUnknownFiles = true;
continue;
}
if (fDesc.fileSize != -1 && fDesc.fileSize != filesProps[fileName].size) {
debug(3, "Size Mismatch. Skipping");
- fileMissing = true;
- hashOrSizeMismatch = true;
+ game.hasUnknownFiles = true;
continue;
}
debug(3, "Matched file: %s", fileName.c_str());
}
- if (!fileMissing) {
- debug(2, "Found game: %s (%s/%s) (%d)", desc.gameId, getPlatformDescription(desc.platform), getLanguageDescription(desc.language), g);
- matched.push_back(&desc);
+ if (allFilesPresent && !game.hasUnknownFiles) {
+ debug(2, "Found game: %s (%s/%s) (%d)", game.desc->gameId, getPlatformDescription(game.desc->platform), getLanguageDescription(game.desc->language), g);
+ gotAnyMatchesWithAllFiles = true;
+ matched.push_back(game);
} else {
- if (allFilesPresent) {
- gotAnyMatchesWithAllFiles = true;
- if (!matchedGameIds.size() || strcmp(matchedGameIds.back(), desc.gameId) != 0)
- matchedGameIds.push_back(desc.gameId);
+ if (allFilesPresent && !gotAnyMatchesWithAllFiles) {
+ if (matched.empty() || strcmp(matched.back().desc->gameId, game.desc->gameId) != 0)
+ matched.push_back(game);
}
- debug(5, "Skipping game: %s (%s/%s) (%d)", desc.gameId, getPlatformDescription(desc.platform), getLanguageDescription(desc.language), g);
- }
- }
-
- // TODO: This could be improved to handle matched and unknown games together in a single directory
- if (matched.empty()) {
- if (!filesProps.empty() && gotAnyMatchesWithAllFiles) {
- reportUnknown(parent, filesProps, matchedGameIds);
+ debug(5, "Skipping game: %s (%s/%s) (%d)", game.desc->gameId, getPlatformDescription(game.desc->platform), getLanguageDescription(game.desc->language), g);
}
}
diff --git a/engines/adl/graphics.cpp b/engines/adl/graphics.cpp
index 0f80bac988..2fcd1473a0 100644
--- a/engines/adl/graphics.cpp
+++ b/engines/adl/graphics.cpp
@@ -350,7 +350,7 @@ void GraphicsMan_v2::fillAt(Common::Point p, const byte pattern) {
const bool stopBit = !_display.getPixelBit(p);
// Move up into the open space above p
- while (--p.y >= _bounds.top && canFillAt(p, stopBit));
+ while (--p.y >= _bounds.top && canFillAt(p, stopBit)) {}
// Then fill by moving down
while (++p.y < _bounds.bottom && canFillAt(p, stopBit))
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index 9d695058dd..6f4efcfb57 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -33,32 +33,16 @@
#include "engines/advancedDetector.h"
#include "engines/obsolete.h"
-static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGameDescriptor *sg) {
- const char *title = 0;
- const char *extra;
-
- if (g.flags & ADGF_USEEXTRAASTITLE) {
- title = g.extra;
- extra = "";
- } else {
- while (sg->gameId) {
- if (!scumm_stricmp(g.gameId, sg->gameId))
- title = sg->description;
- sg++;
- }
+static Common::String sanitizeName(const char *name) {
+ Common::String res;
- extra = g.extra;
+ while (*name) {
+ if (Common::isAlnum(*name))
+ res += tolower(*name);
+ name++;
}
- GameSupportLevel gsl = kStableGame;
- if (g.flags & ADGF_UNSTABLE)
- gsl = kUnstableGame;
- else if (g.flags & ADGF_TESTING)
- gsl = kTestingGame;
-
- GameDescriptor gd(g.gameId, title, g.language, g.platform, 0, gsl);
- gd.updateDesc(extra);
- return gd;
+ return res;
}
/**
@@ -67,8 +51,14 @@ static GameDescriptor toGameDescriptor(const ADGameDescription &g, const PlainGa
* or (if ADGF_DEMO has been set)
* GAMEID-demo-PLAFORM-LANG
*/
-static Common::String generatePreferredTarget(const Common::String &id, const ADGameDescription *desc) {
- Common::String res(id);
+static Common::String generatePreferredTarget(const ADGameDescription *desc) {
+ Common::String res;
+
+ if (desc->flags & ADGF_AUTOGENTARGET && desc->extra && *desc->extra) {
+ res = sanitizeName(desc->extra);
+ } else {
+ res = desc->gameId;
+ }
if (desc->flags & ADGF_DEMO) {
res = res + "-demo";
@@ -89,49 +79,50 @@ 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++;
- }
+DetectedGame AdvancedMetaEngine::toDetectedGame(const ADDetectedGame &adGame) const {
+ const ADGameDescription *desc = adGame.desc;
- return res;
-}
+ const char *gameId = _singleId ? _singleId : desc->gameId;
-void AdvancedMetaEngine::updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const {
- if (_singleId != NULL) {
- desc["preferredtarget"] = desc["gameid"];
- desc["gameid"] = _singleId;
+ const char *title;
+ const char *extra;
+ if (desc->flags & ADGF_USEEXTRAASTITLE) {
+ title = desc->extra;
+ extra = "";
+ } else {
+ const PlainGameDescriptor *pgd = findPlainGameDescriptor(desc->gameId, _gameIds);
+ title = pgd->description;
+ extra = desc->extra;
}
- if (!desc.contains("preferredtarget"))
- desc["preferredtarget"] = desc["gameid"];
+ DetectedGame game(gameId, title, desc->language, desc->platform, extra);
+ game.hasUnknownFiles = adGame.hasUnknownFiles;
+ game.matchedFiles = adGame.matchedFiles;
+ game.preferredTarget = generatePreferredTarget(desc);
- if (realDesc->flags & ADGF_AUTOGENTARGET) {
- if (*realDesc->extra)
- desc["preferredtarget"] = sanitizeName(realDesc->extra);
- }
+ game.gameSupportLevel = kStableGame;
+ if (desc->flags & ADGF_UNSTABLE)
+ game.gameSupportLevel = kUnstableGame;
+ else if (desc->flags & ADGF_TESTING)
+ game.gameSupportLevel = kTestingGame;
- desc["preferredtarget"] = generatePreferredTarget(desc["preferredtarget"], realDesc);
+ game.setGUIOptions(desc->guiOptions + _guiOptions);
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(desc->language));
- if (_flags & kADFlagUseExtraAsHint)
- desc["extra"] = realDesc->extra;
+ if (desc->flags & ADGF_ADDENGLISH)
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY));
- desc.setGUIOptions(realDesc->guiOptions + _guiOptions);
- desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(realDesc->language));
+ if (_flags & kADFlagUseExtraAsHint)
+ game.extra = desc->extra;
- if (realDesc->flags & ADGF_ADDENGLISH)
- desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY));
+ return game;
}
-bool cleanupPirated(ADGameDescList &matched) {
+bool cleanupPirated(ADDetectedGames &matched) {
// OKay, now let's sense presence of pirated games
if (!matched.empty()) {
for (uint j = 0; j < matched.size();) {
- if (matched[j]->flags & ADGF_PIRATED)
+ if (matched[j].desc->flags & ADGF_PIRATED)
matched.remove_at(j);
else
++j;
@@ -148,35 +139,46 @@ bool cleanupPirated(ADGameDescList &matched) {
}
-GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const {
- ADGameDescList matches;
- GameList detectedGames;
+DetectedGames AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const {
FileMap allFiles;
if (fslist.empty())
- return detectedGames;
+ return DetectedGames();
// Compose a hashmap of all files in fslist.
composeFileHashMap(allFiles, fslist, (_maxScanDepth == 0 ? 1 : _maxScanDepth));
// Run the detector on this
- matches = detectGame(fslist.begin()->getParent(), allFiles, Common::UNK_LANG, Common::kPlatformUnknown, "");
+ ADDetectedGames matches = detectGame(fslist.begin()->getParent(), allFiles, Common::UNK_LANG, Common::kPlatformUnknown, "");
- if (matches.empty()) {
- // 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));
- updateGameDescriptor(desc, fallbackDesc);
- detectedGames.push_back(desc);
+ cleanupPirated(matches);
+
+ DetectedGames detectedGames;
+ for (uint i = 0; i < matches.size(); i++) {
+ DetectedGame game = toDetectedGame(matches[i]);
+
+ if (game.hasUnknownFiles) {
+ // Non fallback games with unknown files cannot be added/launched
+ game.canBeAdded = false;
}
- } else {
- // Otherwise use the found matches
- cleanupPirated(matches);
- for (uint i = 0; i < matches.size(); i++) {
- GameDescriptor desc(toGameDescriptor(*matches[i], _gameIds));
- updateGameDescriptor(desc, matches[i]);
- detectedGames.push_back(desc);
+
+ detectedGames.push_back(game);
+ }
+
+ bool foundKnownGames = false;
+ for (uint i = 0; i < detectedGames.size(); i++) {
+ foundKnownGames |= detectedGames[i].canBeAdded;
+ }
+
+ if (!foundKnownGames) {
+ // Use fallback detector if there were no matches by other means
+ ADDetectedGame fallbackDetectionResult = fallbackDetect(allFiles, fslist);
+
+ if (fallbackDetectionResult.desc) {
+ DetectedGame fallbackDetectedGame = toDetectedGame(fallbackDetectionResult);
+ fallbackDetectedGame.preferredTarget += "-fallback";
+
+ detectedGames.push_back(fallbackDetectedGame);
}
}
@@ -214,7 +216,6 @@ const ExtraGuiOptions AdvancedMetaEngine::getExtraGuiOptions(const Common::Strin
Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) const {
assert(engine);
- const ADGameDescription *agdDesc = 0;
Common::Language language = Common::UNK_LANG;
Common::Platform platform = Common::kPlatformUnknown;
Common::String extra;
@@ -235,18 +236,6 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
path = ConfMan.get("path");
} else {
path = ".";
-
- // This situation may happen only when game was
- // launched from a command line with wrong target and
- // no path was provided.
- //
- // A dummy entry will get created and will keep game path
- // We mark this entry, so it will not be added to the
- // config file.
- //
- // Fixes bug #1544799
- ConfMan.setBool("autoadded", true);
-
warning("No path was provided. Assuming the data files are in the current directory");
}
Common::FSNode dir(path);
@@ -264,46 +253,43 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
composeFileHashMap(allFiles, files, (_maxScanDepth == 0 ? 1 : _maxScanDepth));
// Run the detector on this
- ADGameDescList matches = detectGame(files.begin()->getParent(), allFiles, language, platform, extra);
+ ADDetectedGames matches = detectGame(files.begin()->getParent(), allFiles, language, platform, extra);
if (cleanupPirated(matches))
return Common::kNoGameDataFoundError;
- if (_singleId == NULL) {
- // Find the first match with correct gameid.
- for (uint i = 0; i < matches.size(); i++) {
- if (matches[i]->gameId == gameid) {
- agdDesc = matches[i];
- break;
- }
+ ADDetectedGame agdDesc;
+ for (uint i = 0; i < matches.size(); i++) {
+ if ((_singleId || matches[i].desc->gameId == gameid) && !matches[i].hasUnknownFiles) {
+ agdDesc = matches[i];
+ break;
}
- } else if (matches.size() > 0) {
- agdDesc = matches[0];
}
- if (agdDesc == 0) {
+ if (!agdDesc.desc) {
// Use fallback detector if there were no matches by other means
- agdDesc = fallbackDetect(allFiles, files);
- if (agdDesc != 0) {
+ ADDetectedGame fallbackDetectedGame = fallbackDetect(allFiles, files);
+ agdDesc = fallbackDetectedGame;
+ if (agdDesc.desc) {
// Seems we found a fallback match. But first perform a basic
// sanity check: the gameid must match.
- if (_singleId == NULL && agdDesc->gameId != gameid)
- agdDesc = 0;
+ if (!_singleId && agdDesc.desc->gameId != gameid)
+ agdDesc = ADDetectedGame();
}
}
- if (agdDesc == 0)
+ if (!agdDesc.desc)
return Common::kNoGameDataFoundError;
// If the GUI options were updated, we catch this here and update them in the users config
// file transparently.
- Common::String lang = getGameGUIOptionsDescriptionLanguage(agdDesc->language);
- if (agdDesc->flags & ADGF_ADDENGLISH)
+ Common::String lang = getGameGUIOptionsDescriptionLanguage(agdDesc.desc->language);
+ if (agdDesc.desc->flags & ADGF_ADDENGLISH)
lang += " " + getGameGUIOptionsDescriptionLanguage(Common::EN_ANY);
- Common::updateGameGUIOptions(agdDesc->guiOptions + _guiOptions, lang);
+ Common::updateGameGUIOptions(agdDesc.desc->guiOptions + _guiOptions, lang);
- GameDescriptor gameDescriptor = toGameDescriptor(*agdDesc, _gameIds);
+ DetectedGame gameDescriptor = toDetectedGame(agdDesc);
bool showTestingWarning = false;
@@ -311,53 +297,20 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
showTestingWarning = true;
#endif
- if (((gameDescriptor.getSupportLevel() == kUnstableGame
- || (gameDescriptor.getSupportLevel() == kTestingGame
+ if (((gameDescriptor.gameSupportLevel == kUnstableGame
+ || (gameDescriptor.gameSupportLevel == kTestingGame
&& showTestingWarning)))
&& !Engine::warnUserAboutUnsupportedGame())
return Common::kUserCanceled;
- debug(2, "Running %s", gameDescriptor.description().c_str());
- initSubSystems(agdDesc);
- if (!createInstance(syst, engine, agdDesc))
+ debug(2, "Running %s", gameDescriptor.description.c_str());
+ initSubSystems(agdDesc.desc);
+ if (!createInstance(syst, engine, agdDesc.desc))
return Common::kNoGameDataFoundError;
else
return Common::kNoError;
}
-void AdvancedMetaEngine::reportUnknown(const Common::FSNode &path, const ADFilePropertiesMap &filesProps, const ADGameIdList &matchedGameIds) const {
- Common::String report = Common::String::format(
- _("The game in '%s' seems to be an unknown %s engine game "
- "variant.\n\nPlease report the following data to the ScummVM "
- "team at %s along with the name of the game you tried to add and "
- "its version, language, etc.:"),
- path.getPath().c_str(), getName(), "https://bugs.scummvm.org/");
-
- if (matchedGameIds.size()) {
- report += "\n\n";
- report += _("Matched game IDs:");
- report += " ";
-
- for (ADGameIdList::const_iterator gameId = matchedGameIds.begin(); gameId != matchedGameIds.end(); ++gameId) {
- if (gameId != matchedGameIds.begin()) {
- report += ", ";
- }
- report += *gameId;
- }
- }
-
- report += "\n\n";
-
- report.wordWrap(80);
-
- for (ADFilePropertiesMap::const_iterator file = filesProps.begin(); file != filesProps.end(); ++file)
- report += Common::String::format(" {\"%s\", 0, \"%s\", %d},\n", file->_key.c_str(), file->_value.md5.c_str(), file->_value.size);
-
- report += "\n";
-
- g_system->logMessage(LogMessageType::kInfo, report.c_str());
-}
-
void AdvancedMetaEngine::composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::String &parentName) const {
if (depth <= 0)
return;
@@ -398,7 +351,7 @@ void AdvancedMetaEngine::composeFileHashMap(FileMap &allFiles, const Common::FSL
}
}
-bool AdvancedMetaEngine::getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, ADFileProperties &fileProps) const {
+bool AdvancedMetaEngine::getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const {
// FIXME/TODO: We don't handle the case that a file is listed as a regular
// file and as one with resource fork.
@@ -428,8 +381,9 @@ bool AdvancedMetaEngine::getFileProperties(const Common::FSNode &parent, const F
return true;
}
-ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
- ADFilePropertiesMap filesProps;
+ADDetectedGames AdvancedMetaEngine::detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const {
+ FilePropertiesMap filesProps;
+ ADDetectedGames matched;
const ADGameFileDescription *fileDesc;
const ADGameDescription *g;
@@ -439,12 +393,12 @@ 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 != nullptr; descPtr += _descItemSize) {
g = (const ADGameDescription *)descPtr;
for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) {
Common::String fname = fileDesc->fileName;
- ADFileProperties tmp;
+ FileProperties tmp;
if (filesProps.contains(fname))
continue;
@@ -456,16 +410,13 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons
}
}
- ADGameDescList matched;
- ADGameIdList matchedGameIds;
int maxFilesMatched = 0;
bool gotAnyMatchesWithAllFiles = false;
// 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 != nullptr; descPtr += _descItemSize, ++i) {
g = (const ADGameDescription *)descPtr;
- bool fileMissing = false;
// Do not even bother to look at entries which do not have matching
// language and platform (if specified).
@@ -478,34 +429,33 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons
if ((_flags & kADFlagUseExtraAsHint) && !extra.empty() && g->extra != extra)
continue;
+ ADDetectedGame game(g);
bool allFilesPresent = true;
int curFilesMatched = 0;
- bool hashOrSizeMismatch = false;
// Try to match all files for this game
- for (fileDesc = g->filesDescriptions; fileDesc->fileName; fileDesc++) {
+ for (fileDesc = game.desc->filesDescriptions; fileDesc->fileName; fileDesc++) {
Common::String tstr = fileDesc->fileName;
if (!filesProps.contains(tstr)) {
- fileMissing = true;
allFilesPresent = false;
break;
}
- if (hashOrSizeMismatch)
+ game.matchedFiles[tstr] = filesProps[tstr];
+
+ if (game.hasUnknownFiles)
continue;
- if (fileDesc->md5 != NULL && fileDesc->md5 != filesProps[tstr].md5) {
+ if (fileDesc->md5 != nullptr && fileDesc->md5 != filesProps[tstr].md5) {
debug(3, "MD5 Mismatch. Skipping (%s) (%s)", fileDesc->md5, filesProps[tstr].md5.c_str());
- fileMissing = true;
- hashOrSizeMismatch = true;
+ game.hasUnknownFiles = true;
continue;
}
if (fileDesc->fileSize != -1 && fileDesc->fileSize != filesProps[tstr].size) {
debug(3, "Size Mismatch. Skipping");
- fileMissing = true;
- hashOrSizeMismatch = true;
+ game.hasUnknownFiles = true;
continue;
}
@@ -522,13 +472,12 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons
// Potentially this could rule out variants where some particular file
// is really missing, but the developers should better know about such
// cases.
- if (allFilesPresent) {
- gotAnyMatchesWithAllFiles = true;
- if (!matchedGameIds.size() || strcmp(matchedGameIds.back(), g->gameId) != 0)
- matchedGameIds.push_back(g->gameId);
+ if (allFilesPresent && !gotAnyMatchesWithAllFiles) {
+ if (matched.empty() || strcmp(matched.back().desc->gameId, g->gameId) != 0)
+ matched.push_back(game);
}
- if (!fileMissing) {
+ if (allFilesPresent && !game.hasUnknownFiles) {
debug(2, "Found game: %s (%s %s/%s) (%d)", g->gameId, g->extra,
getPlatformDescription(g->platform), getLanguageDescription(g->language), i);
@@ -537,37 +486,29 @@ ADGameDescList AdvancedMetaEngine::detectGame(const Common::FSNode &parent, cons
maxFilesMatched = curFilesMatched;
matched.clear(); // Remove any prior, lower ranked matches.
- matched.push_back(g);
+ matched.push_back(game);
} else if (curFilesMatched == maxFilesMatched) {
- matched.push_back(g);
+ matched.push_back(game);
} else {
debug(2, " ... skipped");
}
+ gotAnyMatchesWithAllFiles = true;
} else {
debug(5, "Skipping game: %s (%s %s/%s) (%d)", g->gameId, g->extra,
getPlatformDescription(g->platform), getLanguageDescription(g->language), i);
}
}
- // We didn't find a match
- if (matched.empty()) {
- if (!filesProps.empty() && gotAnyMatchesWithAllFiles) {
- reportUnknown(parent, filesProps, matchedGameIds);
- }
-
- // Filename based fallback
- }
-
return matched;
}
-const ADGameDescription *AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback, ADFilePropertiesMap *filesProps) const {
+ADDetectedGame AdvancedMetaEngine::detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const {
const ADFileBasedFallback *ptr;
const char* const* filenames;
int maxNumMatchedFiles = 0;
- const ADGameDescription *matchedDesc = 0;
+ ADDetectedGame result;
for (ptr = fileBasedFallback; ptr->desc; ++ptr) {
const ADGameDescription *agdesc = ptr->desc;
@@ -588,35 +529,36 @@ const ADGameDescription *AdvancedMetaEngine::detectGameFilebased(const FileMap &
debug(4, "Matched: %s", agdesc->gameId);
if (numMatchedFiles > maxNumMatchedFiles) {
- matchedDesc = agdesc;
maxNumMatchedFiles = numMatchedFiles;
debug(4, "and overridden");
- if (filesProps) {
- for (filenames = ptr->filenames; *filenames; ++filenames) {
- ADFileProperties tmp;
+ ADDetectedGame game(agdesc);
+ game.hasUnknownFiles = true;
+
+ for (filenames = ptr->filenames; *filenames; ++filenames) {
+ FileProperties tmp;
- if (getFileProperties(fslist.begin()->getParent(), allFiles, *agdesc, *filenames, tmp))
- (*filesProps)[*filenames] = tmp;
- }
+ if (getFileProperties(fslist.begin()->getParent(), allFiles, *agdesc, *filenames, tmp))
+ game.matchedFiles[*filenames] = tmp;
}
+ result = game;
}
}
}
- return matchedDesc;
+ return result;
}
-GameList AdvancedMetaEngine::getSupportedGames() const {
+PlainGameList AdvancedMetaEngine::getSupportedGames() const {
if (_singleId != NULL) {
- GameList gl;
+ PlainGameList gl;
const PlainGameDescriptor *g = _gameIds;
while (g->gameId) {
if (0 == scumm_stricmp(_singleId, g->gameId)) {
- gl.push_back(GameDescriptor(g->gameId, g->description));
+ gl.push_back(*g);
return gl;
}
@@ -625,17 +567,17 @@ GameList AdvancedMetaEngine::getSupportedGames() const {
error("Engine %s doesn't have its singleid specified in ids list", _singleId);
}
- return GameList(_gameIds);
+ return PlainGameList(_gameIds);
}
-GameDescriptor AdvancedMetaEngine::findGame(const char *gameId) const {
+PlainGameDescriptor AdvancedMetaEngine::findGame(const char *gameId) const {
// First search the list of supported gameids for a match.
const PlainGameDescriptor *g = findPlainGameDescriptor(gameId, _gameIds);
if (g)
- return GameDescriptor(*g);
+ return *g;
// No match found
- return GameDescriptor();
+ return PlainGameDescriptor::empty();
}
AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, const PlainGameDescriptor *gameIds, const ADExtraGuiOptionsMap *extraGuiOptions)
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 5160a99679..326cb79c49 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -41,27 +41,13 @@ class FSList;
* enable detection.
*/
struct ADGameFileDescription {
- const char *fileName; ///< Name of described file.
- uint16 fileType; ///< Optional. Not used during detection, only by engines.
- const char *md5; ///< MD5 of (the beginning of) the described file. Optional. Set to NULL to ignore.
- int32 fileSize; ///< Size of the described file. Set to -1 to ignore.
+ const char *fileName; ///< Name of described file.
+ uint16 fileType; ///< Optional. Not used during detection, only by engines.
+ const char *md5; ///< MD5 of (the beginning of) the described file. Optional. Set to NULL to ignore.
+ int32 fileSize; ///< Size of the described file. Set to -1 to ignore.
};
/**
- * A record describing the properties of a file. Used on the existing
- * files while detecting a game.
- */
-struct ADFileProperties {
- int32 size;
- Common::String md5;
-};
-
-/**
- * A map of all relevant existing files in a game directory while detecting.
- */
-typedef Common::HashMap<Common::String, ADFileProperties, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> ADFilePropertiesMap;
-
-/**
* A shortcut to produce an empty ADGameFileDescription record. Used to mark
* the end of a list of these.
*/
@@ -80,18 +66,18 @@ typedef Common::HashMap<Common::String, ADFileProperties, Common::IgnoreCase_Has
#define AD_ENTRY1s(f, x, s) {{ f, 0, x, s}, AD_LISTEND}
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
- ADGF_ADDENGLISH = (1 << 24), ///< always add English as language option
- ADGF_MACRESFORK = (1 << 25), ///< the md5 for this entry will be calculated from the resource fork
+ 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
+ ADGF_ADDENGLISH = (1 << 24), ///< always add English as language option
+ ADGF_MACRESFORK = (1 << 25), ///< the md5 for this entry will be calculated from the resource fork
ADGF_USEEXTRAASTITLE = (1 << 26), ///< Extra field value will be used as main game title, not gameid
- ADGF_DROPLANGUAGE = (1 << 27), ///< don't add language to gameid
- ADGF_DROPPLATFORM = (1 << 28), ///< don't add platform to gameid
- ADGF_CD = (1 << 29), ///< add "-cd" to gameid
- ADGF_DEMO = (1 << 30) ///< add "-demo" to gameid
+ ADGF_DROPLANGUAGE = (1 << 27), ///< don't add language to gameid
+ ADGF_DROPPLATFORM = (1 << 28), ///< don't add platform to gameid
+ ADGF_CD = (1 << 29), ///< add "-cd" to gameid
+ ADGF_DEMO = (1 << 30) ///< add "-demo" to gameid
};
struct ADGameDescription {
@@ -112,14 +98,19 @@ struct ADGameDescription {
};
/**
- * A list of pointers to ADGameDescription structs (or subclasses thereof).
+ * A game installation matching an AD game description
*/
-typedef Common::Array<const ADGameDescription *> ADGameDescList;
+struct ADDetectedGame {
+ bool hasUnknownFiles;
+ FilePropertiesMap matchedFiles;
+ const ADGameDescription *desc;
-/**
- * A list of raw game ID strings.
- */
-typedef Common::Array<const char *> ADGameIdList;
+ ADDetectedGame() : desc(nullptr), hasUnknownFiles(false) {}
+ explicit ADDetectedGame(const ADGameDescription *d) : desc(d), hasUnknownFiles(false) {}
+};
+
+/** A list of games detected by the AD */
+typedef Common::Array<ADDetectedGame> ADDetectedGames;
/**
* End marker for a table of ADGameDescription structs. Use this to
@@ -274,11 +265,11 @@ public:
* Returns list of targets supported by the engine.
* Distinguishes engines with single ID
*/
- virtual GameList getSupportedGames() const;
+ PlainGameList getSupportedGames() const override;
- virtual GameDescriptor findGame(const char *gameId) const;
+ PlainGameDescriptor findGame(const char *gameId) const override;
- virtual GameList detectGames(const Common::FSList &fslist) const;
+ DetectedGames detectGames(const Common::FSList &fslist) const override;
virtual Common::Error createInstance(OSystem *syst, Engine **engine) const;
@@ -294,8 +285,8 @@ protected:
* An (optional) generic fallback detect function which is invoked
* if the regular MD5 based detection failed to detect anything.
*/
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- return 0;
+ virtual ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ return ADDetectedGame();
}
private:
@@ -313,7 +304,7 @@ protected:
* @param extra restrict results to specified extra string (only if kADFlagUseExtraAsHint is set)
* @return list of ADGameDescription pointers corresponding to matched games
*/
- virtual ADGameDescList detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const;
+ virtual ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const;
/**
* Iterates over all ADFileBasedFallback records inside fileBasedFallback.
@@ -327,16 +318,7 @@ protected:
* @param fileBasedFallback a list of ADFileBasedFallback records, zero-terminated
* @param filesProps if not 0, return a map of properties for all detected files here
*/
- const ADGameDescription *detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback, ADFilePropertiesMap *filesProps = 0) const;
-
- /**
- * Log and print a report that we found an unknown game variant, together with the file
- * names, sizes and MD5 sums.
- */
- void reportUnknown(const Common::FSNode &path, const ADFilePropertiesMap &filesProps, const ADGameIdList &matchedGameIds = ADGameIdList()) const;
-
- // TODO
- void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *realDesc) const;
+ ADDetectedGame detectGameFilebased(const FileMap &allFiles, const Common::FSList &fslist, const ADFileBasedFallback *fileBasedFallback) const;
/**
* Compose a hashmap of all files in fslist.
@@ -345,7 +327,10 @@ protected:
void composeFileHashMap(FileMap &allFiles, const Common::FSList &fslist, int depth, const Common::String &parentName = Common::String()) const;
/** Get the properties (size and MD5) of this file. */
- bool getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, ADFileProperties &fileProps) const;
+ bool getFileProperties(const Common::FSNode &parent, const FileMap &allFiles, const ADGameDescription &game, const Common::String fname, FileProperties &fileProps) const;
+
+ /** Convert an AD game description into the shared game description format */
+ DetectedGame toDetectedGame(const ADDetectedGame &adGame) const;
};
#endif
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index e26f5c84fc..39275c4f70 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -220,7 +220,7 @@ public:
virtual void removeSaveState(const char *target, int slot) const;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
- const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
};
bool AgiMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -375,7 +375,11 @@ SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int sl
char saveVersion = in->readByte();
if (saveVersion >= 4) {
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*in, thumbnail)) {
+ delete in;
+ return SaveStateDescriptor();
+ }
descriptor.setThumbnail(thumbnail);
@@ -417,7 +421,7 @@ SaveStateDescriptor AgiMetaEngine::querySaveMetaInfos(const char *target, int sl
}
}
-const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const {
+ADDetectedGame AgiMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const {
typedef Common::HashMap<Common::String, int32> IntMap;
IntMap allFiles;
bool matchedUsingFilenames = false;
@@ -580,10 +584,10 @@ const ADGameDescription *AgiMetaEngine::fallbackDetect(const FileMap &allFilesXX
g_system->logMessage(LogMessageType::kWarning, fallbackWarning.c_str());
- return (const ADGameDescription *)&g_fallbackDesc;
+ return ADDetectedGame(&g_fallbackDesc.desc);
}
- return 0;
+ return ADDetectedGame();
}
#if PLUGIN_ENABLED_DYNAMIC(AGI)
diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp
index dbc4ee9145..1847434200 100644
--- a/engines/agos/detection.cpp
+++ b/engines/agos/detection.cpp
@@ -99,7 +99,7 @@ public:
_directoryGlobs = directoryGlobs;
}
- virtual GameDescriptor findGame(const char *gameId) const {
+ PlainGameDescriptor findGame(const char *gameId) const override {
return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
}
diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h
index 90e5a84829..b9cdce6b99 100644
--- a/engines/agos/detection_tables.h
+++ b/engines/agos/detection_tables.h
@@ -2401,6 +2401,156 @@ static const AGOSGameDescription gameDescriptions[] = {
GF_TALKIE
},
+ // Simon the Sorcerer 2 - Russian Fan with MT-32 hack (25th Anniversary Edition)
+ {
+ {
+ "simon2",
+ "25th Anniversary Edition",
+
+ {
+ { "gsptr30", GAME_BASEFILE, "e26d162e573587f4601b88701292212c", 58851 },
+ { "icon.dat", GAME_ICONFILE, "72096a62d36e6034ea9fecc13b2dbdab", 18089 },
+ { "simon2.gme", GAME_GMEFILE, "f1727b15b3e389f0248363d890751ee7", 19695662 },
+ { "stripped.txt", GAME_STRFILE, "e229f84d46fa83f99b4a7115679f3fb6", 171 },
+ { "tbllist", GAME_TBLFILE, "2082f8d02075e590300478853a91ffd9", 513 },
+ { NULL, 0, NULL, 0}
+ },
+ Common::RU_RUS,
+ Common::kPlatformDOS,
+ ADGF_CD,
+ GUIO0()
+ },
+
+ GType_SIMON2,
+ GID_SIMON2,
+ GF_TALKIE
+ },
+
+ // Simon the Sorcerer 2 - Polish with MT-32 hack (25th Anniversary Edition)
+ {
+ {
+ "simon2",
+ "25th Anniversary Edition",
+
+ {
+ { "gsptr30", GAME_BASEFILE, "657fd873f5d0637097ee02315b447e6f", -1},
+ { "icon.dat", GAME_ICONFILE, "72096a62d36e6034ea9fecc13b2dbdab", -1},
+ { "simon2.gme", GAME_GMEFILE, "212fa5638a76869537d092d4e76524c0", 20037221},
+ { "stripped.txt", GAME_STRFILE, "e229f84d46fa83f99b4a7115679f3fb6", -1},
+ { "tbllist", GAME_TBLFILE, "2082f8d02075e590300478853a91ffd9", -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::PL_POL,
+ Common::kPlatformDOS,
+ ADGF_CD,
+ GUIO0()
+ },
+
+ GType_SIMON2,
+ GID_SIMON2,
+ GF_TALKIE | GF_WAVSFX
+ },
+
+ // Simon the Sorcerer 2 - Hebrew with MT-32 hack (25th Anniversary Edition)
+ {
+ {
+ "simon2",
+ "25th Anniversary Edition",
+
+ {
+ { "gsptr30", GAME_BASEFILE, "952a2b1be23c3c609ba8d988a9a1627d", 53366},
+ { "icon.dat", GAME_ICONFILE, "72096a62d36e6034ea9fecc13b2dbdab", 18089},
+ { "simon2.gme", GAME_GMEFILE, "40ac2d4763d97a9268023dc6db17e2ce", 20017302},
+ { "stripped.txt", GAME_STRFILE, "de9dbc24158660e153483fa0cf6c3172", 171},
+ { "tbllist", GAME_TBLFILE, "2082f8d02075e590300478853a91ffd9", 513},
+ { NULL, 0, NULL, 0}
+ },
+ Common::HE_ISR,
+ Common::kPlatformDOS,
+ ADGF_CD,
+ GUIO0()
+ },
+
+ GType_SIMON2,
+ GID_SIMON2,
+ GF_TALKIE | GF_WAVSFX
+ },
+
+ // Simon the Sorcerer 2 - Italian with MT-32 hack (25th Anniversary Edition)
+ {
+ {
+ "simon2",
+ "25th Anniversary Edition",
+
+ {
+ { "gsptr30", GAME_BASEFILE, "3e11d400bea0638f360a724687005cd1", -1},
+ { "icon.dat", GAME_ICONFILE, "72096a62d36e6034ea9fecc13b2dbdab", -1},
+ { "simon2.gme", GAME_GMEFILE, "510d012bcc5775a8513923163ffe4458", 20066490},
+ { "stripped.txt", GAME_STRFILE, "bea6843fb9f3b2144fcb146d62db0b9a", -1},
+ { "tbllist", GAME_TBLFILE, "2082f8d02075e590300478853a91ffd9", -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ ADGF_CD,
+ GUIO0()
+ },
+
+ GType_SIMON2,
+ GID_SIMON2,
+ GF_TALKIE | GF_WAVSFX
+ },
+
+ // Simon the Sorcerer 2 - Czech with MT-32 hack (25th Anniversary Edition)
+ {
+ {
+ "simon2",
+ "25th Anniversary Edition",
+
+ {
+ { "gsptr30", GAME_BASEFILE, "eb8217f9ec4628d12ca606033146c48c", -1},
+ { "icon.dat", GAME_ICONFILE, "72096a62d36e6034ea9fecc13b2dbdab", -1},
+ { "simon2.gme", GAME_GMEFILE, "50188f9fde0d063c824476972936a52f", 20054555},
+ { "stripped.txt", GAME_STRFILE, "e229f84d46fa83f99b4a7115679f3fb6", -1},
+ { "tbllist", GAME_TBLFILE, "2082f8d02075e590300478853a91ffd9", -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::CZ_CZE,
+ Common::kPlatformDOS,
+ ADGF_CD,
+ GUIO0()
+ },
+
+ GType_SIMON2,
+ GID_SIMON2,
+ GF_TALKIE | GF_WAVSFX
+ },
+
+ // Simon the Sorcerer 2 - Spanish with MT-32 hack (25th Anniversary Edition)
+ {
+ {
+ "simon2",
+ "25th Anniversary Edition",
+
+ {
+ { "gsptr30", GAME_BASEFILE, "268dc322aa73bcf27bb016b8e8ceb889", -1},
+ { "icon.dat", GAME_ICONFILE, "72096a62d36e6034ea9fecc13b2dbdab", -1},
+ { "simon2.gme", GAME_GMEFILE, "2b997db3c677fb3d2174c73ba2cc53e1", 20049608},
+ { "stripped.txt", GAME_STRFILE, "d13753796bd81bf313a2449f34d8b112", -1},
+ { "tbllist", GAME_TBLFILE, "2082f8d02075e590300478853a91ffd9", -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::ES_ESP,
+ Common::kPlatformDOS,
+ ADGF_CD,
+ GUIO0()
+ },
+
+ GType_SIMON2,
+ GID_SIMON2,
+ GF_TALKIE | GF_WAVSFX
+ },
+
#ifdef ENABLE_AGOS2
// The Feeble Files - English DOS Demo
{
diff --git a/engines/agos/intern.h b/engines/agos/intern.h
index 3f5c8c519b..afc0cad08e 100644
--- a/engines/agos/intern.h
+++ b/engines/agos/intern.h
@@ -256,7 +256,8 @@ enum GameFeatures {
GF_PLANAR = 1 << 7,
GF_DEMO = 1 << 8,
GF_PACKED = 1 << 9,
- GF_BROKEN_FF_RATING = 1 << 10
+ GF_BROKEN_FF_RATING = 1 << 10,
+ GF_WAVSFX = 1 << 11
};
enum GameFileTypes {
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index 3a7158a203..5e28654c41 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -482,20 +482,14 @@ void MidiPlayer::pause(bool b) {
}
void MidiPlayer::setVolume(int musicVol, int sfxVol) {
- if (musicVol < 0)
- musicVol = 0;
- else if (musicVol > 255)
- musicVol = 255;
- if (sfxVol < 0)
- sfxVol = 0;
- else if (sfxVol > 255)
- sfxVol = 255;
+ musicVol = CLIP(musicVol, 0, 255);
+ sfxVol = CLIP(sfxVol, 0, 255);
if (_musicVolume == musicVol && _sfxVolume == sfxVol)
return;
_musicVolume = musicVol;
- _sfxVolume = sfxVol;
+ _sfxVolume = sfxVol;
// Now tell all the channels this.
Common::StackLock lock(_mutex);
diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp
index 13b5bf761c..ae2412feb4 100644
--- a/engines/agos/sound.cpp
+++ b/engines/agos/sound.cpp
@@ -519,7 +519,7 @@ void Sound::loadSfxTable(const char *gameFilename, uint32 base) {
delete _effects;
const bool dataIsUnsigned = true;
- if (_vm->getPlatform() == Common::kPlatformWindows)
+ if (_vm->getPlatform() == Common::kPlatformWindows || (_vm->getFeatures() & GF_WAVSFX))
_effects = new WavSound(_mixer, gameFilename, base);
else
_effects = new VocSound(_mixer, gameFilename, dataIsUnsigned, base, false);
diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp
index 533b04fa30..d2f7ac6bd5 100644
--- a/engines/agos/string.cpp
+++ b/engines/agos/string.cpp
@@ -486,7 +486,7 @@ void AGOSEngine::printScreenText(uint vgaSpriteId, uint color, const char *strin
if (_variableArray[141] == 0)
_variableArray[141] = 9;
_variableArray[85] = _variableArray[141] * talkDelay;
-
+
if (_language == Common::HE_ISR)
_variableArray[85] += talkDelay * 2;
} else {
diff --git a/engines/avalanche/avalanche.cpp b/engines/avalanche/avalanche.cpp
index 8726ef784a..303fb0cff8 100644
--- a/engines/avalanche/avalanche.cpp
+++ b/engines/avalanche/avalanche.cpp
@@ -39,9 +39,6 @@ AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription *
_console = new AvalancheConsole(this);
_rnd = new Common::RandomSource("avalanche");
- TimeDate time;
- _system->getTimeAndDate(time);
- _rnd->setSeed(time.tm_sec + time.tm_min + time.tm_hour);
_showDebugLines = false;
_clock = nullptr;
@@ -60,7 +57,6 @@ AvalancheEngine::AvalancheEngine(OSystem *syst, const AvalancheGameDescription *
_help = nullptr;
_highscore = nullptr;
- _platform = gd->desc.platform;
initVariables();
}
@@ -182,10 +178,6 @@ GUI::Debugger *AvalancheEngine::getDebugger() {
return _console;
}
-Common::Platform AvalancheEngine::getPlatform() const {
- return _platform;
-}
-
bool AvalancheEngine::hasFeature(EngineFeature f) const {
return (f == kSupportsSavingDuringRuntime) || (f == kSupportsLoadingDuringRuntime);
}
diff --git a/engines/avalanche/avalanche.h b/engines/avalanche/avalanche.h
index 6eb5e675cc..d50373b07a 100644
--- a/engines/avalanche/avalanche.h
+++ b/engines/avalanche/avalanche.h
@@ -48,10 +48,10 @@
#include "avalanche/mainmenu.h"
#include "avalanche/highscore.h"
+#include "common/error.h"
#include "common/serializer.h"
#include "engines/engine.h"
-#include "engines/advancedDetector.h"
#include "graphics/cursorman.h"
@@ -61,9 +61,7 @@ class RandomSource;
namespace Avalanche {
-struct AvalancheGameDescription {
- ADGameDescription desc;
-};
+struct AvalancheGameDescription;
static const int kSavegameVersion = 2;
@@ -132,7 +130,6 @@ protected:
private:
AvalancheConsole *_console;
- Common::Platform _platform;
public:
// For Thinkabout:
diff --git a/engines/avalanche/detection.cpp b/engines/avalanche/detection.cpp
index def395b77f..7f3d4f88a8 100644
--- a/engines/avalanche/detection.cpp
+++ b/engines/avalanche/detection.cpp
@@ -35,6 +35,10 @@
namespace Avalanche {
+struct AvalancheGameDescription {
+ ADGameDescription desc;
+};
+
uint32 AvalancheEngine::getFeatures() const {
return _gameDescription->desc.flags;
}
@@ -43,6 +47,10 @@ const char *AvalancheEngine::getGameId() const {
return _gameDescription->desc.gameId;
}
+Common::Platform AvalancheEngine::getPlatform() const {
+ return _gameDescription->desc.platform;
+}
+
static const PlainGameDescriptor avalancheGames[] = {
{"avalanche", "Lord Avalot d'Argent"},
{0, 0}
@@ -193,7 +201,12 @@ SaveStateDescriptor AvalancheMetaEngine::querySaveMetaInfos(const char *target,
SaveStateDescriptor desc(slot, description);
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*f);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*f, thumbnail)) {
+ warning("Cannot read thumbnail data, possibly broken savegame");
+ delete f;
+ return SaveStateDescriptor();
+ }
desc.setThumbnail(thumbnail);
delete f;
diff --git a/engines/avalanche/dropdown.cpp b/engines/avalanche/dropdown.cpp
index 97adfc2581..ba4e452aaa 100644
--- a/engines/avalanche/dropdown.cpp
+++ b/engines/avalanche/dropdown.cpp
@@ -684,9 +684,9 @@ void DropDownMenu::update() {
Common::Point cursorPos = _vm->getMousePos();
while (!_activeMenuItem._activeNow && (cursorPos.y <= 21) && _vm->_holdLeftMouse) {
_menuBar.chooseMenuItem(cursorPos.x);
- do
+ do {
_vm->updateEvents();
- while (_vm->_holdLeftMouse && !_vm->shouldQuit());
+ } while (_vm->_holdLeftMouse && !_vm->shouldQuit());
while (!_vm->shouldQuit()) {
do {
diff --git a/engines/bbvs/bbvs.h b/engines/bbvs/bbvs.h
index 9fb6b9cac3..a9d37c2551 100644
--- a/engines/bbvs/bbvs.h
+++ b/engines/bbvs/bbvs.h
@@ -417,7 +417,7 @@ public:
const char *getSavegameFilename(int num);
bool existsSavegame(int num);
static Common::String getSavegameFilename(const Common::String &target, int num);
- static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header);
+ WARN_UNUSED_RESULT static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail = true);
void allocSnapshot();
void freeSnapshot();
diff --git a/engines/bbvs/detection.cpp b/engines/bbvs/detection.cpp
index 1b2c644dda..b30c6d3f2d 100644
--- a/engines/bbvs/detection.cpp
+++ b/engines/bbvs/detection.cpp
@@ -124,7 +124,7 @@ SaveStateList BbvsMetaEngine::listSaves(const char *target) const {
if (slotNum >= 0 && slotNum <= 999) {
Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
if (in) {
- if (Bbvs::BbvsEngine::readSaveHeader(in, false, header) == Bbvs::BbvsEngine::kRSHENoError) {
+ if (Bbvs::BbvsEngine::readSaveHeader(in, header) == Bbvs::BbvsEngine::kRSHENoError) {
saveList.push_back(SaveStateDescriptor(slotNum, header.description));
}
delete in;
@@ -142,7 +142,7 @@ SaveStateDescriptor BbvsMetaEngine::querySaveMetaInfos(const char *target, int s
if (in) {
Bbvs::BbvsEngine::SaveHeader header;
Bbvs::BbvsEngine::kReadSaveHeaderError error;
- error = Bbvs::BbvsEngine::readSaveHeader(in, true, header);
+ error = Bbvs::BbvsEngine::readSaveHeader(in, header, false);
delete in;
if (error == Bbvs::BbvsEngine::kRSHENoError) {
SaveStateDescriptor desc(slot, header.description);
diff --git a/engines/bbvs/saveload.cpp b/engines/bbvs/saveload.cpp
index 74c255c860..d4782aad39 100644
--- a/engines/bbvs/saveload.cpp
+++ b/engines/bbvs/saveload.cpp
@@ -27,7 +27,7 @@
namespace Bbvs {
-BbvsEngine::kReadSaveHeaderError BbvsEngine::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) {
+WARN_UNUSED_RESULT BbvsEngine::kReadSaveHeaderError BbvsEngine::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail) {
header.version = in->readUint32LE();
if (header.version > BBVS_SAVEGAME_VERSION)
@@ -38,10 +38,8 @@ BbvsEngine::kReadSaveHeaderError BbvsEngine::readSaveHeader(Common::SeekableRead
while (descriptionLen--)
header.description += (char)in->readByte();
- if (loadThumbnail) {
- header.thumbnail = Graphics::loadThumbnail(*in);
- } else {
- Graphics::skipThumbnail(*in);
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
+ return kRSHEIoError;
}
// Not used yet, reserved for future usage
@@ -101,7 +99,7 @@ void BbvsEngine::loadgame(const char *filename) {
SaveHeader header;
- kReadSaveHeaderError errorCode = readSaveHeader(in, false, header);
+ kReadSaveHeaderError errorCode = readSaveHeader(in, header);
if (errorCode != kRSHENoError) {
warning("Error loading savegame '%s'", filename);
diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index d4c4eeaee3..f9446aae0a 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -22,16 +22,17 @@
#include "bladerunner/actor.h"
-#include "bladerunner/bladerunner.h"
#include "bladerunner/actor_clues.h"
#include "bladerunner/actor_combat.h"
#include "bladerunner/actor_walk.h"
#include "bladerunner/audio_speech.h"
+#include "bladerunner/bladerunner.h"
#include "bladerunner/boundingbox.h"
#include "bladerunner/game_info.h"
#include "bladerunner/items.h"
#include "bladerunner/mouse.h"
#include "bladerunner/movement_track.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/scene.h"
#include "bladerunner/scene_objects.h"
#include "bladerunner/script/scene_script.h"
@@ -51,7 +52,6 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) {
_walkInfo = new ActorWalk(vm);
_movementTrack = new MovementTrack();
_clues = new ActorClues(vm, (actorId && actorId != 99) ? 2 : 4);
- _bbox = new BoundingBox();
_combatInfo = new ActorCombat(vm);
_friendlinessToOther.resize(_vm->_gameInfo->getActorCount());
@@ -64,7 +64,6 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) {
Actor::~Actor() {
delete _combatInfo;
- delete _bbox;
delete _clues;
delete _movementTrack;
delete _walkInfo;
@@ -97,6 +96,8 @@ void Actor::setup(int actorId) {
_retiredHeight = 0;
_scale = 1.0f;
+ _timer4RemainDefault = 60000;
+
_movementTrackWalkingToWaypointId = -1;
_movementTrackDelayOnNextWaypoint = -1;
@@ -120,9 +121,6 @@ void Actor::setup(int actorId) {
_movementTrackNextAngle = -1;
_movementTrackNextRunning = false;
- // Timer for exchanging clues
- _timersLeft[4] = 60000;
-
_animationMode = -1;
_screenRectangle = Common::Rect(-1, -1, -1, -1);
@@ -226,6 +224,8 @@ void Actor::timerUpdate(int timerId) {
break;
case 4:
// Exchange clues between actors
+ acquireCluesByRelations();
+ _timersLeft[4] = _timer4RemainDefault;
break;
case 5:
// Actor animation frame timer
@@ -354,7 +354,7 @@ void Actor::setAtXYZ(const Vector3 &position, int facing, bool snapFacing, bool
_vm->_sceneObjects->remove(_id + kSceneObjectOffsetActors);
if (_vm->_scene->getSetId() == _setId) {
- _vm->_sceneObjects->addActor(_id + kSceneObjectOffsetActors, _bbox, &_screenRectangle, true, moving, _isTarget, retired);
+ _vm->_sceneObjects->addActor(_id + kSceneObjectOffsetActors, _bbox, _screenRectangle, true, moving, _isTarget, retired);
}
}
@@ -468,7 +468,7 @@ bool Actor::loopWalkToItem(int itemId, int destinationOffset, int interruptible,
return loopWalk(itemPosition, destinationOffset, interruptible, runFlag, _position, width, 24.0f, a5, isRunningFlag, false);
}
-bool Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag) {
+bool Actor::loopWalkToSceneObject(const Common::String &objectName, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag) {
int sceneObject = _vm->_scene->_set->findObject(objectName);
if (sceneObject < 0) {
return true;
@@ -671,6 +671,12 @@ bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
return isVisible;
}
+void Actor::tickCombat() {
+ if (_id != kActorMcCoy && !_isRetired && _inCombat) {
+ _combatInfo->tick();
+ }
+}
+
bool Actor::draw(Common::Rect *screenRect) {
Vector3 drawPosition(_position.x, -_position.z, _position.y + 2.0);
float drawAngle = M_PI - _facing * (M_PI / 512.0f);
@@ -753,21 +759,21 @@ void Actor::setFacing(int facing, bool halfOrSet) {
void Actor::setBoundingBox(const Vector3 &position, bool retired) {
if (retired) {
- _bbox->setXYZ(position.x - (_retiredWidth / 2.0f),
- position.y,
- position.z - (_retiredWidth / 2.0f),
+ _bbox.setXYZ(position.x - (_retiredWidth / 2.0f),
+ position.y,
+ position.z - (_retiredWidth / 2.0f),
- position.x + (_retiredWidth / 2.0f),
- position.y + _retiredHeight,
- position.z + (_retiredWidth / 2.0f));
+ position.x + (_retiredWidth / 2.0f),
+ position.y + _retiredHeight,
+ position.z + (_retiredWidth / 2.0f));
} else {
- _bbox->setXYZ(position.x - 12.0f,
- position.y + 6.0f,
- position.z - 12.0f,
+ _bbox.setXYZ(position.x - 12.0f,
+ position.y + 6.0f,
+ position.z - 12.0f,
- position.x + 12.0f,
- position.y + 72.0f,
- position.z + 12.0f);
+ position.x + 12.0f,
+ position.y + 72.0f,
+ position.z + 12.0f);
}
}
@@ -813,7 +819,7 @@ void Actor::faceActor(int otherActorId, bool animate) {
faceXYZ(otherActor->_position, animate);
}
-void Actor::faceObject(const char *objectName, bool animate) {
+void Actor::faceObject(const Common::String &objectName, bool animate) {
int objectId = _vm->_scene->findObject(objectName);
if (objectId == -1) {
return;
@@ -880,6 +886,21 @@ void Actor::setFriendlinessToOther(int otherActorId, int friendliness) {
_friendlinessToOther[otherActorId] = friendliness;
}
+bool Actor::checkFriendlinessAndHonesty(int otherActorId) {
+ int honestyDiff = 2 * _friendlinessToOther[otherActorId] - _honesty;
+ int friendlinessRange;
+
+ if (honestyDiff > 30) {
+ friendlinessRange = 100;
+ } else if (honestyDiff >= 0 && honestyDiff <= 30) {
+ friendlinessRange = 50;
+ } else {
+ friendlinessRange = 0;
+ }
+
+ return _vm->_rnd.getRandomNumberRng(1, 100) <= friendlinessRange;
+}
+
void Actor::setHonesty(int honesty) {
_honesty = honesty;
}
@@ -904,16 +925,6 @@ void Actor::setImmunityToObstacles(bool isImmune) {
_isImmuneToObstacles = isImmune;
}
-void Actor::modifyCurrentHP(signed int change) {
- _currentHP = CLIP(_currentHP + change, 0, 100);
- if (_currentHP > 0)
- retire(false, 0, 0, -1);
-}
-
-void Actor::modifyMaxHP(signed int change) {
- _maxHP = CLIP(_maxHP + change, 0, 100);
-}
-
void Actor::modifyCombatAggressiveness(signed int change) {
_combatAggressiveness = CLIP(_combatAggressiveness + change, 0, 100);
}
@@ -955,6 +966,13 @@ void Actor::setTarget(bool target) {
_isTarget = target;
}
+void Actor::setCurrentHP(int hp) {
+ _currentHP = hp;
+ if (hp > 0) {
+ retire(false, 0, 0, -1);
+ }
+}
+
void Actor::setHealth(int hp, int maxHp) {
_currentHP = hp;
_maxHP = maxHp;
@@ -963,18 +981,29 @@ void Actor::setHealth(int hp, int maxHp) {
}
}
-void Actor::combatModeOn(int a2, int a3, int otherActorId, int a5, int animationModeCombatIdle, int animationModeCombatWalk, int animationModeCombatRun, int a9, int a10, int a11, int ammoDamage, int a13, int a14) {
+void Actor::modifyCurrentHP(signed int change) {
+ _currentHP = CLIP(_currentHP + change, 0, 100);
+ if (_currentHP > 0) {
+ retire(false, 0, 0, -1);
+ }
+}
+
+void Actor::modifyMaxHP(signed int change) {
+ _maxHP = CLIP(_maxHP + change, 0, 100);
+}
+
+
+void Actor::combatModeOn(int initialState, bool rangedAttack, int enemyId, int waypointType, int animationModeCombatIdle, int animationModeCombatWalk, int animationModeCombatRun, int fleeRatio, int coverRatio, int actionRatio, int damage, int range, bool unstoppable) {
_animationModeCombatIdle = animationModeCombatIdle;
_animationModeCombatWalk = animationModeCombatWalk;
_animationModeCombatRun = animationModeCombatRun;
_inCombat = true;
if (_id != kActorMcCoy) {
- _combatInfo->combatOn(_id, a2, a3, otherActorId, a5, a9, a10, a11, ammoDamage, a13, a14);
+ _combatInfo->combatOn(_id, initialState, rangedAttack, enemyId, waypointType, fleeRatio, coverRatio, actionRatio, damage, range, unstoppable);
}
stopWalking(false);
changeAnimationMode(_animationModeCombatIdle, false);
- int i;
- for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
+ for (int i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
Actor *otherActor = _vm->_actors[i];
if (i != _id && otherActor->_setId == _setId && !otherActor->_isRetired) {
_vm->_aiScripts->otherAgentEnteredCombatMode(i, _id, true);
@@ -989,8 +1018,7 @@ void Actor::combatModeOff() {
_inCombat = false;
stopWalking(false);
changeAnimationMode(kAnimationModeIdle, false);
- int i;
- for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
+ for (int i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
Actor *otherActor = _vm->_actors[i];
if (i != _id && otherActor->_setId == _setId && !otherActor->_isRetired) {
_vm->_aiScripts->otherAgentEnteredCombatMode(i, _id, false);
@@ -1002,6 +1030,16 @@ float Actor::distanceFromActor(int otherActorId) {
return (_position - _vm->_actors[otherActorId]->_position).length();
}
+int Actor::angleTo(const Vector3 &target) const {
+ int angle = angle_1024(_position.x, _position.z, target.x, target.z) - _facing;
+ if (angle < -512) {
+ angle += 1024;
+ } else if (angle > 512) {
+ angle -= 1024;
+ }
+ return angle;
+}
+
float Actor::getX() const {
return _position.x;
}
@@ -1014,10 +1052,8 @@ float Actor::getZ() const {
return _position.z;
}
-void Actor::getXYZ(float *x, float *y, float *z) const {
- *x = _position.x;
- *y = _position.y;
- *z = _position.z;
+Vector3 Actor::getXYZ() const {
+ return _position;
}
int Actor::getFacing() const {
@@ -1044,13 +1080,10 @@ int Actor::getGoal() const {
}
void Actor::speechPlay(int sentenceId, bool voiceOver) {
- char name[13];
- sprintf(name, "%02d-%04d%s.AUD", _id, sentenceId, _vm->_languageCode);
- int balance;
+ Common::String name = Common::String::format( "%02d-%04d%s.AUD", _id, sentenceId, _vm->_languageCode.c_str());
- if (voiceOver || _id == BladeRunnerEngine::kActorVoiceOver) {
- balance = 0;
- } else {
+ int balance = 0;
+ if (!voiceOver && _id != BladeRunnerEngine::kActorVoiceOver) {
// Vector3 pos = _vm->_view->_frameViewMatrix * _position;
int screenX = 320; //, screenY = 0;
//TODO: transform to screen space using fov;
@@ -1102,6 +1135,18 @@ void Actor::copyClues(int actorId) {
}
}
+void Actor::acquireCluesByRelations() {
+ if (_setId >= 0 && _setId != kSetFreeSlotG && _setId != _vm->_actors[0]->_setId) {
+ for (int i = 0; i < _vm->_gameInfo->getActorCount(); i++) {
+ if (i != _id && _vm->_actors[i]->_setId == _setId && i && _id
+ && checkFriendlinessAndHonesty(i)
+ && _vm->_actors[i]->checkFriendlinessAndHonesty(_id)) {
+ _clues->acquireCluesByRelations(_id, i);
+ }
+ }
+ }
+}
+
int Actor::soundVolume() const {
float dist = distanceFromView(_vm->_view);
return 35.0f * CLIP(1.0f - (dist / 1200.0f), 0.0f, 1.0f);
@@ -1112,8 +1157,8 @@ int Actor::soundBalance() const {
return 35.0f * (CLIP(screenPosition.x / 640.0f, 0.0f, 1.0f) * 2.0f - 1.0f);
}
-bool Actor::isObstacleBetween(float targetX, float targetZ) {
- return _vm->_sceneObjects->isObstacleBetween(_position.x, _position.z, targetX, targetZ, _position.y, -1);
+bool Actor::isObstacleBetween(const Vector3 &target) {
+ return _vm->_sceneObjects->isObstacleBetween(_position, target, -1);
}
int Actor::findTargetUnderMouse(BladeRunnerEngine *vm, int mouseX, int mouseY) {
@@ -1204,4 +1249,157 @@ bool Actor::walkToNearestPoint(const Vector3 &destination, float distance) {
return false;
}
+void Actor::save(SaveFileWriteStream &f) {
+ f.writeInt(_id);
+ f.writeInt(_setId);
+ f.writeVector3(_position);
+ f.writeInt(_facing);
+ f.writeInt(_targetFacing);
+ f.writeInt(_timer4RemainDefault);
+
+ f.writeInt(_honesty);
+ f.writeInt(_intelligence);
+ f.writeInt(_stability);
+ f.writeInt(_combatAggressiveness);
+ f.writeInt(_goalNumber);
+
+ f.writeInt(_currentHP);
+ f.writeInt(_maxHP);
+
+ f.writeBool(_movementTrackPaused);
+ f.writeInt(_movementTrackNextWaypointId);
+ f.writeInt(_movementTrackNextDelay);
+ f.writeInt(_movementTrackNextAngle);
+ f.writeBool(_movementTrackNextRunning);
+
+ f.writeInt(0); // TODO: _clueType
+ f.writeBool(_isMoving);
+ f.writeBool(_isTarget);
+ f.writeBool(_inCombat);
+ f.writeBool(_isInvisible);
+ f.writeBool(_isRetired);
+ f.writeBool(_isImmuneToObstacles);
+
+ f.writeInt(_animationMode);
+ f.writeInt(_fps);
+ f.writeInt(_frameMs);
+ f.writeInt(_animationId);
+ f.writeInt(_animationFrame);
+
+ f.writeInt(_movementTrackWalkingToWaypointId);
+ f.writeInt(_movementTrackDelayOnNextWaypoint);
+
+ f.writeRect(_screenRectangle);
+ f.writeInt(_retiredWidth);
+ f.writeInt(_retiredHeight);
+ f.writeInt(_damageAnimIfMoving);
+ f.writeInt(0); // TODO: _actorFieldU6
+ f.writeInt(0); // TODO: _actorFieldU7
+ f.writeFloat(_scale);
+
+ for (int i = 0; i < 7; ++i) {
+ f.writeInt(_timersLeft[i]);
+ }
+
+ uint32 now = _vm->getTotalPlayTime(); // TODO: should be last lock time
+ for (int i = 0; i < 7; ++i) {
+ f.writeInt(_timersLast[i] - now);
+ }
+
+ int actorCount = _vm->_gameInfo->getActorCount();
+ for (int i = 0; i != actorCount; ++i) {
+ f.writeInt(_friendlinessToOther[i]);
+ }
+
+ _clues->save(f);
+
+ _movementTrack->save(f);
+
+ _walkInfo->save(f);
+
+ f.writeBoundingBox(_bbox);
+
+ _combatInfo->save(f);
+ f.writeInt(_animationModeCombatIdle);
+ f.writeInt(_animationModeCombatWalk);
+ f.writeInt(_animationModeCombatRun);
+}
+
+void Actor::load(SaveFileReadStream &f) {
+ _id = f.readInt();
+ _setId = f.readInt();
+ _position = f.readVector3();
+ _facing = f.readInt();
+ _targetFacing = f.readInt();
+ _timer4RemainDefault = f.readInt();
+
+ _honesty = f.readInt();
+ _intelligence = f.readInt();
+ _stability = f.readInt();
+ _combatAggressiveness = f.readInt();
+ _goalNumber = f.readInt();
+
+ _currentHP = f.readInt();
+ _maxHP = f.readInt();
+
+ _movementTrackPaused = f.readBool();
+ _movementTrackNextWaypointId = f.readInt();
+ _movementTrackNextDelay = f.readInt();
+ _movementTrackNextAngle = f.readInt();
+ _movementTrackNextRunning = f.readBool();
+
+ f.skip(4); // TODO: _clueType
+ _isMoving = f.readBool();
+ _isTarget = f.readBool();
+ _inCombat = f.readBool();
+ _isInvisible = f.readBool();
+ _isRetired = f.readBool();
+ _isImmuneToObstacles = f.readBool();
+
+ _animationMode = f.readInt();
+ _fps = f.readInt();
+ _frameMs = f.readInt();
+ _animationId = f.readInt();
+ _animationFrame = f.readInt();
+
+ _movementTrackWalkingToWaypointId = f.readInt();
+ _movementTrackDelayOnNextWaypoint = f.readInt();
+
+ _screenRectangle = f.readRect();
+ _retiredWidth = f.readInt();
+ _retiredHeight = f.readInt();
+ _damageAnimIfMoving = f.readInt();
+ f.skip(4); // TODO: _actorFieldU6
+ f.skip(4); // TODO: _actorFieldU7
+ _scale = f.readFloat();
+
+ for (int i = 0; i < 7; ++i) {
+ _timersLeft[i] = f.readInt();
+ }
+
+ uint32 now = _vm->getTotalPlayTime(); // TODO: should be last lock time
+ for (int i = 0; i < 7; ++i) {
+ _timersLast[i] = f.readInt() + now;
+ }
+
+ int actorCount = _vm->_gameInfo->getActorCount();
+ for (int i = 0; i != actorCount; ++i) {
+ _friendlinessToOther[i] = f.readInt();
+ }
+
+ _clues->load(f);
+
+ _movementTrack->load(f);
+
+ _walkInfo->load(f);
+
+ _bbox = f.readBoundingBox();
+
+ _combatInfo->load(f);
+
+ _animationModeCombatIdle = f.readInt();
+ _animationModeCombatWalk = f.readInt();
+ _animationModeCombatRun = f.readInt();
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index af0c14e367..6540c0593a 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -23,6 +23,7 @@
#ifndef BLADERUNNER_ACTOR_H
#define BLADERUNNER_ACTOR_H
+#include "bladerunner/boundingbox.h"
#include "bladerunner/vector.h"
#include "common/array.h"
@@ -36,21 +37,22 @@ class ActorWalk;
class BladeRunnerEngine;
class BoundingBox;
class MovementTrack;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class View;
class Actor {
- friend class ScriptBase;
- friend class KIA;
-
BladeRunnerEngine *_vm;
-private:
- BoundingBox *_bbox;
+public:
+ BoundingBox _bbox;
Common::Rect _screenRectangle;
MovementTrack *_movementTrack;
ActorWalk *_walkInfo;
ActorCombat *_combatInfo;
+ ActorClues *_clues;
+private:
int _honesty;
int _intelligence;
int _stability;
@@ -61,8 +63,6 @@ private:
int _currentHP;
int _maxHP;
- ActorClues *_clues;
-
int _id;
int _setId;
Vector3 _position;
@@ -70,6 +70,8 @@ private:
int _targetFacing;
int _walkboxId;
+ int _timer4RemainDefault;
+
// Flags
bool _isTarget;
bool _isInvisible;
@@ -124,7 +126,7 @@ public:
float getX() const;
float getY() const;
float getZ() const;
- void getXYZ(float *x, float *y, float *z) const;
+ Vector3 getXYZ() const;
int getFacing() const;
int getAnimationMode() const;
@@ -149,7 +151,7 @@ public:
bool walkTo(bool runFlag, const Vector3 &destination, bool a3);
bool loopWalkToActor(int otherActorId, int destinationOffset, int interruptible, bool runFlag, bool a5, bool *isRunningFlag);
bool loopWalkToItem(int itemId, int destinationOffset, int interruptible, bool runFlag, bool a5, bool *isRunningFlag);
- bool loopWalkToSceneObject(const char *objectName, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag);
+ bool loopWalkToSceneObject(const Common::String &objectName, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag);
bool loopWalkToWaypoint(int waypointId, int destinationOffset, int interruptible, bool runFlag, bool a5, bool *isRunningFlag);
bool loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag);
bool asyncWalkToWaypoint(int waypointId, int destinationOffset, bool runFlag, bool a5);
@@ -157,60 +159,83 @@ public:
void run();
bool tick(bool forceUpdate, Common::Rect *screenRect);
+ void tickCombat();
bool draw(Common::Rect *screenRect);
int getSetId() const;
void setSetId(int setId);
- BoundingBox *getBoundingBox() const { return _bbox; }
- Common::Rect *getScreenRectangle() { return &_screenRectangle; }
+ const BoundingBox &getBoundingBox() const { return _bbox; }
+ const Common::Rect &getScreenRectangle() { return _screenRectangle; }
int getWalkbox() const { return _walkboxId; }
+
bool isRetired() const { return _isRetired; }
bool isTarget() const { return _isTarget; }
void setTarget(bool targetable);
bool isImmuneToObstacles() const { return _isImmuneToObstacles; }
bool inCombat() const { return _inCombat; }
+
bool isMoving() const { return _isMoving; }
void setMoving(bool value) { _isMoving = value; }
+
bool inWalkLoop() const { return _inWalkLoop; }
bool isWalking() const;
bool isRunning() const;
void stopWalking(bool value);
void faceActor(int otherActorId, bool animate);
- void faceObject(const char *objectName, bool animate);
+ void faceObject(const Common::String &objectName, bool animate);
void faceItem(int itemId, bool animate);
void faceWaypoint(int waypointId, bool animate);
void faceXYZ(float x, float y, float z, bool animate);
void faceXYZ(const Vector3 &pos, bool animate);
void faceCurrentCamera(bool animate);
void faceHeading(int heading, bool animate);
- void modifyFriendlinessToOther(int otherActorId, signed int change);
+ void setFacing(int facing, bool halfOrSet = true);
+
+ int getCurrentHP() const { return _currentHP; }
+ int getMaxHP() const { return _maxHP; }
+ void setCurrentHP(int hp);
+ void setHealth(int hp, int maxHp);
+ void modifyCurrentHP(signed int change);
+ void modifyMaxHP(signed int change);
+
+ int getFriendlinessToOther(int otherActorId) const { return _friendlinessToOther[otherActorId]; }
void setFriendlinessToOther(int otherActorId, int friendliness);
+ void modifyFriendlinessToOther(int otherActorId, signed int change);
+ bool checkFriendlinessAndHonesty(int otherActorId);
+
+ int getHonesty() const { return _honesty; }
void setHonesty(int honesty);
+ void modifyHonesty(signed int change);
+
+ int getIntelligence() const { return _intelligence; }
void setIntelligence(int intelligence);
+ void modifyIntelligence(signed int change);
+
+ int getStability() const { return _stability; }
void setStability(int stability);
+ void modifyStability(signed int change);
+
+ int getCombatAggressiveness() const { return _combatAggressiveness; }
void setCombatAggressiveness(int combatAggressiveness);
+ void modifyCombatAggressiveness(signed int change);
+
void setInvisible(bool isInvisible);
void setImmunityToObstacles(bool isImmune);
- void modifyCurrentHP(signed int change);
- void modifyMaxHP(signed int change);
- void modifyCombatAggressiveness(signed int change);
- void modifyHonesty(signed int change);
- void modifyIntelligence(signed int change);
- void modifyStability(signed int change);
+
void setFlagDamageAnimIfMoving(bool value);
- bool getFlagDamageAnimIfMoving() const;
- void setHealth(int hp, int maxHp);
+ bool getFlagDamageAnimIfMoving() const;
void retire(bool isRetired, int width, int height, int retiredByActorId);
- void combatModeOn(int a2, int a3, int a4, int a5, int combatAnimationMode, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14);
+ void combatModeOn(int initialState, bool rangedAttack, int enemyId, int waypointType, int animationModeCombatIdle, int animationModeCombatWalk, int animationModeCombatRun, int fleeRatio, int coverRatio, int actionRatio, int damage, int range, bool unstoppable);
void combatModeOff();
void setGoal(int goalNumber);
int getGoal() const;
float distanceFromActor(int otherActorId);
+ int angleTo(const Vector3 &target) const;
void speechPlay(int sentenceId, bool voiceOver);
void speechStop();
@@ -221,15 +246,19 @@ public:
void loseClue(int clueId);
bool hasClue(int clueId) const;
void copyClues(int actorId);
+ void acquireCluesByRelations();
int soundVolume() const;
int soundBalance() const;
- bool isObstacleBetween(float targetX, float targetZ);
+ bool isObstacleBetween(const Vector3 &target);
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
static int findTargetUnderMouse(BladeRunnerEngine *vm, int mouseX, int mouseY);
+
private:
- void setFacing(int facing, bool halfOrSet = true);
void setBoundingBox(const Vector3 &position, bool retired);
float distanceFromView(View *view) const;
diff --git a/engines/bladerunner/actor_clues.cpp b/engines/bladerunner/actor_clues.cpp
index 39fbc77d4e..b34e67b46e 100644
--- a/engines/bladerunner/actor_clues.cpp
+++ b/engines/bladerunner/actor_clues.cpp
@@ -21,10 +21,13 @@
*/
#include "bladerunner/actor_clues.h"
+#include "bladerunner/actor.h"
+#include "bladerunner/script/ai_script.h"
#include "bladerunner/bladerunner.h"
#include "bladerunner/game_info.h"
#include "bladerunner/crimes_database.h"
+#include "bladerunner/savefile.h"
#include "common/debug.h"
@@ -87,6 +90,147 @@ bool ActorClues::isAcquired(int clueId) const {
#endif
}
+int ActorClues::getWeight(int clueId) const {
+ int clueIndex = findClueIndex(clueId);
+ if (clueIndex == -1) {
+ return 0;
+ }
+ return _clues[clueIndex].weight;
+}
+
+int ActorClues::getModifier(int actorId, int otherActorId, int clueId) {
+ Actor *actor = _vm->_actors[actorId];
+ int modifier1, modifier2, modifier3, modifier4;
+
+ int friendliness = actor->getFriendlinessToOther(otherActorId);
+ int clueWeight = actor->_clues->getWeight(clueId);
+
+ if (actor->_clues->isFlag2(clueId)) {
+ modifier1 = 100 - actor->getHonesty() - friendliness;
+ } else {
+ modifier1 = 0;
+ }
+ modifier2 = 0;
+ modifier3 = _vm->_aiScripts->callGetFriendlinessModifierIfGetsClue(otherActorId, actorId, clueId);
+
+ for (int i = 0; i < _vm->_gameInfo->getActorCount(); i++) {
+ if (i != actorId && i != otherActorId) {
+ modifier2 += (friendliness - 50) * _vm->_aiScripts->callGetFriendlinessModifierIfGetsClue(i, otherActorId, clueId) / 100;
+ }
+ }
+ modifier4 = _vm->_rnd.getRandomNumberRng(0, (100 - actor->getIntelligence()) / 10);
+
+ if (_vm->_rnd.getRandomNumberRng(0, 1) == 1) {
+ modifier4 = -modifier4;
+ }
+
+ return modifier1 + modifier2 + modifier3 + modifier4 + clueWeight;
+}
+
+static int cluesCompare(const void *p1, const void *p2) {
+ const ActorClues::CluesUS *clue1 = (const ActorClues::CluesUS *)p1;
+ const ActorClues::CluesUS *clue2 = (const ActorClues::CluesUS *)p2;
+
+ if (clue1->modifier > clue2->modifier)
+ return -1;
+
+ return (clue1->modifier < clue2->modifier);
+}
+
+void ActorClues::acquireCluesByRelations(int actorId, int otherActorId) {
+ CluesUS clues1[kClueCount], clues2[kClueCount];
+
+ int count1 = findAcquirableCluesFromActor(actorId, otherActorId, clues1, kClueCount);
+ int count2 = findAcquirableCluesFromActor(otherActorId, actorId, clues2, kClueCount);
+
+ if (count1 || count2) {
+ for (int i = 0; i < count1; i++) {
+ clues1[i].modifier = getModifier(actorId, otherActorId, clues1[i].clueId);
+ }
+ qsort(clues1, count1, sizeof(CluesUS), cluesCompare);
+
+ for (int i = 0; i < count2; i++) {
+ clues2[i].modifier = getModifier(otherActorId, actorId, clues2[i].clueId);
+ }
+ qsort(clues2, count2, sizeof(CluesUS), cluesCompare);
+
+ Actor *actor = _vm->_actors[actorId];
+ Actor *otherActor = _vm->_actors[otherActorId];
+
+ int avgParameters = (otherActor->getHonesty() + otherActor->getIntelligence() + actor->getFriendlinessToOther(otherActorId)) / 3;
+ int clue1count = avgParameters * count1 / 100;
+
+ if (avgParameters >= 50 && !clue1count && count1 == 1) {
+ clue1count = 1;
+ }
+
+ avgParameters = (actor->getHonesty() + actor->getIntelligence() + otherActor->getFriendlinessToOther(actorId)) / 3;
+ int clue2count = avgParameters * count2 / 100;
+
+ if (avgParameters >= 50 && !clue2count && count2 == 1) {
+ clue2count = 1;
+ }
+
+ for (int i = 0; i < clue2count; i++) {
+ bool flag = false;
+ if (otherActor->_clues->isFlag2(clues2[i].clueId)) {
+ avgParameters = (2 * otherActor->getFriendlinessToOther(actorId) + otherActor->getHonesty()) / 3;
+
+ if (avgParameters > 70) {
+ avgParameters = 100;
+ } else if (avgParameters < 30) {
+ avgParameters = 0;
+ }
+ if (_vm->_rnd.getRandomNumberRng(1, 100) <= avgParameters) {
+ flag = true;
+ }
+ }
+
+ actor->_clues->acquire(clues2[i].clueId, flag, otherActorId);
+ }
+
+ for (int i = 0; i < clue1count; i++) {
+ bool flag = false;
+ if (actor->_clues->isFlag2(clues1[i].clueId)) {
+ avgParameters = (2 * actor->getFriendlinessToOther(otherActorId) + actor->getHonesty()) / 3;
+
+ if (avgParameters > 70) {
+ avgParameters = 100;
+ } else if (avgParameters < 30) {
+ avgParameters = 0;
+ }
+ if (_vm->_rnd.getRandomNumberRng(1, 100) <= avgParameters) {
+ flag = true;
+ }
+ }
+
+ otherActor->_clues->acquire(clues1[i].clueId, flag, actorId);
+ }
+ }
+}
+
+int ActorClues::findAcquirableCluesFromActor(int actorId, int targetActorId, CluesUS *list, int size) {
+ Actor *actor = _vm->_actors[actorId];
+ Actor *otherActor = _vm->_actors[targetActorId];
+ int count = 0;
+ int cluesCount = actor->_clues->getCount();
+
+ for (int i = 0; i < cluesCount; i++) {
+ int clueId = actor->_clues->getClueIdByIndex(i);
+
+ if (actor->_clues->isAcquired(clueId)
+ && otherActor->_clues->getWeight(clueId) > 0
+ && !otherActor->_clues->isAcquired(clueId)) {
+ list[count].clueId = clueId;
+ list[count].modifier = 0;
+
+ count++;
+ }
+ }
+
+ return count;
+}
+
int ActorClues::getFromActorId(int clueId) const {
int clueIndex = findClueIndex(clueId);
if (clueIndex == -1) {
@@ -166,6 +310,10 @@ int ActorClues::getCount() const {
return _count;
}
+int ActorClues::getClueIdByIndex(int index) const {
+ return _clues[index].clueId;
+}
+
void ActorClues::removeAll() {
_count = 0;
for (int i = 0; i < _maxCount; ++i) {
@@ -216,6 +364,44 @@ void ActorClues::remove(int index) {
_clues[index].field8 = 0;
}
+void ActorClues::save(SaveFileWriteStream &f) {
+ f.writeInt(_count);
+ f.writeInt(_maxCount);
+ for (int i = 0; i < _count; ++i) {
+ Clue &c = _clues[i];
+ f.writeInt(c.clueId);
+ f.writeInt(c.weight);
+ f.writeInt(c.fromActorId);
+ f.writeInt(c.field3);
+ f.writeInt(c.field4);
+ f.writeInt(c.field5);
+ f.writeInt(c.field6);
+ f.writeInt(c.field7);
+ f.writeInt(c.field8);
+ f.writeByte(c.flags);
+ }
+}
+
+void ActorClues::load(SaveFileReadStream &f) {
+ _count = f.readInt();
+ _maxCount = f.readInt();
+ _clues.clear();
+ _clues.resize(_maxCount);
+ for (int i = 0; i < _count; ++i) {
+ Clue &c = _clues[i];
+ c.clueId = f.readInt();
+ c.weight = f.readInt();
+ c.fromActorId = f.readInt();
+ c.field3 = f.readInt();
+ c.field4 = f.readInt();
+ c.field5 = f.readInt();
+ c.field6 = f.readInt();
+ c.field7 = f.readInt();
+ c.field8 = f.readInt();
+ c.flags = f.readByte();
+ }
+}
+
bool ActorClues::exists(int clueId) const {
return findClueIndex(clueId) != -1;
}
diff --git a/engines/bladerunner/actor_clues.h b/engines/bladerunner/actor_clues.h
index b2b39d8b89..76690329d3 100644
--- a/engines/bladerunner/actor_clues.h
+++ b/engines/bladerunner/actor_clues.h
@@ -28,8 +28,12 @@
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class ActorClues {
+ static const int kClueCount = 288;
+
struct Clue {
int clueId;
int weight;
@@ -40,7 +44,7 @@ class ActorClues {
int field6;
int field7;
int field8;
- unsigned char flags;
+ byte flags;
};
BladeRunnerEngine *_vm;
@@ -50,6 +54,12 @@ class ActorClues {
Common::Array<Clue> _clues;
public:
+ struct CluesUS {
+ int clueId;
+ int modifier;
+ };
+
+public:
ActorClues(BladeRunnerEngine *_vm, int cluesType);
void add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId);
@@ -57,6 +67,12 @@ public:
void acquire(int clueId, bool flag2, int fromActorId);
void lose(int clueId);
bool isAcquired(int clueId) const;
+ int getWeight(int clueId) const;
+
+ int getModifier(int actorId, int otherActorId, int clueId);
+
+ void acquireCluesByRelations(int actorId, int otherActorId);
+ int findAcquirableCluesFromActor(int actorId, int targetActorId, CluesUS *list, int size);
int getFromActorId(int clueId) const;
@@ -71,11 +87,12 @@ public:
int getField1(int clueId) const;
int getCount() const;
+ int getClueIdByIndex(int index) const;
void removeAll();
- //savegame
- //loadgame
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
private:
bool exists(int clueId) const;
diff --git a/engines/bladerunner/actor_combat.cpp b/engines/bladerunner/actor_combat.cpp
index 4bd8d17c67..4bcce5d3bf 100644
--- a/engines/bladerunner/actor_combat.cpp
+++ b/engines/bladerunner/actor_combat.cpp
@@ -22,25 +22,673 @@
#include "bladerunner/actor_combat.h"
+#include "bladerunner/actor.h"
+#include "bladerunner/audio_speech.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/combat.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/movement_track.h"
+#include "bladerunner/savefile.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/scene_objects.h"
+#include "bladerunner/script/ai_script.h"
+#include "bladerunner/set.h"
+#include "bladerunner/settings.h"
+
namespace BladeRunner {
ActorCombat::ActorCombat(BladeRunnerEngine *vm) {
_vm = vm;
+ reset();
}
ActorCombat::~ActorCombat() {
}
-void ActorCombat::hitAttempt() {
+void ActorCombat::setup() {
+ reset();
}
-void ActorCombat::combatOn(int actorId, int a3, int a4, int otherActorId, int a6, int a7, int a8, int a9, int ammoDamage, int a11, int a12) {
+void ActorCombat::combatOn(int actorId, int initialState, bool rangedAttackFlag, int enemyId, int waypointType, int fleeRatio, int coverRatio, int actionRatio, int damage, int range, bool unstoppable) {
+ _actorId = actorId;
+ _state = initialState;
+ _rangedAttack = rangedAttackFlag;
+ _enemyId = enemyId;
+ _waypointType = waypointType;
+ _damage = damage;
+ _fleeRatioConst = fleeRatio;
+ _coverRatioConst = coverRatio;
+ _actionRatioConst = actionRatio;
+ _fleeRatio = fleeRatio;
+ _coverRatio = coverRatio;
+ _actionRatio = actionRatio;
+ _active = true;
+ if (_rangedAttack) {
+ _range = range;
+ } else {
+ _range = 300;
+ }
+ _unstoppable = unstoppable;
+
+ Actor *actor = _vm->_actors[_actorId];
+
+ _actorPosition = actor->getXYZ();
+ _enemyPosition = _vm->_actors[_enemyId]->getXYZ();
+
+ actor->_movementTrack->flush();
+ actor->stopWalking(false);
+
+ if (_enemyId == kActorMcCoy) {
+ actor->setTarget(true);
+ }
+
+ _actorHp = actor->getCurrentHP();
+
+ _coversWaypointCount = 0;
+ for (int i = 0; i < (int)_vm->_gameInfo->getCoverWaypointCount(); ++i) {
+ if (_vm->_combat->_coverWaypoints[i].type == waypointType && _vm->_combat->_coverWaypoints[i].setId == actor->getSetId()) {
+ ++_coversWaypointCount;
+ }
+ }
+ if (_coversWaypointCount == 0) {
+ _coverRatioConst = 0;
+ _coverRatio = 0;
+ }
+
+ _fleeWaypointsCount = 0;
+ for (int i = 0; i < (int)_vm->_gameInfo->getFleeWaypointCount(); ++i) {
+ if (_vm->_combat->_fleeWaypoints[i].type == waypointType && _vm->_combat->_fleeWaypoints[i].setId == actor->getSetId()) {
+ ++_fleeWaypointsCount;
+ }
+ }
+ if (_fleeWaypointsCount == 0) {
+ _fleeRatioConst = 0;
+ _fleeRatio = 0;
+ }
}
void ActorCombat::combatOff() {
+ _active = false;
+ reset();
}
-void ActorCombat::setup() {
+void ActorCombat::tick() {
+ static int processingCounter = 0;
+
+ if (!_active || processingCounter > 0) {
+ return;
+ }
+
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ if (actor->getSetId() != enemy->getSetId()) {
+ actor->combatModeOff();
+ return;
+ }
+
+ ++processingCounter;
+
+ _actorPosition = actor->getXYZ();
+ _enemyPosition = enemy->getXYZ();
+
+ if (_actionRatioConst >= 0) {
+ _actionRatio = _actionRatioConst;
+ } else {
+ _actionRatio = calculateActionRatio();
+ }
+
+ if (_vm->_combat->findCoverWaypoint(_waypointType, _actorId, _enemyId) != -1) {
+ if (_coverRatioConst >= 0) {
+ _coverRatio = _coverRatioConst;
+ } else {
+ _coverRatio = calculateCoverRatio();
+ }
+ } else {
+ _coverRatio = 0;
+ }
+
+ if (_fleeRatioConst >= 0) {
+ _fleeRatio = _fleeRatioConst;
+ } else {
+ _fleeRatio = calculateFleeRatio();
+ }
+
+ float dist = actor->distanceFromActor(_enemyId);
+ int oldState = _state;
+
+ if (_actionRatio < _fleeRatio || _actionRatio < _coverRatio) {
+ if (_coverRatio >= _fleeRatio && _coverRatio >= _actionRatio) {
+ _state = kActorCombatStateCover;
+ } else {
+ _state = kActorCombatStateFlee;
+ }
+ } else {
+ if (_rangedAttack) {
+ if (dist > _range) {
+ _state = kActorCombatStateApproachRangedAttack;
+ } else {
+ if (actor->isObstacleBetween(_enemyPosition)) {
+ _state = kActorCombatStateUncover;
+ } else {
+ _state = kActorCombatStateRangedAttack;
+ }
+ }
+ } else {
+ if (dist > 36.0f) {
+ _state = kActorCombatStateApproachCloseAttack;
+ } else {
+ _state = kActorCombatStateCloseAttack;
+ }
+ }
+ }
+
+ if (enemy->isRetired()) {
+ _state = kActorCombatStateIdle;
+ }
+
+ if (actor->getAnimationMode() == kAnimationModeHit || actor->getAnimationMode() == kAnimationModeCombatHit) {
+ _state = kActorCombatStateIdle;
+ } else {
+ if (_state != oldState) {
+ actor->stopWalking(false);
+ }
+ }
+ switch (_state) {
+ case kActorCombatStateCover:
+ cover();
+ break;
+ case kActorCombatStateApproachCloseAttack:
+ approachToCloseAttack();
+ break;
+ case kActorCombatStateUncover:
+ uncover();
+ break;
+ case kActorCombatStateAim:
+ aim();
+ break;
+ case kActorCombatStateRangedAttack:
+ rangedAttack();
+ break;
+ case kActorCombatStateCloseAttack:
+ closeAttack();
+ break;
+ case kActorCombatStateFlee:
+ flee();
+ break;
+ case kActorCombatStateApproachRangedAttack:
+ approachToRangedAttack();
+ break;
+ }
+ --processingCounter;
+}
+
+void ActorCombat::hitAttempt() {
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ if (_enemyId == kActorMcCoy && !_vm->playerHasControl() && !_unstoppable) {
+ return;
+ }
+
+ if (actor->isRetired()) {
+ return;
+ }
+
+ int aggressiveness = 0;
+ if (_rangedAttack) {
+ aggressiveness = _rangedAttack == 1 ? getaggressivenessRangedAttack() : 0;
+ } else {
+ aggressiveness = getaggressivenessCloseAttack();
+ }
+
+ if (aggressiveness == 0) {
+ return;
+ }
+
+ int random = _vm->_rnd.getRandomNumberRng(1, 100);
+
+ if (random <= aggressiveness) {
+ if (enemy->isWalking()) {
+ enemy->stopWalking(true);
+ }
+
+ int sentenceId = _vm->_rnd.getRandomNumberRng(0, 1) ? 9000 : 9005;
+ if (enemy->inCombat()) {
+ enemy->changeAnimationMode(22, false);
+ } else {
+ enemy->changeAnimationMode(21, false);
+ }
+
+ int damage = 0;
+ if (_rangedAttack) {
+ damage = getDamageRangedAttack(random, aggressiveness);
+ } else {
+ damage = getDamageCloseAttack(random, aggressiveness);
+ }
+
+ int enemyHp = MAX(enemy->getCurrentHP() - damage, 0);
+ enemy->setCurrentHP(enemyHp);
+
+ if (enemyHp <= 0) {
+ if (!enemy->isRetired()) {
+ if (enemy->inCombat()) {
+ enemy->changeAnimationMode(49, false);
+ } else {
+ enemy->changeAnimationMode(48, false);
+ }
+ sentenceId = 9020;
+ }
+ enemy->retire(true, 6, 3, _actorId);
+ }
+
+ if (_enemyId == kActorMcCoy) {
+ sentenceId += 900;
+ }
+
+ _vm->_audioSpeech->playSpeechLine(_enemyId, sentenceId, 75, enemy->soundBalance(), 99);
+ }
+}
+
+void ActorCombat::save(SaveFileWriteStream &f) {
+ f.writeInt(_actorId);
+ f.writeBool(_active);
+ f.writeInt(_state);
+ f.writeBool(_rangedAttack);
+ f.writeInt(_enemyId);
+ f.writeInt(_waypointType);
+ f.writeInt(_damage);
+ f.writeInt(_fleeRatio);
+ f.writeInt(_coverRatio);
+ f.writeInt(_actionRatio);
+ f.writeInt(_fleeRatioConst);
+ f.writeInt(_coverRatioConst);
+ f.writeInt(_actionRatioConst);
+ f.writeInt(_range);
+ f.writeInt(_unstoppable);
+ f.writeInt(_actorHp);
+ f.writeInt(_fleeingTowards);
+ f.writeVector3(_actorPosition);
+ f.writeVector3(_enemyPosition);
+ f.writeInt(_coversWaypointCount);
+ f.writeInt(_fleeWaypointsCount);
+}
+
+void ActorCombat::load(SaveFileReadStream &f) {
+ _actorId = f.readInt();
+ _active = f.readBool();
+ _state = f.readInt();
+ _rangedAttack = f.readBool();
+ _enemyId = f.readInt();
+ _waypointType = f.readInt();
+ _damage = f.readInt();
+ _fleeRatio = f.readInt();
+ _coverRatio = f.readInt();
+ _actionRatio = f.readInt();
+ _fleeRatioConst = f.readInt();
+ _coverRatioConst = f.readInt();
+ _actionRatioConst = f.readInt();
+ _range = f.readInt();
+ _unstoppable = f.readInt();
+ _actorHp = f.readInt();
+ _fleeingTowards = f.readInt();
+ _actorPosition = f.readVector3();
+ _enemyPosition = f.readVector3();
+ _coversWaypointCount = f.readInt();
+ _fleeWaypointsCount = f.readInt();
+}
+
+void ActorCombat::reset() {
+ _active = false;
+ _actorId = -1;
+ _state = -1;
+ _rangedAttack = false;
+ _enemyId = -1;
+ _waypointType = -1;
+ _damage = 0;
+ _fleeRatio = -1;
+ _coverRatio = -1;
+ _actionRatio = -1;
+ _fleeRatioConst = -1;
+ _coverRatioConst = -1;
+ _actionRatioConst = -1;
+ _actorHp = 0;
+ _range = 300;
+ _unstoppable = false;
+ _actorPosition = Vector3(0.0f, 0.0f, 0.0f);
+ _enemyPosition = Vector3(0.0f, 0.0f, 0.0f);
+ _coversWaypointCount = 0;
+ _fleeWaypointsCount = 0;
+ _fleeingTowards = -1;
+}
+
+void ActorCombat::cover() {
+ Actor *actor = _vm->_actors[_actorId];
+
+ if (actor->isWalking()) {
+ return;
+ }
+
+ if (actor->isObstacleBetween(_enemyPosition)) {
+ faceEnemy();
+ return;
+ }
+
+ int coverWaypointId = _vm->_combat->findCoverWaypoint(_waypointType, _actorId, _enemyId);
+ if (coverWaypointId == -1) {
+ _state = kActorCombatStateIdle;
+ } else {
+ actor->asyncWalkToXYZ(_vm->_combat->_coverWaypoints[coverWaypointId].position, 0, true, 0);
+ }
+}
+
+void ActorCombat::approachToCloseAttack() {
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ float dist = actor->distanceFromActor(_enemyId);
+ if (dist > 36.0f) {
+ if (!actor->isWalking() || enemy->isWalking()) {
+ Vector3 target;
+ if (findClosestPositionToEnemy(target)) {
+ actor->asyncWalkToXYZ(target, 0, dist >= 240.0f, 0);
+ } else {
+ _state = kActorCombatStateCover;
+ }
+ }
+ } else {
+ if (actor->isWalking()) {
+ actor->stopWalking(false);
+ }
+ faceEnemy();
+ _state = kActorCombatStateCloseAttack;
+ }
+}
+
+void ActorCombat::approachToRangedAttack() {
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ float dist = actor->distanceFromActor(_enemyId);
+ if (dist > _range) {
+ if (!actor->isWalking() || enemy->isWalking()) {
+ Vector3 target;
+ if (findClosestPositionToEnemy(target)) {
+ actor->asyncWalkToXYZ(target, 0, dist >= 240.0f, 0);
+ } else {
+ _state = kActorCombatStateCover;
+ }
+ }
+ } else {
+ if (actor->isWalking()) {
+ actor->stopWalking(false);
+ }
+ faceEnemy();
+ _state = kActorCombatStateRangedAttack;
+ }
+}
+
+void ActorCombat::uncover() {
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ if (actor->isObstacleBetween(_enemyPosition)) {
+ actor->asyncWalkToXYZ(enemy->getXYZ(), 16, false, 0);
+ } else {
+ if (actor->isWalking()) {
+ actor->stopWalking(false);
+ }
+ faceEnemy();
+ }
+}
+
+void ActorCombat::aim() {
+ Actor *actor = _vm->_actors[_actorId];
+
+ if (actor->isObstacleBetween(_enemyPosition)) {
+ if (actor->getAnimationMode() != kAnimationModeCombatIdle) {
+ actor->changeAnimationMode(kAnimationModeCombatIdle, false);
+ }
+ } else {
+ faceEnemy();
+ if (actor->getAnimationMode() != kAnimationModeCombatAim) {
+ actor->changeAnimationMode(kAnimationModeCombatAim, false);
+ }
+ }
+}
+
+void ActorCombat::rangedAttack() {
+ Actor *actor = _vm->_actors[_actorId];
+
+ if (actor->isObstacleBetween(_enemyPosition) || (actor->distanceFromActor(_enemyId) > _range)) {
+ _state = kActorCombatStateApproachRangedAttack;
+ } else {
+ faceEnemy();
+ if (actor->getAnimationMode() != kAnimationModeCombatAttack) {
+ if (_enemyId != kActorMcCoy || _vm->playerHasControl() || _unstoppable) {
+ actor->changeAnimationMode(kAnimationModeCombatAttack, false);
+ }
+ }
+ }
+}
+
+void ActorCombat::closeAttack() {
+ Actor *actor = _vm->_actors[_actorId];
+
+ if (actor->isObstacleBetween(_enemyPosition) || (actor->distanceFromActor(_enemyId) > 36.0f)) {
+ _state = kActorCombatStateApproachCloseAttack;
+ } else {
+ faceEnemy();
+ if (actor->getAnimationMode() != kAnimationModeCombatAttack) {
+ if (_enemyId != kActorMcCoy || _vm->playerHasControl() || _unstoppable) {
+ actor->changeAnimationMode(kAnimationModeCombatAttack, false);
+ }
+ }
+ }
+}
+
+void ActorCombat::flee() {
+ Actor *actor = _vm->_actors[_actorId];
+
+ if (_fleeingTowards != -1 && actor->isWalking()) {
+ Vector3 fleeWaypointPosition = _vm->_combat->_fleeWaypoints[_fleeingTowards].position;
+ if (distance(_actorPosition, fleeWaypointPosition) <= 12.0f) {
+ _vm->_aiScripts->fledCombat(_actorId/*, _enemyId*/);
+ actor->setSetId(kSetFreeSlotG);
+ actor->combatModeOff();
+ _fleeingTowards = -1;
+ }
+ } else {
+ int fleeWaypointId = _vm->_combat->findFleeWaypoint(actor->getSetId(), _enemyId, _actorPosition);
+ if (fleeWaypointId == -1) {
+ _state = kActorCombatStateIdle;
+ } else {
+ Vector3 fleeWaypointPosition = _vm->_combat->_fleeWaypoints[fleeWaypointId].position;
+ actor->asyncWalkToXYZ(fleeWaypointPosition, 0, true, 0);
+ _fleeingTowards = fleeWaypointId;
+ }
+ }
+}
+
+void ActorCombat::faceEnemy() {
+ _vm->_actors[_actorId]->setFacing(angle_1024(_actorPosition.x, _actorPosition.z, _enemyPosition.x, _enemyPosition.z), false);
+}
+
+int ActorCombat::getaggressivenessCloseAttack() const{
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ float distance = actor->distanceFromActor(_enemyId);
+
+ if (distance > 36.0f) {
+ return 0;
+ }
+
+ int aggressiveness = 0;
+ if (enemy->isRunning()) {
+ aggressiveness = 11;
+ } else if (enemy->isMoving()) {
+ aggressiveness = 22;
+ } else {
+ aggressiveness = 33;
+ }
+
+ aggressiveness += actor->getCombatAggressiveness() / 3;
+
+ int angle = abs(actor->angleTo(_enemyPosition));
+
+ if (angle > 128) {
+ return false;
+ }
+
+ return aggressiveness + (abs(angle - 128) / 3.7f);
+}
+
+int ActorCombat::getaggressivenessRangedAttack() const {
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ if (actor->isObstacleBetween(_enemyPosition)) {
+ return 0;
+ }
+
+ int distance = MIN(actor->distanceFromActor(_enemyId), 900.0f);
+
+ int aggressiveness = 0;
+ if (enemy->isRunning()) {
+ aggressiveness = 10;
+ } else if (enemy->isMoving()) {
+ aggressiveness = 20;
+ } else {
+ aggressiveness = 30;
+ }
+
+ aggressiveness += actor->getCombatAggressiveness() / 5;
+ return aggressiveness + abs((distance / 30) - 30) + actor->getIntelligence() / 5;
+}
+
+int ActorCombat::getDamageCloseAttack(int min, int max) const {
+ if (_enemyId == kActorMcCoy && _vm->_settings->getDifficulty() == 0) {
+ return _damage / 2;
+ }
+ if (_enemyId == kActorMcCoy && _vm->_settings->getDifficulty() == 2) {
+ return _damage;
+ }
+ return ((MIN(max - min, 30) * 100.0f / 60.0f) + 50) * _damage / 100;
+}
+
+int ActorCombat::getDamageRangedAttack(int min, int max) const {
+ if (_enemyId == kActorMcCoy && _vm->_settings->getDifficulty() == 0) {
+ return _damage / 2;
+ }
+ if (_enemyId == kActorMcCoy && _vm->_settings->getDifficulty() == 2) {
+ return _damage;
+ }
+ return ((MIN(max - min, 30) * 100.0f / 60.0f) + 50) * _damage / 100;
+}
+
+int ActorCombat::calculateActionRatio() const {
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ int aggressivenessFactor = actor->getCombatAggressiveness();
+ int actorHpFactor = actor->getCurrentHP();
+ int enemyHpFactor = 100 - enemy->getCurrentHP();
+ int combatFactor = enemy->inCombat() ? 0 : 100;
+ int angleFactor = (100 * abs(enemy->angleTo(_actorPosition))) / 512;
+ int distanceFactor = 2 * (50 - MAX(actor->distanceFromActor(_enemyId) / 12.0f, 50.0f));
+
+ if (_rangedAttack) {
+ return
+ angleFactor * 0.25f +
+ combatFactor * 0.05f +
+ enemyHpFactor * 0.20f +
+ actorHpFactor * 0.10f +
+ aggressivenessFactor * 0.40f;
+ } else {
+ return
+ distanceFactor * 0.20f +
+ angleFactor * 0.10f +
+ combatFactor * 0.10f +
+ enemyHpFactor * 0.15f +
+ actorHpFactor * 0.15f +
+ aggressivenessFactor * 0.30f;
+ }
+}
+
+int ActorCombat::calculateCoverRatio() const {
+ if (_coversWaypointCount == 0) {
+ return 0;
+ }
+
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ int angleFactor = 100 - (100 * abs(enemy->angleTo(_actorPosition))) / 512;
+ int actorHpFactor = 100 - actor->getCurrentHP();
+ int enemyHpFactor = enemy->getCurrentHP();
+ int aggressivenessFactor = 100 - actor->getCombatAggressiveness();
+ int distanceFactor = 2 * MAX(actor->distanceFromActor(_enemyId) / 12.0f, 50.0f);
+
+ if (_rangedAttack) {
+ return
+ angleFactor * 0.40f +
+ enemyHpFactor * 0.05f +
+ actorHpFactor * 0.15f +
+ aggressivenessFactor * 0.50f;
+ } else {
+ return
+ distanceFactor * 0.25f +
+ angleFactor * 0.20f +
+ enemyHpFactor * 0.05f +
+ actorHpFactor * 0.10f +
+ aggressivenessFactor * 0.50f;
+ }
+}
+
+int ActorCombat::calculateFleeRatio() const {
+ if (_fleeWaypointsCount == 0) {
+ return 0;
+ }
+
+ Actor *actor = _vm->_actors[_actorId];
+ Actor *enemy = _vm->_actors[_enemyId];
+
+ int aggressivenessFactor = 100 - actor->getCombatAggressiveness();
+ int actorHpFactor = 100 - actor->getCurrentHP();
+ int combatFactor = enemy->inCombat() ? 100 : 0;
+
+ return
+ combatFactor * 0.2f +
+ actorHpFactor * 0.4f +
+ aggressivenessFactor * 0.4f;
+}
+
+bool ActorCombat::findClosestPositionToEnemy(Vector3 &output) const {
+ output = Vector3();
+
+ Vector3 offsets[] = {
+ Vector3( 0.0f, 0.0f, -28.0f),
+ Vector3( 28.0f, 0.0f, 0.0f),
+ Vector3( 0.0f, 0.0f, 28.0f),
+ Vector3(-28.0f, 0.0f, 0.0f)
+ };
+
+ float min = -1.0f;
+
+ for (int i = 0; i < 4; ++i) {
+ Vector3 test = _enemyPosition + offsets[i];
+ float dist = distance(_actorPosition, test);
+ if ( min == -1.0f || dist < min) {
+ if (!_vm->_sceneObjects->existsOnXZ(_actorId, test.x, test.z, true, true) && _vm->_scene->_set->findWalkbox(test.x, test.z) >= 0) {
+ output = test;
+ min = dist;
+ }
+ }
+ }
+
+ return min >= 0.0f;
}
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_combat.h b/engines/bladerunner/actor_combat.h
index b7ec93533d..8f36445008 100644
--- a/engines/bladerunner/actor_combat.h
+++ b/engines/bladerunner/actor_combat.h
@@ -28,31 +28,33 @@
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class ActorCombat {
BladeRunnerEngine *_vm;
-// int _actorId;
-// int _combatOn;
-// int _field2;
-// int _field3;
-// int _otherActorId;
-// int _field5;
-// int _field6;
-// int _field7;
-// int _field8;
-// int _field9;
-// int _field10;
-// int _field11;
-// int _field12;
-// int _actorHp;
-// int _field14;
-// int _field15;
- Vector3 actorPosition;
- Vector3 otherActorPosition;
-// int _availableCoversCount;
-// int _availableFleeWaypointsCount;
-// int _field24;
+ int _actorId;
+ bool _active;
+ int _state;
+ bool _rangedAttack;
+ int _enemyId;
+ int _waypointType;
+ int _damage;
+ int _fleeRatio;
+ int _coverRatio;
+ int _actionRatio;
+ int _fleeRatioConst;
+ int _coverRatioConst;
+ int _actionRatioConst;
+ int _actorHp;
+ int _range;
+ bool _unstoppable;
+ Vector3 _actorPosition;
+ Vector3 _enemyPosition;
+ int _coversWaypointCount;
+ int _fleeWaypointsCount;
+ int _fleeingTowards;
public:
ActorCombat(BladeRunnerEngine *vm);
@@ -60,10 +62,41 @@ public:
void setup();
+ void combatOn(int actorId, int initialState, bool rangedAttack, int enemyId, int waypointType, int fleeRatio, int coverRatio, int actionRatio, int damage, int range, bool unstoppable);
+ void combatOff();
+
+ void tick();
+
void hitAttempt();
- void combatOn(int actorId, int a3, int a4, int otherActorId, int a6, int a7, int a8, int a9, int a10, int a11, int a12);
- void combatOff();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
+private:
+ void reset();
+
+ void cover();
+ void approachToCloseAttack();
+ void approachToRangedAttack();
+ void uncover();
+ void aim();
+ void rangedAttack();
+ void closeAttack();
+ void flee();
+
+ void faceEnemy();
+
+ int getaggressivenessCloseAttack() const;
+ int getaggressivenessRangedAttack() const;
+
+ int getDamageCloseAttack(int min, int max) const;
+ int getDamageRangedAttack(int min, int max) const;
+
+ int calculateActionRatio() const;
+ int calculateCoverRatio() const;
+ int calculateFleeRatio() const;
+
+ bool findClosestPositionToEnemy(Vector3 &output) const;
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_dialogue_queue.cpp b/engines/bladerunner/actor_dialogue_queue.cpp
index dbf5598a52..48fcf8a6ab 100644
--- a/engines/bladerunner/actor_dialogue_queue.cpp
+++ b/engines/bladerunner/actor_dialogue_queue.cpp
@@ -26,6 +26,7 @@
#include "bladerunner/actor.h"
#include "bladerunner/audio_speech.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/scene.h"
#include "bladerunner/script/scene_script.h"
@@ -53,7 +54,7 @@ void ActorDialogueQueue::add(int actorId, int sentenceId, int animationMode) {
if (actorId == 0 || actorId == BladeRunnerEngine::kActorVoiceOver) {
animationMode = -1;
}
- if (_entries.size() < 25) {
+ if (_entries.size() < kMaxEntries) {
Entry entry;
entry.isNotPause = true;
entry.isPause = false;
@@ -67,7 +68,7 @@ void ActorDialogueQueue::add(int actorId, int sentenceId, int animationMode) {
}
void ActorDialogueQueue::addPause(int delay) {
- if (_entries.size() < 25) {
+ if (_entries.size() < kMaxEntries) {
Entry entry;
entry.isNotPause = false;
entry.isPause = true;
@@ -159,6 +160,58 @@ void ActorDialogueQueue::tick() {
}
}
+void ActorDialogueQueue::save(SaveFileWriteStream &f) {
+ int count = (int)_entries.size();
+ f.writeInt(count);
+ for (int i = 0; i < count; ++i) {
+ Entry &e = _entries[i];
+ f.writeBool(e.isNotPause);
+ f.writeBool(e.isPause);
+ f.writeInt(e.actorId);
+ f.writeInt(e.sentenceId);
+ f.writeInt(e.animationMode);
+ f.writeInt(e.delay);
+ }
+ f.padBytes((kMaxEntries - count) * 24);
+
+ f.writeBool(_isNotPause);
+ f.writeInt(_actorId);
+ f.writeInt(_sentenceId);
+ f.writeInt(_animationMode);
+ f.writeInt(_animationModePrevious);
+ f.writeBool(_isPause);
+ f.writeInt(_delay);
+ // f.write(_timeLast);
+}
+
+void ActorDialogueQueue::load(SaveFileReadStream &f) {
+ _entries.clear();
+ int count = f.readInt();
+ assert(count <= kMaxEntries);
+ _entries.resize(count);
+ for (int i = 0; i < count; ++i) {
+ Entry &e = _entries[i];
+ e.isNotPause = f.readBool();
+ e.isPause = f.readBool();
+ e.actorId = f.readInt();
+ e.sentenceId = f.readInt();
+ e.animationMode = f.readInt();
+ e.delay = f.readInt();
+ }
+
+ f.skip((kMaxEntries - count) * 24);
+
+ _isNotPause = f.readBool();
+ _actorId = f.readInt();
+ _sentenceId = f.readInt();
+ _animationMode = f.readInt();
+ _animationModePrevious = f.readInt();
+ _isPause = f.readBool();
+ _delay = f.readInt();
+
+ _timeLast = 0;
+}
+
void ActorDialogueQueue::clear() {
_entries.clear();
_isNotPause = false;
@@ -170,4 +223,5 @@ void ActorDialogueQueue::clear() {
_delay = 0;
_timeLast = 0;
}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_dialogue_queue.h b/engines/bladerunner/actor_dialogue_queue.h
index 841ca8a48e..832bcc9dab 100644
--- a/engines/bladerunner/actor_dialogue_queue.h
+++ b/engines/bladerunner/actor_dialogue_queue.h
@@ -22,13 +22,18 @@
#ifndef BLADERUNNER_ACTOR_DIALOGUE_QUEUE_H
#define BLADERUNNER_ACTOR_DIALOGUE_QUEUE_H
+
#include "common/array.h"
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class ActorDialogueQueue {
+ static const int kMaxEntries = 25;
+
struct Entry {
bool isNotPause;
bool isPause;
@@ -61,6 +66,9 @@ public:
void flush(int a1, bool callScript);
void tick();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
private:
void clear();
};
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp
index 16009aa65b..b4587333a1 100644
--- a/engines/bladerunner/actor_walk.cpp
+++ b/engines/bladerunner/actor_walk.cpp
@@ -28,6 +28,7 @@
#include "bladerunner/game_constants.h"
#include "bladerunner/game_info.h"
#include "bladerunner/obstacles.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/scene.h"
#include "bladerunner/scene_objects.h"
#include "bladerunner/set.h"
@@ -238,6 +239,53 @@ void ActorWalk::run(int actorId) {
_vm->_actors[actorId]->changeAnimationMode(animationMode, false);
}
+void ActorWalk::save(SaveFileWriteStream &f) {
+ f.writeInt(_walking);
+ f.writeInt(_running);
+ f.writeVector3(_destination);
+ // _originalDestination is not saved
+ f.writeVector3(_current);
+ f.writeVector3(_next);
+ f.writeInt(_facing);
+
+ assert(_nearActors.size() <= 20);
+ for (Common::HashMap<int, bool>::const_iterator it = _nearActors.begin(); it != _nearActors.end(); ++it) {
+ f.writeInt(it->_key);
+ f.writeBool(it->_value);
+ }
+ f.padBytes(8 * (20 - _nearActors.size()));
+ f.writeInt(_nearActors.size());
+
+ f.writeInt(0); // _notUsed
+ f.writeInt(_status);
+}
+
+void ActorWalk::load(SaveFileReadStream &f) {
+ _walking = f.readInt();
+ _running = f.readInt();
+ _destination = f.readVector3();
+ // _originalDestination is not saved
+ _current = f.readVector3();
+ _next = f.readVector3();
+ _facing = f.readInt();
+
+ int actorId[20];
+ bool isNear[20];
+
+ for (int i = 0; i < 20; ++i) {
+ actorId[i] = f.readInt();
+ isNear[i] = f.readBool();
+ }
+
+ int count = f.readInt();
+ for (int i = 0; i < count; ++i) {
+ _nearActors.setVal(actorId[i], isNear[i]);
+ }
+
+ f.skip(4); // _notUsed
+ _status = f.readInt();
+}
+
bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) const {
if (_vm->_scene->_set->findWalkbox(x, z) == -1) {
return true;
diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
index f4caa65453..45298e2794 100644
--- a/engines/bladerunner/actor_walk.h
+++ b/engines/bladerunner/actor_walk.h
@@ -29,6 +29,8 @@
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class ActorWalk {
BladeRunnerEngine *_vm;
@@ -60,6 +62,9 @@ public:
void stop(int actorId, bool immediately, int combatAnimationMode, int animationMode);
void run(int actorId);
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
private:
int nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 &next) const;
diff --git a/engines/bladerunner/ambient_sounds.cpp b/engines/bladerunner/ambient_sounds.cpp
index 64a85bc46c..81b6174ab9 100644
--- a/engines/bladerunner/ambient_sounds.cpp
+++ b/engines/bladerunner/ambient_sounds.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/audio_player.h"
#include "bladerunner/bladerunner.h"
#include "bladerunner/game_info.h"
+#include "bladerunner/savefile.h"
#include "common/debug.h"
#include "common/system.h"
@@ -68,25 +69,23 @@ void AmbientSounds::addSound(
int panStartMin, int panStartMax,
int panEndMin, int panEndMax,
int priority, int unk) {
- const char *name = _vm->_gameInfo->getSfxTrack(sfxId);
sort(volumeMin, volumeMax);
sort(panStartMin, panStartMax);
sort(panEndMin, panEndMax);
addSoundByName(
- name,
- timeMin, timeMax,
- volumeMin, volumeMax,
- panStartMin, panStartMax,
- panEndMin, panEndMax,
- priority, unk
+ _vm->_gameInfo->getSfxTrack(sfxId),
+ timeMin, timeMax,
+ volumeMin, volumeMax,
+ panStartMin, panStartMax,
+ panEndMin, panEndMax,
+ priority, unk
);
}
void AmbientSounds::removeNonLoopingSound(int sfxId, bool stopPlaying) {
- const char *name = _vm->_gameInfo->getSfxTrack(sfxId);
- int32 hash = mix_id(name);
+ int32 hash = MIXArchive::getHash(_vm->_gameInfo->getSfxTrack(sfxId));
int index = findNonLoopingTrackByHash(hash);
if (index >= 0) {
removeNonLoopingSoundByIndex(index, stopPlaying);
@@ -104,8 +103,7 @@ void AmbientSounds::addSpeech(int actorId, int sentenceId, int timeMin, int time
sort(panStartMin, panStartMax);
sort(panEndMin, panEndMax);
- char name[13];
- sprintf(name, "%02d-%04d%s.AUD", actorId, sentenceId, _vm->_languageCode);
+ Common::String name = Common::String::format( "%02d-%04d%s.AUD", actorId, sentenceId, _vm->_languageCode.c_str());
addSoundByName(name,
timeMin, timeMax,
volumeMin, volumeMax,
@@ -115,15 +113,12 @@ void AmbientSounds::addSpeech(int actorId, int sentenceId, int timeMin, int time
}
void AmbientSounds::playSound(int sfxId, int volume, int panStart, int panEnd, int priority) {
- const char *name = _vm->_gameInfo->getSfxTrack(sfxId);
-
- _vm->_audioPlayer->playAud(name, volume * _ambientVolume / 100, panStart, panEnd, priority, kAudioPlayerOverrideVolume);
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(sfxId), volume * _ambientVolume / 100, panStart, panEnd, priority, kAudioPlayerOverrideVolume);
}
void AmbientSounds::addLoopingSound(int sfxId, int volume, int pan, int delay) {
- const char *name = _vm->_gameInfo->getSfxTrack(sfxId);
-
- int32 hash = mix_id(name);
+ const Common::String &name = _vm->_gameInfo->getSfxTrack(sfxId);
+ int32 hash = MIXArchive::getHash(name);
if (findLoopingTrackByHash(hash) >= 0) {
return;
@@ -136,8 +131,7 @@ void AmbientSounds::addLoopingSound(int sfxId, int volume, int pan, int delay) {
LoopingSound &track = _loopingSounds[i];
track.isActive = true;
- strncpy(track.name, name, sizeof(track.name));
- track.name[sizeof(track.name) - 1] = 0;
+ track.name = name;
track.hash = hash;
track.pan = pan;
track.volume = volume;
@@ -161,8 +155,7 @@ void AmbientSounds::addLoopingSound(int sfxId, int volume, int pan, int delay) {
}
void AmbientSounds::adjustLoopingSound(int sfxId, int volume, int pan, int delay) {
- const char *name = _vm->_gameInfo->getSfxTrack(sfxId);
- int32 hash = mix_id(name);
+ int32 hash = MIXArchive::getHash(_vm->_gameInfo->getSfxTrack(sfxId));
int index = findLoopingTrackByHash(hash);
if (index >= 0 && _loopingSounds[index].audioPlayerTrack != -1 && _vm->_audioPlayer->isActive(_loopingSounds[index].audioPlayerTrack)) {
@@ -178,8 +171,7 @@ void AmbientSounds::adjustLoopingSound(int sfxId, int volume, int pan, int delay
}
void AmbientSounds::removeLoopingSound(int sfxId, int delay) {
- const char *name = _vm->_gameInfo->getSfxTrack(sfxId);
- int32 hash = mix_id(name);
+ int32 hash = MIXArchive::getHash(_vm->_gameInfo->getSfxTrack(sfxId));
int index = findLoopingTrackByHash(hash);
if (index >= 0) {
removeLoopingSoundByIndex(index, delay);
@@ -297,15 +289,12 @@ int AmbientSounds::findLoopingTrackByHash(int32 hash) const {
}
void AmbientSounds::addSoundByName(
- const char *name,
+ const Common::String &name,
int timeMin, int timeMax,
int volumeMin, int volumeMax,
int panStartMin, int panStartMax,
int panEndMin, int panEndMax,
int priority, int unk) {
- if (strlen(name) > 12) {
- error("AmbientSounds::addSoundByName: Overlong name '%s'", name);
- }
int i = findAvailableNonLoopingTrack();
if (i < 0) {
@@ -317,9 +306,8 @@ void AmbientSounds::addSoundByName(
uint32 now = _vm->getTotalPlayTime();
track.isActive = true;
- strncpy(track.name, name, sizeof(track.name));
- track.name[sizeof(track.name) - 1] = 0;
- track.hash = mix_id(name);
+ track.name = name;
+ track.hash = MIXArchive::getHash(name);
track.timeMin = 1000 * timeMin;
track.timeMax = 1000 * timeMax;
track.nextPlayTime = now + _vm->_rnd.getRandomNumberRng(track.timeMin, track.timeMax);
@@ -355,11 +343,83 @@ void AmbientSounds::removeLoopingSoundByIndex(int index, int delay) {
}
}
track.isActive = false;
- track.name[0] = 0;
+ track.name.clear();
track.hash = 0;
track.audioPlayerTrack = -1;
track.volume = 0;
track.pan = 0;
}
+void AmbientSounds::save(SaveFileWriteStream &f) {
+ f.writeBool(false); // TODO: _isDisabled
+
+ for (int i = 0; i != kNonLoopingSounds; ++i) {
+ // 73 bytes per non-looping sound
+ NonLoopingSound &s = _nonLoopingSounds[i];
+ f.writeBool(s.isActive);
+ f.writeStringSz(s.name, 13);
+ f.writeSint32LE(s.hash);
+ f.writeInt(s.audioPlayerTrack);
+ f.writeInt(s.timeMin);
+ f.writeInt(s.timeMax);
+ f.writeUint32LE(s.nextPlayTime);
+ f.writeInt(s.volumeMin);
+ f.writeInt(s.volumeMax);
+ f.writeInt(s.volume);
+ f.writeInt(s.panStartMin);
+ f.writeInt(s.panStartMax);
+ f.writeInt(s.panEndMin);
+ f.writeInt(s.panEndMax);
+ f.writeInt(s.priority);
+ f.padBytes(4); // field_45
+ }
+
+ for (int i = 0; i != kLoopingSounds; ++i) {
+ // 33 bytes per looping sound
+ LoopingSound &s = _loopingSounds[i];
+ f.writeBool(s.isActive);
+ f.writeStringSz(s.name, 13);
+ f.writeSint32LE(s.hash);
+ f.writeInt(s.audioPlayerTrack);
+ f.writeInt(s.volume);
+ f.writeInt(s.pan);
+ }
+}
+
+void AmbientSounds::load(SaveFileReadStream &f) {
+ f.skip(4); // TODO: _isDisabled
+
+ for (int i = 0; i != kNonLoopingSounds; ++i) {
+ // 73 bytes per non-looping sound
+ NonLoopingSound &s = _nonLoopingSounds[i];
+ s.isActive = f.readBool();
+ s.name = f.readStringSz(13);
+ s.hash = f.readSint32LE();
+ s.audioPlayerTrack = f.readInt();
+ s.timeMin = f.readInt();
+ s.timeMax = f.readInt();
+ s.nextPlayTime = f.readUint32LE();
+ s.volumeMin = f.readInt();
+ s.volumeMax = f.readInt();
+ s.volume = f.readInt();
+ s.panStartMin = f.readInt();
+ s.panStartMax = f.readInt();
+ s.panEndMin = f.readInt();
+ s.panEndMax = f.readInt();
+ s.priority = f.readInt();
+ f.skip(4); // field_45
+ }
+
+ for (int i = 0; i != kLoopingSounds; ++i) {
+ // 33 bytes per looping sound
+ LoopingSound &s = _loopingSounds[i];
+ s.isActive = f.readBool();
+ s.name = f.readStringSz(13);
+ s.hash = f.readSint32LE();
+ s.audioPlayerTrack = f.readInt();
+ s.volume = f.readInt();
+ s.pan = f.readInt();
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ambient_sounds.h b/engines/bladerunner/ambient_sounds.h
index e06726b183..de08965a11 100644
--- a/engines/bladerunner/ambient_sounds.h
+++ b/engines/bladerunner/ambient_sounds.h
@@ -25,39 +25,43 @@
#include "audio/audiostream.h"
+#include "common/str.h"
+
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class AmbientSounds {
static const int kNonLoopingSounds = 25;
static const int kLoopingSounds = 3;
struct NonLoopingSound {
- bool isActive;
- char name[13];
- int32 hash;
- int32 audioPlayerTrack;
- int32 timeMin;
- int32 timeMax;
- uint32 nextPlayTime;
- int32 volumeMin;
- int32 volumeMax;
- int32 volume;
- int32 panStartMin;
- int32 panStartMax;
- int32 panEndMin;
- int32 panEndMax;
- int32 priority;
+ bool isActive;
+ Common::String name;
+ int32 hash;
+ int audioPlayerTrack;
+ int timeMin;
+ int timeMax;
+ uint32 nextPlayTime;
+ int volumeMin;
+ int volumeMax;
+ int volume;
+ int panStartMin;
+ int panStartMax;
+ int panEndMin;
+ int panEndMax;
+ int priority;
};
struct LoopingSound {
- bool isActive;
- char name[13];
- int32 hash;
- int audioPlayerTrack;
- int32 volume;
- int pan;
+ bool isActive;
+ Common::String name;
+ int32 hash;
+ int audioPlayerTrack;
+ int volume;
+ int pan;
};
BladeRunnerEngine *_vm;
@@ -103,6 +107,9 @@ public:
int getVolume() const;
void playSample();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
private:
int findAvailableNonLoopingTrack() const;
int findNonLoopingTrackByHash(int32 hash) const;
@@ -119,7 +126,7 @@ private:
// playVolumeAdjustSound
void addSoundByName(
- const char *name,
+ const Common::String &name,
int timeMin, int timeMax,
int volumeMin, int volumeMax,
int panStartMin, int panStartMax,
diff --git a/engines/bladerunner/archive.cpp b/engines/bladerunner/archive.cpp
index 8088e1ac67..c116eeb94f 100644
--- a/engines/bladerunner/archive.cpp
+++ b/engines/bladerunner/archive.cpp
@@ -51,7 +51,7 @@ bool MIXArchive::open(const Common::String &filename) {
_entries.resize(_entryCount);
for (uint16 i = 0; i != _entryCount; ++i) {
- _entries[i].id = _fd.readSint32LE();
+ _entries[i].hash = _fd.readUint32LE();
_entries[i].offset = _fd.readUint32LE();
_entries[i].length = _fd.readUint32LE();
@@ -61,7 +61,7 @@ bool MIXArchive::open(const Common::String &filename) {
// Verify that the entries are sorted by id. Note that id is signed.
if (i > 0) {
- assert(_entries[i].id > _entries[i - 1].id);
+ assert(_entries[i].hash > _entries[i - 1].hash);
}
}
@@ -86,7 +86,7 @@ bool MIXArchive::isOpen() const {
#define ROL(n) ((n << 1) | ((n >> 31) & 1))
-int32 mix_id(const Common::String &name) {
+int32 MIXArchive::getHash(const Common::String &name) {
char buffer[12] = { 0 };
for (uint i = 0; i != name.size() && i < 12u; ++i) {
@@ -103,11 +103,10 @@ int32 mix_id(const Common::String &name) {
id = ROL(id) + t;
}
- return reinterpret_cast<int32&>(id);
+ return id;
}
-static
-int32 tlk_id(const Common::String &name) {
+static uint32 tlk_id(const Common::String &name) {
char buffer[12] = { 0 };
for (uint i = 0; i != name.size() && i < 12u; ++i)
@@ -124,15 +123,15 @@ int32 tlk_id(const Common::String &name) {
return 10000 * actor_id + speech_id;
}
-uint32 MIXArchive::indexForId(int32 id) const {
+uint32 MIXArchive::indexForHash(int32 hash) const {
uint32 lo = 0, hi = _entryCount;
while (lo < hi) {
uint32 mid = lo + (hi - lo) / 2;
- if (id > _entries[mid].id) {
+ if (hash > _entries[mid].hash) {
lo = mid + 1;
- } else if (id < _entries[mid].id) {
+ } else if (hash < _entries[mid].hash) {
hi = mid;
} else {
return mid;
@@ -142,14 +141,15 @@ uint32 MIXArchive::indexForId(int32 id) const {
}
Common::SeekableReadStream *MIXArchive::createReadStreamForMember(const Common::String &name) {
- int32 id;
+ int32 hash;
- if (_isTLK)
- id = tlk_id(name);
- else
- id = mix_id(name);
+ if (_isTLK) {
+ hash = tlk_id(name);
+ } else {
+ hash = MIXArchive::getHash(name);
+ }
- uint32 i = indexForId(id);
+ uint32 i = indexForHash(hash);
if (i == _entryCount) {
return nullptr;
diff --git a/engines/bladerunner/archive.h b/engines/bladerunner/archive.h
index 7bec41f97a..9f7c67920d 100644
--- a/engines/bladerunner/archive.h
+++ b/engines/bladerunner/archive.h
@@ -34,6 +34,8 @@ public:
MIXArchive();
~MIXArchive();
+ static int32 getHash(const Common::String &name);
+
bool open(const Common::String &filename);
void close();
bool isOpen() const;
@@ -50,17 +52,16 @@ private:
uint32 _size;
struct ArchiveEntry {
- int32 id;
+ int32 hash;
uint32 offset;
uint32 length;
};
Common::Array<ArchiveEntry> _entries;
- uint32 indexForId(int32 id) const;
+ uint32 indexForHash(int32 hash) const;
};
-int32 mix_id(const Common::String &name);
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/aud_stream.cpp b/engines/bladerunner/aud_stream.cpp
index 0d4434cbbf..3d14f948d2 100644
--- a/engines/bladerunner/aud_stream.cpp
+++ b/engines/bladerunner/aud_stream.cpp
@@ -133,7 +133,12 @@ int AudStream::getLength() const {
if (_flags & 2) { // stereo
bytesPerSecond *= 2;
}
- return (1000 * _sizeDecompressed) / bytesPerSecond;
+
+ // since everything is 44100, we easily get overflows with ints
+ // thus we must use doubles
+ double res = (double)_sizeDecompressed * 1000.0 / (double)bytesPerSecond;
+
+ return (int32)res;
}
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/audio_player.cpp b/engines/bladerunner/audio_player.cpp
index e1ef0263b6..5186888dd2 100644
--- a/engines/bladerunner/audio_player.cpp
+++ b/engines/bladerunner/audio_player.cpp
@@ -253,7 +253,7 @@ int AudioPlayer::playAud(const Common::String &name, int volume, int panFrom, in
}
/* Load audio resource and store in cache. Playback will happen directly from there. */
- int32 hash = mix_id(name);
+ int32 hash = MIXArchive::getHash(name);
if (!_cache->findByHash(hash)) {
Common::SeekableReadStream *r = _vm->getResourceStream(name);
if (!r) {
diff --git a/engines/bladerunner/audio_speech.cpp b/engines/bladerunner/audio_speech.cpp
index 69883cbce2..5ffde9db6c 100644
--- a/engines/bladerunner/audio_speech.cpp
+++ b/engines/bladerunner/audio_speech.cpp
@@ -58,12 +58,12 @@ AudioSpeech::~AudioSpeech() {
delete[] _data;
}
-bool AudioSpeech::playSpeech(const char *name, int pan) {
+bool AudioSpeech::playSpeech(const Common::String &name, int pan) {
// debug("AudioSpeech::playSpeech(\"%s\")", name);
Common::ScopedPtr<Common::SeekableReadStream> r(_vm->getResourceStream(name));
if (!r) {
- warning("AudioSpeech::playSpeech: AUD resource \"%s\" not found", name);
+ warning("AudioSpeech::playSpeech: AUD resource \"%s\" not found", name.c_str());
return false;
}
@@ -78,7 +78,7 @@ bool AudioSpeech::playSpeech(const char *name, int pan) {
r->read(_data, r->size());
if (r->err()) {
- warning("AudioSpeech::playSpeech: Error reading resource \"%s\"", name);
+ warning("AudioSpeech::playSpeech: Error reading resource \"%s\"", name.c_str());
return false;
}
@@ -110,14 +110,14 @@ void AudioSpeech::stopSpeech() {
bool AudioSpeech::isPlaying() const {
if (_channel == -1) {
- return false;
+ return false;
}
return _isActive;
}
bool AudioSpeech::playSpeechLine(int actorId, int sentenceId, int volume, int a4, int priority) {
int balance = _vm->_actors[actorId]->soundBalance();
- Common::String name = Common::String::format("%02d-%04d%s.AUD", actorId, sentenceId, _vm->_languageCode);
+ Common::String name = Common::String::format("%02d-%04d%s.AUD", actorId, sentenceId, _vm->_languageCode.c_str());
return _vm->_audioPlayer->playAud(name, _speechVolume * volume / 100, balance, balance, priority, kAudioPlayerOverrideVolume);
}
diff --git a/engines/bladerunner/audio_speech.h b/engines/bladerunner/audio_speech.h
index 010499f480..5406f1d8e5 100644
--- a/engines/bladerunner/audio_speech.h
+++ b/engines/bladerunner/audio_speech.h
@@ -23,6 +23,7 @@
#ifndef BLADERUNNER_AUDIO_SPEECH_H
#define BLADERUNNER_AUDIO_SPEECH_H
+#include "common/str.h"
#include "common/types.h"
namespace BladeRunner {
@@ -44,7 +45,7 @@ public:
AudioSpeech(BladeRunnerEngine *vm);
~AudioSpeech();
- bool playSpeech(const char *name, int balance = 0);
+ bool playSpeech(const Common::String &name, int balance = 0);
void stopSpeech();
bool isPlaying() const;
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index ea663b53bc..fab708cbb8 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -46,6 +46,7 @@
#include "bladerunner/obstacles.h"
#include "bladerunner/overlays.h"
#include "bladerunner/regions.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/scene.h"
#include "bladerunner/scene_objects.h"
#include "bladerunner/screen_effects.h"
@@ -53,6 +54,7 @@
#include "bladerunner/script/ai_script.h"
#include "bladerunner/script/init_script.h"
#include "bladerunner/script/kia_script.h"
+#include "bladerunner/script/police_maze.h"
#include "bladerunner/script/scene_script.h"
#include "bladerunner/settings.h"
#include "bladerunner/shape.h"
@@ -60,9 +62,12 @@
#include "bladerunner/slice_renderer.h"
#include "bladerunner/suspects_database.h"
#include "bladerunner/text_resource.h"
+#include "bladerunner/time.h"
#include "bladerunner/ui/elevator.h"
+#include "bladerunner/ui/end_credits.h"
#include "bladerunner/ui/esper.h"
#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/scores.h"
#include "bladerunner/ui/spinner.h"
#include "bladerunner/ui/vk.h"
#include "bladerunner/vqa_decoder.h"
@@ -70,8 +75,10 @@
#include "bladerunner/zbuffer.h"
#include "common/array.h"
+#include "common/config-manager.h"
#include "common/error.h"
#include "common/events.h"
+#include "common/savefile.h"
#include "common/system.h"
#include "engines/util.h"
@@ -88,6 +95,9 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst, const ADGameDescription *des
_windowIsActive = true;
_gameIsRunning = true;
+ _vqaIsPlaying = false;
+ _vqaStopIsRequested = false;
+
_playerLosesControlCounter = 0;
_playerActorIdle = false;
@@ -139,6 +149,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst, const ADGameDescription *des
_lights = nullptr;
_obstacles = nullptr;
_sceneScript = nullptr;
+ _gameTime = nullptr;
_gameInfo = nullptr;
_waypoints = nullptr;
_gameVars = nullptr;
@@ -165,11 +176,14 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst, const ADGameDescription *des
_dialogueMenu = nullptr;
_suspectsDatabase = nullptr;
_kia = nullptr;
+ _endCredits = nullptr;
_spinner = nullptr;
+ _scores = nullptr;
_elevator = nullptr;
_mainFont = nullptr;
_esper = nullptr;
_vk = nullptr;
+ _policeMaze = nullptr;
_mouse = nullptr;
_sliceAnimations = nullptr;
_sliceRenderer = nullptr;
@@ -212,6 +226,13 @@ Common::Error BladeRunnerEngine::run() {
/* TODO: Check for save games and enter KIA */
gameLoop();
+
+ _mouse->disable();
+
+ if (_gameOver) {
+ // autoSaveGame(4, 1); // TODO
+ _endCredits->show();
+ }
}
shutdown();
@@ -224,9 +245,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
_screenEffects = new ScreenEffects(this, 0x8000);
- _combat = new Combat(this);
-
- // TODO: end credits
+ _endCredits = new EndCredits(this);
_actorDialogueQueue = new ActorDialogueQueue(this);
@@ -238,7 +257,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
// TODO: outtake player - but this is done bit differently
- // TODO: police maze
+ _policeMaze = new PoliceMaze(this);
_obstacles = new Obstacles(this);
@@ -254,19 +273,22 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
_surfaceBack.create(640, 480, createRGB555());
_surface4.create(640, 480, createRGB555());
+ _gameTime = new Time(this);
+
r = openArchive("STARTUP.MIX");
if (!r)
return false;
- // TODO: Timer
-
_gameInfo = new GameInfo(this);
if (!_gameInfo)
return false;
r = _gameInfo->open("GAMEINFO.DAT");
- if (!r)
+ if (!r) {
return false;
+ }
+
+ _combat = new Combat(this);
// TODO: Create datetime - not used
@@ -286,7 +308,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
// TODO: Flee waypoints
- _gameVars = new int[_gameInfo->getGlobalVarCount()];
+ _gameVars = new int[_gameInfo->getGlobalVarCount()]();
// TODO: Actor AI DLL init
@@ -348,7 +370,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
// TODO: Set actor ids (redundant?)
- // TODO: Police Maze
+ _policeMaze = new PoliceMaze(this);
_textActorNames = new TextResource(this);
if (!_textActorNames->open("ACTORS"))
@@ -390,7 +412,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
_elevator = new Elevator(this);
- // TODO: Scores
+ _scores = new Scores(this);
_mainFont = new Font(this);
_mainFont->open("KIA6PT.FON", 640, 480, -1, 0, 0x252D);
@@ -415,13 +437,6 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
if (!r)
return false;
- // TODO: Support cdframes
-
- r = _sliceAnimations->openHDFrames();
- if (!r) {
- return false;
- }
-
r = _sliceAnimations->openCoreAnim();
if (!r) {
return false;
@@ -461,8 +476,20 @@ void BladeRunnerEngine::initChapterAndScene() {
_actors[i]->movementTrackNext(true);
}
- _settings->setChapter(1);
- _settings->setNewSetAndScene(_gameInfo->getInitialSetId(), _gameInfo->getInitialSceneId());
+ if (ConfMan.hasKey("boot_param")) {
+ int param = ConfMan.getInt("boot_param"); // CTTTSSS
+ int chapter = param / 1000000;
+ param -= chapter * 1000000;
+ int set = param / 1000;
+ param -= set * 1000;
+ int scene = param;
+
+ _settings->setChapter(chapter);
+ _settings->setNewSetAndScene(set, scene);
+ } else {
+ _settings->setChapter(1);
+ _settings->setNewSetAndScene(_gameInfo->getInitialSetId(), _gameInfo->getInitialSceneId());
+ }
}
void BladeRunnerEngine::shutdown() {
@@ -590,7 +617,11 @@ void BladeRunnerEngine::shutdown() {
// TODO: Delete Flee waypoints
- // TODO: Delete Scores
+ delete _scores;
+ _scores = nullptr;
+
+ delete _endCredits;
+ _endCredits = nullptr;
delete _elevator;
_elevator = nullptr;
@@ -630,8 +661,8 @@ void BladeRunnerEngine::shutdown() {
// TODO: Delete MIXArchives here
- // TODO: Delete Timer
-
+ delete _gameTime;
+ _gameTime = nullptr;
// These are static objects in original game
@@ -644,6 +675,9 @@ void BladeRunnerEngine::shutdown() {
delete _itemPickup;
_itemPickup = nullptr;
+ delete _policeMaze;
+ _policeMaze = nullptr;
+
delete _obstacles;
_obstacles = nullptr;
@@ -744,17 +778,25 @@ void BladeRunnerEngine::gameTick() {
return;
}
- // TODO: Scores
+ if (_scores->isOpen()) {
+ _scores->tick();
+ _ambientSounds->tick();
+ return;
+ }
_actorDialogueQueue->tick();
if (_scene->didPlayerWalkIn()) {
_sceneScript->playerWalkedIn();
}
bool inDialogueMenu = _dialogueMenu->isVisible();
- if (!inDialogueMenu) {
- // TODO: actors combat-tick
+ if (!inDialogueMenu) {
+ for (int i = 0; i < (int)_gameInfo->getActorCount(); ++i) {
+ _actors[i]->tickCombat();
+ }
}
+ _policeMaze->tick();
+
// TODO: Gun range announcements
_zbuffer->clean();
@@ -769,9 +811,6 @@ void BladeRunnerEngine::gameTick() {
(void)backgroundChanged;
blit(_surfaceBack, _surfaceFront);
- // TODO: remove zbuffer draw
- // _surfaceFront.copyRectToSurface(_zbuffer->getData(), 1280, 0, 0, 640, 480);
-
_overlays->tick();
if (!inDialogueMenu) {
@@ -814,14 +853,16 @@ void BladeRunnerEngine::gameTick() {
// TODO: Process AUD
if (_walkSoundId >= 0) {
- const char *name = _gameInfo->getSfxTrack(_walkSoundId);
- _audioPlayer->playAud(name, _walkSoundVolume, _walkSoundBalance, _walkSoundBalance, 50, 0);
+ _audioPlayer->playAud(_gameInfo->getSfxTrack(_walkSoundId), _walkSoundVolume, _walkSoundBalance, _walkSoundBalance, 50, 0);
_walkSoundId = -1;
}
if (_debugger->_viewSceneObjects) {
_debugger->drawSceneObjects();
}
+ if (_debugger->_viewObstacles) {
+ _obstacles->draw();
+ }
blitToScreen(_surfaceFront);
_system->delayMillis(10);
@@ -908,6 +949,13 @@ void BladeRunnerEngine::handleKeyUp(Common::Event &event) {
_speechSkipped = true;
}
+ if (_vqaIsPlaying) {
+ _vqaStopIsRequested = true;
+ _vqaIsPlaying = false;
+
+ return;
+ }
+
// TODO:
if (!playerHasControl() /*|| ActorInWalkingLoop*/) {
return;
@@ -938,7 +986,10 @@ void BladeRunnerEngine::handleKeyUp(Common::Event &event) {
return;
}
- //TODO: scores
+ if (_scores->isOpen()) {
+ return;
+ }
+
switch (event.kbd.keycode) {
case Common::KEYCODE_TAB:
_kia->openLastOpened();
@@ -986,7 +1037,10 @@ void BladeRunnerEngine::handleKeyDown(Common::Event &event) {
return;
}
- //TODO: scores
+ if (_scores->isOpen()) {
+ _scores->handleKeyDown(event.kbd);
+ return;
+ }
switch (event.kbd.keycode) {
case Common::KEYCODE_F1:
@@ -1075,6 +1129,15 @@ void BladeRunnerEngine::handleMouseAction(int x, int y, bool mainButton, bool bu
return;
}
+ if (_scores->isOpen()) {
+ if (buttonDown) {
+ _scores->handleMouseDown(x, y);
+ } else {
+ _scores->handleMouseUp(x, y);
+ }
+ return;
+ }
+
if (_dialogueMenu->waitingForInput()) {
if (mainButton && !buttonDown) {
_dialogueMenu->mouseUp();
@@ -1093,7 +1156,7 @@ void BladeRunnerEngine::handleMouseAction(int x, int y, bool mainButton, bool bu
int exitIndex = _scene->_exits->getRegionAtXY(x, y);
int regionIndex = _scene->_regions->getRegionAtXY(x, y);
- if ((sceneObjectId < kSceneObjectOffsetActors || sceneObjectId >= kSceneObjectOffsetActors) && exitIndex >= 0) {
+ if ((sceneObjectId < kSceneObjectOffsetActors || sceneObjectId >= kSceneObjectOffsetItems) && exitIndex >= 0) {
handleMouseClickExit(exitIndex, x, y, buttonDown);
} else if (regionIndex >= 0) {
handleMouseClickRegion(regionIndex, x, y, buttonDown);
@@ -1183,8 +1246,8 @@ void BladeRunnerEngine::handleMouseClickRegion(int regionId, int x, int y, bool
}
void BladeRunnerEngine::handleMouseClick3DObject(int objectId, bool buttonDown, bool isClickable, bool isTarget) {
- const char *objectName = _scene->objectGetName(objectId);
- debug("Clicked on object %s", objectName);
+ const Common::String &objectName = _scene->objectGetName(objectId);
+ debug("Clicked on object %s", objectName.c_str());
if (_isWalkingInterruptible && objectId != _walkingToObjectId) {
_isWalkingInterruptible = false;
@@ -1217,7 +1280,7 @@ void BladeRunnerEngine::handleMouseClick3DObject(int objectId, bool buttonDown,
_walkingToActorId = -1;
_isInsideScriptObject = true;
- _sceneScript->clickedOn3DObject(objectName, false);
+ _sceneScript->clickedOn3DObject(objectName.c_str(), false);
_isInsideScriptObject = false;
}
} else {
@@ -1226,14 +1289,14 @@ void BladeRunnerEngine::handleMouseClick3DObject(int objectId, bool buttonDown,
}
_playerActor->stopWalking(false);
_playerActor->faceObject(objectName, false);
- _playerActor->changeAnimationMode(kAnimationModeCombatShoot, false);
+ _playerActor->changeAnimationMode(kAnimationModeCombatAttack, false);
_settings->decreaseAmmo();
_audioPlayer->playAud(_gameInfo->getSfxTrack(_combat->getHitSound()), 100, 0, 0, 90, 0);
- //TODO mouse::randomize(Mouse);
+ _mouse->setMouseJitterUp();
_isInsideScriptObject = true;
- _sceneScript->clickedOn3DObject(objectName, true);
+ _sceneScript->clickedOn3DObject(objectName.c_str(), true);
_isInsideScriptObject = false;
}
}
@@ -1267,11 +1330,11 @@ void BladeRunnerEngine::handleMouseClickEmpty(int x, int y, Vector3 &scenePositi
} else {
_playerActor->faceItem(itemId, false);
}
- _playerActor->changeAnimationMode(kAnimationModeCombatShoot, false);
+ _playerActor->changeAnimationMode(kAnimationModeCombatAttack, false);
_settings->decreaseAmmo();
_audioPlayer->playAud(_gameInfo->getSfxTrack(_combat->getMissSound()), 100, 0, 0, 90, 0);
- //TODO mouse::randomize(Mouse);
+ _mouse->setMouseJitterUp();
if (actorId > 0) {
_aiScripts->shotAtAndMissed(actorId);
@@ -1362,11 +1425,12 @@ void BladeRunnerEngine::handleMouseClickItem(int itemId, bool buttonDown) {
_playerActor->stopWalking(false);
_playerActor->faceItem(itemId, false);
- _playerActor->changeAnimationMode(kAnimationModeCombatShoot, false);
+ _playerActor->changeAnimationMode(kAnimationModeCombatAttack, false);
_settings->decreaseAmmo();
_audioPlayer->playAud(_gameInfo->getSfxTrack(_combat->getHitSound()), 100, 0, 0, 90, 0);
- //TODO mouse::randomize(Mouse);
+ _mouse->setMouseJitterUp();
+
_isInsideScriptItem = true;
_sceneScript->clickedOnItem(itemId, true);
_isInsideScriptItem = false;
@@ -1422,22 +1486,21 @@ void BladeRunnerEngine::handleMouseClickActor(int actorId, bool mainButton, bool
}
}
} else {
- if (!_combat->isActive() || actorId == kActorMcCoy || !_actors[actorId]->isTarget() || _actors[actorId]->isRetired() /*|| _mouse->isRandomized()*/) {
+ Actor *actor = _actors[actorId];
+
+ if (!_combat->isActive() || actorId == kActorMcCoy || !actor->isTarget() || actor->isRetired() /*|| _mouse->isRandomized()*/) {
return;
}
_playerActor->stopWalking(false);
_playerActor->faceActor(actorId, false);
- _playerActor->changeAnimationMode(kAnimationModeCombatShoot, false);
+ _playerActor->changeAnimationMode(kAnimationModeCombatAttack, false);
_settings->decreaseAmmo();
- float targetX = _actors[actorId]->getX();
- float targetZ = _actors[actorId]->getZ();
-
- bool missed = _playerActor->isObstacleBetween(targetX, targetZ);
+ bool missed = _playerActor->isObstacleBetween(actor->getXYZ());
_audioPlayer->playAud(_gameInfo->getSfxTrack(missed ? _combat->getMissSound() : _combat->getHitSound()), 100, 0, 0, 90, 0);
- //TODO mouse::randomize(Mouse);
+ _mouse->setMouseJitterUp();
if (missed) {
_aiScripts->shotAtAndMissed(actorId);
@@ -1501,7 +1564,6 @@ bool BladeRunnerEngine::openArchive(const Common::String &name) {
* archive when it runs out of slots. */
error("openArchive: No more archive slots");
- return false;
}
_archives[i].open(name);
@@ -1534,9 +1596,11 @@ Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::S
if (!_archives[i].isOpen()) {
continue;
}
+
if (false) {
debug("getResource: Searching archive %s for %s.", _archives[i].getName().c_str(), name.c_str());
}
+
Common::SeekableReadStream *stream = _archives[i].createReadStreamForMember(name);
if (stream) {
return stream;
@@ -1573,8 +1637,144 @@ void BladeRunnerEngine::playerGainsControl() {
}
}
-void BladeRunnerEngine::ISez(const char *str) {
- debug("\t%s", str);
+bool BladeRunnerEngine::saveGame(const Common::String &filename, byte *thumbnail) {
+ warning("BladeRunnerEngine::saveGame not finished");
+
+ if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) {
+ return false;
+ }
+
+ Common::OutSaveFile *commonSaveFile = getSaveFileManager()->openForSaving(filename, false);
+ if (commonSaveFile->err()) {
+ return false;
+ }
+
+ SaveFileWriteStream s;
+
+ s.padBytes(9600); // TODO: thumbnail
+ s.writeFloat(-1.0f);
+ _settings->save(s);
+ _scene->save(s);
+ _scene->_exits->save(s);
+ _scene->_regions->save(s);
+ _scene->_set->save(s);
+ for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) {
+ s.writeInt(_gameVars[i]);
+ }
+ _music->save(s);
+ // _audioPlayer->save(s) // zero func
+ // _audioSpeech->save(s) // zero func
+ _combat->save(s);
+ _gameFlags->save(s);
+ _items->save(s);
+ _sceneObjects->save(s);
+ _ambientSounds->save(s);
+ _overlays->save(s);
+ _spinner->save(s);
+ _scores->save(s);
+ _dialogueMenu->save(s);
+ _obstacles->save(s);
+ _actorDialogueQueue->save(s);
+ _waypoints->save(s);
+
+ for (uint i = 0; i != _gameInfo->getActorCount(); ++i) {
+ _actors[i]->save(s);
+
+ int animationState, animationFrame, animationStateNext, nextAnimation;
+ _aiScripts->queryAnimationState(i, &animationState, &animationFrame, &animationStateNext, &nextAnimation);
+ s.writeInt(animationState);
+ s.writeInt(animationFrame);
+ s.writeInt(animationStateNext);
+ s.writeInt(nextAnimation);
+ }
+ _actors[kActorVoiceOver]->save(s);
+
+ _policeMaze->save(s);
+ _crimesDatabase->save(s);
+
+ s.finalize();
+ assert(0 && "ok");
+
+ commonSaveFile->writeUint32LE(s.size() + 4);
+ commonSaveFile->write(s.getData(), s.size());
+
+ return !commonSaveFile->err();
+}
+
+void BladeRunnerEngine::loadGame(const Common::String &filename, byte *thumbnail) {
+ warning("BladeRunnerEngine::loadGame not finished");
+
+ if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) {
+ return;
+ }
+
+ Common::InSaveFile *commonSaveFile = getSaveFileManager()->openForLoading(filename);
+ if (commonSaveFile->err()) {
+ return;
+ }
+
+ void *buf = malloc(commonSaveFile->size());
+ int dataSize = commonSaveFile->read(buf, commonSaveFile->size());
+
+ SaveFileReadStream s((const byte*)buf, dataSize);
+
+ _ambientSounds->removeAllNonLoopingSounds(true);
+ _ambientSounds->removeAllLoopingSounds(1);
+ _music->stop(2);
+ _audioSpeech->stopSpeech();
+ _actorDialogueQueue->flush(true, false);
+
+ int size = s.readInt();
+
+ if (size != dataSize) {
+ return;
+ }
+
+ s.skip(9600); // thumbnail
+ _settings->load(s);
+ _scene->load(s);
+ _scene->_exits->load(s);
+ _scene->_regions->load(s);
+ _scene->_set->load(s);
+ for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) {
+ _gameVars[i] = s.readInt();
+ }
+ _music->load(s);
+ // _audioPlayer->load(s) // zero func
+ // _audioSpeech->load(s) // zero func
+ _combat->load(s);
+ _gameFlags->load(s);
+ _items->load(s);
+ _sceneObjects->load(s);
+ _ambientSounds->load(s);
+ _overlays->load(s);
+ _spinner->load(s);
+ _scores->load(s);
+ _dialogueMenu->load(s);
+ _obstacles->load(s);
+ _actorDialogueQueue->load(s);
+ _waypoints->load(s);
+
+ for (uint i = 0; i != _gameInfo->getActorCount(); ++i) {
+ _actors[i]->load(s);
+
+ int animationState = s.readInt();
+ int animationFrame = s.readInt();
+ int animationStateNext = s.readInt();
+ int nextAnimation = s.readInt();
+ _aiScripts->setAnimationState(i, animationState, animationFrame, animationStateNext, nextAnimation);
+ }
+ _actors[kActorVoiceOver]->load(s);
+
+ _policeMaze->load(s);
+ _crimesDatabase->load(s);
+
+ _settings->setNewSetAndScene(_settings->getSet(), _settings->getScene());
+ _settings->setChapter(_settings->getChapter());
+}
+
+void BladeRunnerEngine::ISez(const Common::String &str) {
+ debug("\t%s", str.c_str());
}
void BladeRunnerEngine::blitToScreen(const Graphics::Surface &src) {
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 066e6837cc..fc0abf4e0a 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -63,6 +63,7 @@ class Combat;
class Debugger;
class DialogueMenu;
class Elevator;
+class EndCredits;
class ESPER;
class Font;
class GameFlags;
@@ -75,9 +76,11 @@ class Mouse;
class Music;
class Obstacles;
class Overlays;
+class PoliceMaze;
class Scene;
class SceneObjects;
class SceneScript;
+class Scores;
class Settings;
class Shape;
class SliceAnimations;
@@ -85,6 +88,7 @@ class SliceRenderer;
class Spinner;
class SuspectsDatabase;
class TextResource;
+class Time;
class KIAShapes;
class Vector3;
class View;
@@ -102,10 +106,10 @@ public:
static const int kActorCount = 100;
static const int kActorVoiceOver = kActorCount - 1;
- bool _gameIsRunning;
- bool _windowIsActive;
- int _playerLosesControlCounter;
- const char *_languageCode;
+ bool _gameIsRunning;
+ bool _windowIsActive;
+ int _playerLosesControlCounter;
+ Common::String _languageCode;
ActorDialogueQueue *_actorDialogueQueue;
ScreenEffects *_screenEffects;
@@ -119,6 +123,7 @@ public:
Combat *_combat;
DialogueMenu *_dialogueMenu;
Elevator *_elevator;
+ EndCredits *_endCredits;
ESPER *_esper;
GameFlags *_gameFlags;
GameInfo *_gameInfo;
@@ -131,14 +136,17 @@ public:
Music *_music;
Obstacles *_obstacles;
Overlays *_overlays;
+ PoliceMaze *_policeMaze;
Scene *_scene;
SceneObjects *_sceneObjects;
SceneScript *_sceneScript;
+ Scores *_scores;
Settings *_settings;
SliceAnimations *_sliceAnimations;
SliceRenderer *_sliceRenderer;
Spinner *_spinner;
SuspectsDatabase *_suspectsDatabase;
+ Time *_gameTime;
View *_view;
VK *_vk;
Waypoints *_waypoints;
@@ -176,6 +184,8 @@ public:
int _gameAutoSave;
bool _gameIsLoading;
bool _sceneIsLoading;
+ bool _vqaIsPlaying;
+ bool _vqaStopIsRequested;
int _walkSoundId;
int _walkSoundVolume;
@@ -256,7 +266,12 @@ public:
void playerLosesControl();
void playerGainsControl();
- void ISez(const char *str);
+ bool saveGame(const Common::String &filename, byte *thumbnail);
+ void loadGame(const Common::String &filename, byte *thumbnail);
+ void newGame();
+ void autoSaveGame();
+
+ void ISez(const Common::String &str);
void blitToScreen(const Graphics::Surface &src);
diff --git a/engines/bladerunner/boundingbox.cpp b/engines/bladerunner/boundingbox.cpp
index a1c79a17e7..40b7d4285a 100644
--- a/engines/bladerunner/boundingbox.cpp
+++ b/engines/bladerunner/boundingbox.cpp
@@ -22,6 +22,8 @@
#include "bladerunner/boundingbox.h"
+#include "bladerunner/savefile.h"
+
namespace BladeRunner {
BoundingBox::BoundingBox(float x0, float y0, float z0, float x1, float y1, float z1) {
diff --git a/engines/bladerunner/boundingbox.h b/engines/bladerunner/boundingbox.h
index 11922cbd14..0206f0bbdc 100644
--- a/engines/bladerunner/boundingbox.h
+++ b/engines/bladerunner/boundingbox.h
@@ -27,6 +27,8 @@
namespace BladeRunner {
+class SaveFileWriteStream;
+
class BoundingBox {
Vector3 _vertices[2];
diff --git a/engines/bladerunner/chapters.cpp b/engines/bladerunner/chapters.cpp
index e7404c3c97..16d084b970 100644
--- a/engines/bladerunner/chapters.cpp
+++ b/engines/bladerunner/chapters.cpp
@@ -23,12 +23,15 @@
#include "bladerunner/chapters.h"
#include "bladerunner/bladerunner.h"
+#include "bladerunner/slice_animations.h"
namespace BladeRunner {
bool Chapters::enterChapter(int chapter) {
int id = _resourceIds[chapter];
+ _vm->_sliceAnimations->openFrames(id);
+
if (!_vm->openArchive("A.TLK"))
return false;
diff --git a/engines/bladerunner/combat.cpp b/engines/bladerunner/combat.cpp
index c371f7bedd..e1dc6b1044 100644
--- a/engines/bladerunner/combat.cpp
+++ b/engines/bladerunner/combat.cpp
@@ -22,10 +22,14 @@
#include "bladerunner/combat.h"
-
#include "bladerunner/actor.h"
+#include "bladerunner/audio_speech.h"
#include "bladerunner/bladerunner.h"
#include "bladerunner/game_constants.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/movement_track.h"
+#include "bladerunner/savefile.h"
+#include "bladerunner/scene_objects.h"
#include "bladerunner/settings.h"
namespace BladeRunner {
@@ -33,6 +37,9 @@ namespace BladeRunner {
Combat::Combat(BladeRunnerEngine *vm) {
_vm = vm;
+ _coverWaypoints.resize(_vm->_gameInfo->getCoverWaypointCount());
+ _fleeWaypoints.resize(_vm->_gameInfo->getFleeWaypointCount());
+
reset();
}
@@ -55,7 +62,7 @@ void Combat::reset() {
void Combat::activate() {
if(_enabled) {
- _vm->_playerActor->combatModeOn(-1, -1, -1, -1, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, _vm->_combat->_ammoDamage[_vm->_settings->getAmmoType()], 0, 0);
+ _vm->_playerActor->combatModeOn(-1, true, -1, -1, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, _vm->_combat->_ammoDamage[_vm->_settings->getAmmoType()], 0, false);
_active = true;
}
}
@@ -97,16 +104,127 @@ void Combat::setMissSound(int ammoType, int column, int soundId) {
_missSoundId[ammoType * 3 + column] = soundId;
}
-int Combat::getHitSound() {
+int Combat::getHitSound() const {
return _hitSoundId[3 * _vm->_settings->getAmmoType() + _vm->_rnd.getRandomNumber(2)];
}
-int Combat::getMissSound() {
+int Combat::getMissSound() const {
return _hitSoundId[3 * _vm->_settings->getAmmoType() + _vm->_rnd.getRandomNumber(2)];
}
void Combat::shoot(int actorId, Vector3 &to, int screenX) {
+ Actor *actor = _vm->_actors[actorId];
+
+ if (actor->isRetired()) {
+ return;
+ }
+
+ int sentenceId = -1;
+
+ /*
+ Distance from center as a percentage:
+ screenX - abs(right + left) / 2
+ distanceFromCenter = 100 * -------------------------------
+ abs(right - left) / 2
+ */
+ const Common::Rect &rect = actor->getScreenRectangle();
+ int distanceFromCenter = CLIP(100 * (screenX - abs((rect.right + rect.left) / 2)) / abs((rect.right - rect.left) / 2), 0, 100);
+
+ int damage = (100 - distanceFromCenter) * _ammoDamage[_vm->_settings->getAmmoType()] / 100;
+
+ int hp = MAX(actor->getCurrentHP() - damage, 0);
+
+ actor->setCurrentHP(hp);
+
+ bool setDamageAnimation = true;
+ if (actor->isWalking() == 1 && !actor->getFlagDamageAnimIfMoving()) {
+ setDamageAnimation = false;
+ }
+ if (actor->_movementTrack->hasNext() && !actor->_movementTrack->isPaused()) {
+ setDamageAnimation = false;
+ }
+ if (setDamageAnimation) {
+ if (actor->isWalking()) {
+ actor->stopWalking(false);
+ }
+ if (actor->getAnimationMode() != kAnimationModeHit && actor->getAnimationMode() != kAnimationModeCombatHit) {
+ actor->changeAnimationMode(kAnimationModeHit, false);
+ sentenceId = _vm->_rnd.getRandomNumberRng(0, 1) ? 9000 : 9005;
+ }
+ }
+
+ if (hp <= 0) {
+ actor->setTarget(false);
+ if (actor->inCombat()) {
+ actor->combatModeOff();
+ }
+ actor->stopWalking(false);
+ actor->changeAnimationMode(48, false);
+ actor->retire(true, 72, 36, kActorMcCoy);
+ actor->setAtXYZ(actor->getXYZ(), actor->getFacing(), true, false, true);
+ _vm->_sceneObjects->setRetired(actorId + kSceneObjectOffsetActors, true);
+ sentenceId = 9020;
+ }
+ if (sentenceId >= 0 && actor->inCombat()) {
+ _vm->_audioSpeech->playSpeechLine(actorId, sentenceId, 75, 0, 99);
+ }
+}
+
+int Combat::findFleeWaypoint(int setId, int enemyId, const Vector3& position) const {
+ float min = -1.0f;
+ int result = -1;
+ for (int i = 0; i < (int)_fleeWaypoints.size(); ++i) {
+ if (setId == _fleeWaypoints[i].setId) {
+ float dist = distance(position, _fleeWaypoints[i].position);
+ if (result == -1 || dist < min) {
+ result = i;
+ min = dist;
+ }
+ }
+ }
+ return result;
+}
+
+int Combat::findCoverWaypoint(int waypointType, int actorId, int enemyId) const {
+ Actor *actor = _vm->_actors[actorId];
+ Actor *enemy = _vm->_actors[enemyId];
+ int result = -1;
+ float min = -1.0f;
+ for (int i = 0; i < (int)_coverWaypoints.size(); ++i) {
+ if (waypointType == _coverWaypoints[i].type && actor->getSetId() == _coverWaypoints[i].setId) {
+ if (_vm->_sceneObjects->isObstacleBetween(_coverWaypoints[i].position, enemy->getXYZ(), enemyId)) {
+ float dist = distance(_coverWaypoints[i].position, actor->getXYZ());
+ if (result == -1 || dist < min) {
+ result = i;
+ min = dist;
+ }
+ }
+ }
+ }
+ return result;
+}
+
+void Combat::save(SaveFileWriteStream &f) {
+ f.writeBool(_active);
+ f.writeBool(_enabled);
+ for (int i = 0; i != kSoundCount; ++i) {
+ f.writeInt(_hitSoundId[i]);
+ }
+ for (int i = 0; i != kSoundCount; ++i) {
+ f.writeInt(_missSoundId[i]);
+ }
+}
+
+void Combat::load(SaveFileReadStream &f) {
+ _active = f.readBool();
+ _enabled = f.readBool();
+ for (int i = 0; i != kSoundCount; ++i) {
+ _hitSoundId[i] = f.readInt();
+ }
+ for (int i = 0; i != kSoundCount; ++i) {
+ _missSoundId[i] = f.readInt();
+ }
}
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/combat.h b/engines/bladerunner/combat.h
index 21989dac52..e0038d677e 100644
--- a/engines/bladerunner/combat.h
+++ b/engines/bladerunner/combat.h
@@ -23,11 +23,16 @@
#ifndef BLADERUNNER_COMBAT_H
#define BLADERUNNER_COMBAT_H
-namespace BladeRunner {
+#include "bladerunner/vector.h"
-class Vector3;
+#include "common/array.h"
+
+namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
+class Vector3;
class Combat {
static const int kSoundCount = 9;
@@ -36,14 +41,32 @@ class Combat {
bool _active;
bool _enabled;
- int _hitSoundId[kSoundCount];
- int _missSoundId[kSoundCount];
-// int _random1;
-// int _random2;
+ int _hitSoundId[kSoundCount];
+ int _missSoundId[kSoundCount];
+ // int _random1;
+ // int _random2;
public:
int _ammoDamage[3];
+ struct CoverWaypoint {
+ int type;
+ int setId;
+ int sceneId;
+ Vector3 position;
+ };
+
+ struct FleeWaypoint {
+ int type;
+ int setId;
+ int sceneId;
+ Vector3 position;
+ int field7;
+ };
+
+ Common::Array<CoverWaypoint> _coverWaypoints;
+ Common::Array<FleeWaypoint> _fleeWaypoints;
+
public:
Combat(BladeRunnerEngine *vm);
~Combat();
@@ -60,10 +83,16 @@ public:
void setHitSound(int ammoType, int column, int soundId);
void setMissSound(int ammoType, int column, int soundId);
- int getHitSound();
- int getMissSound();
+ int getHitSound() const;
+ int getMissSound() const;
void shoot(int actorId, Vector3 &to, int screenX);
+
+ int findFleeWaypoint(int setId, int enemyId, const Vector3& position) const;
+ int findCoverWaypoint(int waypointType, int actorId, int enemyId) const;
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/crimes_database.cpp b/engines/bladerunner/crimes_database.cpp
index febe408cd9..e9faa22b41 100644
--- a/engines/bladerunner/crimes_database.cpp
+++ b/engines/bladerunner/crimes_database.cpp
@@ -24,11 +24,12 @@
#include "bladerunner/bladerunner.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/text_resource.h"
namespace BladeRunner {
-CrimesDatabase::CrimesDatabase(BladeRunnerEngine *vm, const char *cluesResource, int crimeCount) {
+CrimesDatabase::CrimesDatabase(BladeRunnerEngine *vm, const Common::String &cluesResource, int crimeCount) {
_crimeCount = crimeCount;
_crimes.resize(_crimeCount);
@@ -70,4 +71,17 @@ const char *CrimesDatabase::getClueText(int clueId) const {
return _cluesText->getText(clueId);
}
+void CrimesDatabase::save(SaveFileWriteStream &f) {
+ for (int i = 0; i < _crimeCount; ++i) {
+ uint8 c = _crimes[i];
+ f.writeByte(c);
+ }
+}
+
+void CrimesDatabase::load(SaveFileReadStream &f) {
+ for (int i = 0; i < _crimeCount; ++i) {
+ _crimes[i] = f.readByte();
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/crimes_database.h b/engines/bladerunner/crimes_database.h
index 40e46cb356..9bb83f148f 100644
--- a/engines/bladerunner/crimes_database.h
+++ b/engines/bladerunner/crimes_database.h
@@ -28,6 +28,8 @@
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class TextResource;
class CrimesDatabase {
@@ -37,7 +39,7 @@ class CrimesDatabase {
TextResource *_cluesText;
public:
- CrimesDatabase(BladeRunnerEngine *vm, const char *cluesResource, int crimeCount);
+ CrimesDatabase(BladeRunnerEngine *vm, const Common::String &cluesResource, int crimeCount);
~CrimesDatabase();
void setCrime(int clueId, int crimeId);
@@ -47,6 +49,9 @@ public:
int getAssetType(int clueId) const;
const char *getClueText(int clueId) const;
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp
index 5539082187..0355f9d0f5 100644
--- a/engines/bladerunner/debugger.cpp
+++ b/engines/bladerunner/debugger.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/actor.h"
#include "bladerunner/bladerunner.h"
#include "bladerunner/boundingbox.h"
+#include "bladerunner/combat.h"
#include "bladerunner/font.h"
#include "bladerunner/game_constants.h"
#include "bladerunner/game_flags.h"
@@ -55,6 +56,8 @@ Debugger::Debugger(BladeRunnerEngine *vm) : GUI::Debugger() {
_vm = vm;
_viewSceneObjects = false;
+ _viewActorsOnly = false;
+ _viewObstacles = false;
_viewUI = false;
_viewZBuffer = false;
@@ -105,8 +108,8 @@ bool Debugger::cmdAnimation(int argc, const char **argv) {
bool Debugger::cmdDraw(int argc, const char **argv) {
if (argc != 2) {
- debugPrintf("Enables debug rendering of scene objects, ui elements, zbuffer or disables debug rendering.\n");
- debugPrintf("Usage: %s (obj | ui | zbuf | reset)\n", argv[0]);
+ debugPrintf("Enables debug rendering of scene objects, obstacles, ui elements, zbuffer or disables debug rendering.\n");
+ debugPrintf("Usage: %s (obj | actors | obstacles | ui | zbuf | reset)\n", argv[0]);
return true;
}
@@ -114,6 +117,13 @@ bool Debugger::cmdDraw(int argc, const char **argv) {
if (arg == "obj") {
_viewSceneObjects = !_viewSceneObjects;
debugPrintf("Drawing scene objects = %i\n", _viewSceneObjects);
+ } else if (arg == "actors") {
+ _viewSceneObjects = !_viewSceneObjects;
+ _viewActorsOnly = _viewSceneObjects;
+ debugPrintf("Drawing scene actors = %i\n", _viewSceneObjects);
+ } else if (arg == "obstacles") {
+ _viewObstacles = !_viewObstacles;
+ debugPrintf("Drawing obstacles = %i\n", _viewObstacles);
} else if (arg == "ui") {
_viewUI = !_viewUI;
debugPrintf("Drawing UI elements = %i\n", _viewUI);
@@ -256,7 +266,6 @@ bool Debugger::cmdPosition(int argc, const char **argv) {
debugPrintf("actorY(%i) = %f\n", actorId, actor->getY());
debugPrintf("actorZ(%i) = %f\n", actorId, actor->getZ());
debugPrintf("actorFacing(%i) = %i\n", actorId, actor->getFacing());
- return true;
}
if (argc == 3) {
@@ -271,11 +280,9 @@ bool Debugger::cmdPosition(int argc, const char **argv) {
return true;
}
- Vector3 position;
- otherActor->getXYZ(&position.x, &position.y, &position.z);
+ Vector3 position = otherActor->getXYZ();
actor->setSetId(otherActor->getSetId());
actor->setAtXYZ(position, otherActor->getFacing());
- return true;
}
if (argc == 7) {
@@ -285,7 +292,6 @@ bool Debugger::cmdPosition(int argc, const char **argv) {
actor->setSetId(setId);
actor->setAtXYZ(position, facing);
- return true;
}
return true;
}
@@ -386,19 +392,22 @@ void Debugger::drawSceneObjects() {
for (int i = 0; i < count; i++) {
SceneObjects::SceneObject *sceneObject = &_vm->_sceneObjects->_sceneObjects[_vm->_sceneObjects->_sceneObjectsSortedByDistance[i]];
- const BoundingBox *bbox = sceneObject->boundingBox;
+ const BoundingBox &bbox = sceneObject->boundingBox;
Vector3 a, b;
- bbox->getXYZ(&a.x, &a.y, &a.z, &b.x, &b.y, &b.z);
+ bbox.getXYZ(&a.x, &a.y, &a.z, &b.x, &b.y, &b.z);
Vector3 pos = _vm->_view->calculateScreenPosition(0.5 * (a + b));
int color;
+ if (_viewActorsOnly && sceneObject->type != kSceneObjectTypeActor)
+ continue;
+
switch (sceneObject->type) {
case kSceneObjectTypeUnknown:
break;
case kSceneObjectTypeActor:
color = 0x7C00; // 11111 00000 00000;
drawBBox(a, b, _vm->_view, &_vm->_surfaceFront, color);
- _vm->_surfaceFront.frameRect(*sceneObject->screenRectangle, color);
+ _vm->_surfaceFront.frameRect(sceneObject->screenRectangle, color);
_vm->_mainFont->drawColor(_vm->_textActorNames->getText(sceneObject->id - kSceneObjectOffsetActors), _vm->_surfaceFront, pos.x, pos.y, color);
break;
case kSceneObjectTypeItem:
@@ -406,7 +415,7 @@ void Debugger::drawSceneObjects() {
char itemText[40];
drawBBox(a, b, _vm->_view, &_vm->_surfaceFront, color);
sprintf(itemText, "item %i", sceneObject->id - kSceneObjectOffsetItems);
- _vm->_surfaceFront.frameRect(*sceneObject->screenRectangle, color);
+ _vm->_surfaceFront.frameRect(sceneObject->screenRectangle, color);
_vm->_mainFont->drawColor(itemText, _vm->_surfaceFront, pos.x, pos.y, color);
break;
case kSceneObjectTypeObject:
@@ -417,13 +426,16 @@ void Debugger::drawSceneObjects() {
color = 0x03E0; // 00000 11111 00000;
}
drawBBox(a, b, _vm->_view, &_vm->_surfaceFront, color);
- _vm->_surfaceFront.frameRect(*sceneObject->screenRectangle, color);
+ _vm->_surfaceFront.frameRect(sceneObject->screenRectangle, color);
_vm->_mainFont->drawColor(_vm->_scene->objectGetName(sceneObject->id - kSceneObjectOffsetObjects), _vm->_surfaceFront, pos.x, pos.y, color);
break;
}
}
}
+ if (_viewActorsOnly)
+ return;
+
//draw regions
for (int i = 0; i < 10; i++) {
Regions::Region *region = &_vm->_scene->_regions->_regions[i];
@@ -481,12 +493,13 @@ void Debugger::drawSceneObjects() {
}
//draw waypoints
- for(int i = 0; i < _vm->_waypoints->_count; i++) {
+ for (int i = 0; i < _vm->_waypoints->_count; i++) {
Waypoints::Waypoint *waypoint = &_vm->_waypoints->_waypoints[i];
- if(waypoint->setId != _vm->_scene->getSetId())
+ if(waypoint->setId != _vm->_scene->getSetId()) {
continue;
+ }
Vector3 pos = waypoint->position;
- Vector3 size = Vector3(5.0f, 5.0f, 5.0f);
+ Vector3 size = Vector3(3.0f, 3.0f, 3.0f);
int color = 0x7FFF; // 11111 11111 11111
drawBBox(pos - size, pos + size, _vm->_view, &_vm->_surfaceFront, color);
Vector3 spos = _vm->_view->calculateScreenPosition(pos);
@@ -495,6 +508,38 @@ void Debugger::drawSceneObjects() {
_vm->_mainFont->drawColor(waypointText, _vm->_surfaceFront, spos.x, spos.y, color);
}
+ //draw combat cover waypoints
+ for (int i = 0; i < (int)_vm->_combat->_coverWaypoints.size(); i++) {
+ Combat::CoverWaypoint *cover = &_vm->_combat->_coverWaypoints[i];
+ if (cover->setId != _vm->_scene->getSetId()) {
+ continue;
+ }
+ Vector3 pos = cover->position;
+ Vector3 size = Vector3(3.0f, 3.0f, 3.0f);
+ int color = 0x7C1F; // 11111 00000 11111
+ drawBBox(pos - size, pos + size, _vm->_view, &_vm->_surfaceFront, color);
+ Vector3 spos = _vm->_view->calculateScreenPosition(pos);
+ char coverText[40];
+ sprintf(coverText, "cover %i", i);
+ _vm->_mainFont->drawColor(coverText, _vm->_surfaceFront, spos.x, spos.y, color);
+ }
+
+ //draw combat flee waypoints
+ for (int i = 0; i < (int)_vm->_combat->_fleeWaypoints.size(); i++) {
+ Combat::FleeWaypoint *flee = &_vm->_combat->_fleeWaypoints[i];
+ if (flee->setId != _vm->_scene->getSetId()) {
+ continue;
+ }
+ Vector3 pos = flee->position;
+ Vector3 size = Vector3(3.0f, 3.0f, 3.0f);
+ int color = 0x03FF; // 00000 11111 11111
+ drawBBox(pos - size, pos + size, _vm->_view, &_vm->_surfaceFront, color);
+ Vector3 spos = _vm->_view->calculateScreenPosition(pos);
+ char fleeText[40];
+ sprintf(fleeText, "flee %i", i);
+ _vm->_mainFont->drawColor(fleeText, _vm->_surfaceFront, spos.x, spos.y, color);
+ }
+
#if 0
//draw aesc
for (uint i = 0; i < _screenEffects->_entries.size(); i++) {
diff --git a/engines/bladerunner/debugger.h b/engines/bladerunner/debugger.h
index bfe4e49b9b..64e312ae20 100644
--- a/engines/bladerunner/debugger.h
+++ b/engines/bladerunner/debugger.h
@@ -41,6 +41,8 @@ class Debugger : public GUI::Debugger{
public:
bool _viewSceneObjects;
+ bool _viewActorsOnly;
+ bool _viewObstacles;
bool _viewUI;
bool _viewZBuffer;
diff --git a/engines/bladerunner/detection_tables.h b/engines/bladerunner/detection_tables.h
index 52627890ea..3c509f4314 100644
--- a/engines/bladerunner/detection_tables.h
+++ b/engines/bladerunner/detection_tables.h
@@ -30,24 +30,18 @@ static const ADGameDescription gameDescriptions[] = {
{
"bladerunner",
0,
- {
- {"STARTUP.MIX", 0, "5643b53306ca7764cf1ec7b79c9630a3", 2312374},
- AD_LISTEND
- },
+ AD_ENTRY1s("STARTUP.MIX", "5643b53306ca7764cf1ec7b79c9630a3", 2312374),
Common::EN_ANY,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
GUIO0()
},
-
+
// BladeRunner (German)
{
"bladerunner",
0,
- {
- {"STARTUP.MIX", 0, "57d674ed860148a530b7f4957cbe65ec", 2314301},
- AD_LISTEND
- },
+ AD_ENTRY1s("STARTUP.MIX", "57d674ed860148a530b7f4957cbe65ec", 2314301),
Common::DE_DEU,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
@@ -58,10 +52,7 @@ static const ADGameDescription gameDescriptions[] = {
{
"bladerunner",
0,
- {
- {"STARTUP.MIX", 0, "39d1901df50935d58aee252707134952", 2314526},
- AD_LISTEND
- },
+ AD_ENTRY1s("STARTUP.MIX", "39d1901df50935d58aee252707134952", 2314526),
Common::FR_FRA,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
@@ -72,10 +63,7 @@ static const ADGameDescription gameDescriptions[] = {
{
"bladerunner",
0,
- {
- {"STARTUP.MIX", 0, "c7ceb9c691223d25e78516aa519ff504", 2314461},
- AD_LISTEND
- },
+ AD_ENTRY1s("STARTUP.MIX", "c7ceb9c691223d25e78516aa519ff504", 2314461),
Common::IT_ITA,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
@@ -86,10 +74,7 @@ static const ADGameDescription gameDescriptions[] = {
{
"bladerunner",
0,
- {
- {"STARTUP.MIX", 0, "c198b54a5366b88b1734bbca21d3b192", 2678672},
- AD_LISTEND
- },
+ AD_ENTRY1s("STARTUP.MIX", "c198b54a5366b88b1734bbca21d3b192", 2678672),
Common::RU_RUS,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
@@ -100,10 +85,7 @@ static const ADGameDescription gameDescriptions[] = {
{
"bladerunner",
0,
- {
- {"STARTUP.MIX", 0, "54cad53da9e4ae03a85648834ac6765d", 2312976},
- AD_LISTEND
- },
+ AD_ENTRY1s("STARTUP.MIX", "54cad53da9e4ae03a85648834ac6765d", 2312976),
Common::ES_ESP,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
diff --git a/engines/bladerunner/dialogue_menu.cpp b/engines/bladerunner/dialogue_menu.cpp
index 685c8459e0..d9a7c62866 100644
--- a/engines/bladerunner/dialogue_menu.cpp
+++ b/engines/bladerunner/dialogue_menu.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/bladerunner.h"
#include "bladerunner/font.h"
#include "bladerunner/mouse.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/settings.h"
#include "bladerunner/shape.h"
#include "bladerunner/text_resource.h"
@@ -158,7 +159,7 @@ int DialogueMenu::queryInput() {
if (_items[0].isDone) {
_selectedItemIndex = 1;
answer = _items[0].answerValue;
- } else if (_items[0].isDone) {
+ } else if (_items[1].isDone) {
_selectedItemIndex = 0;
answer = _items[1].answerValue;
}
@@ -364,6 +365,54 @@ bool DialogueMenu::waitingForInput() const {
return _waitingForInput;
}
+void DialogueMenu::save(SaveFileWriteStream &f) {
+ f.writeBool(_isVisible);
+ f.writeBool(_waitingForInput);
+ f.writeInt(_selectedItemIndex);
+ f.writeInt(_listSize);
+
+ f.writeInt(_neverRepeatListSize);
+ for (int i = 0; i < 100; ++i) {
+ f.writeInt(_neverRepeatValues[i]);
+ }
+ for (int i = 0; i < 100; ++i) {
+ f.writeBool(_neverRepeatWasSelected[i]);
+ }
+ for (int i = 0; i < 10; ++i) {
+ f.writeStringSz(_items[i].text, 50);
+ f.writeInt(_items[i].answerValue);
+ f.writeInt(_items[i].colorIntensity);
+ f.writeInt(_items[i].priorityPolite);
+ f.writeInt(_items[i].priorityNormal);
+ f.writeInt(_items[i].prioritySurly);
+ f.writeInt(_items[i].isDone);
+ }
+}
+
+void DialogueMenu::load(SaveFileReadStream &f) {
+ _isVisible = f.readBool();
+ _waitingForInput = f.readBool();
+ _selectedItemIndex = f.readInt();
+ _listSize = f.readInt();
+
+ _neverRepeatListSize = f.readInt();
+ for (int i = 0; i < 100; ++i) {
+ _neverRepeatValues[i] = f.readInt();
+ }
+ for (int i = 0; i < 100; ++i) {
+ _neverRepeatWasSelected[i] = f.readBool();
+ }
+ for (int i = 0; i < 10; ++i) {
+ _items[i].text = f.readStringSz(50);
+ _items[i].answerValue = f.readInt();
+ _items[i].colorIntensity = f.readInt();
+ _items[i].priorityPolite = f.readInt();
+ _items[i].priorityNormal = f.readInt();
+ _items[i].prioritySurly = f.readInt();
+ _items[i].isDone = f.readInt();
+ }
+}
+
void DialogueMenu::clear() {
_isVisible = false;
_waitingForInput = false;
diff --git a/engines/bladerunner/dialogue_menu.h b/engines/bladerunner/dialogue_menu.h
index 63e23d8ada..6dfd3efdc6 100644
--- a/engines/bladerunner/dialogue_menu.h
+++ b/engines/bladerunner/dialogue_menu.h
@@ -33,6 +33,8 @@
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class TextResource;
class DialogueMenu {
@@ -96,12 +98,14 @@ public:
void mouseUp();
bool waitingForInput() const;
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
private:
bool showAt(int x, int y);
int getAnswerIndex(int answer) const;
const char *getText(int id) const;
void calculatePosition(int unusedX = 0, int unusedY = 0);
-
void clear();
void reset();
diff --git a/engines/bladerunner/fog.cpp b/engines/bladerunner/fog.cpp
index fff27b0558..cb8235ba64 100644
--- a/engines/bladerunner/fog.cpp
+++ b/engines/bladerunner/fog.cpp
@@ -27,7 +27,6 @@
namespace BladeRunner {
Fog::Fog() {
- _name[0] = 0;
_frameCount = 0;
_animatedParameters = 0;
_fogDensity = 0.0f;
@@ -55,7 +54,9 @@ Fog::~Fog() {
int Fog::readCommon(Common::ReadStream *stream) {
int offset = stream->readUint32LE();
- stream->read(_name, 20);
+ char buf[20];
+ stream->read(buf, sizeof(buf));
+ _name = buf;
_fogColor.r = stream->readFloatLE();
_fogColor.g = stream->readFloatLE();
_fogColor.b = stream->readFloatLE();
@@ -65,7 +66,7 @@ int Fog::readCommon(Common::ReadStream *stream) {
void Fog::readAnimationData(Common::ReadStream *stream, int size) {
_animatedParameters = stream->readUint32LE();
-
+
int floatCount = size / 4;
_animationData = new float[floatCount];
for (int i = 0; i < floatCount; i++) {
diff --git a/engines/bladerunner/fog.h b/engines/bladerunner/fog.h
index 95ac550fd1..e952d24165 100644
--- a/engines/bladerunner/fog.h
+++ b/engines/bladerunner/fog.h
@@ -38,7 +38,8 @@ class Fog {
friend class SetEffects;
protected:
- char _name[20];
+ Common::String _name;
+
int _frameCount;
int _animatedParameters;
Matrix4x3 _matrix;
diff --git a/engines/bladerunner/font.cpp b/engines/bladerunner/font.cpp
index 5ae1c8eedc..d4b0e16515 100644
--- a/engines/bladerunner/font.cpp
+++ b/engines/bladerunner/font.cpp
@@ -120,6 +120,14 @@ void Font::drawColor(const Common::String &text, Graphics::Surface &surface, int
draw(text, surface, x, y);
}
+void Font::drawNumber(int num, Graphics::Surface &surface, int x, int y) const {
+ char buffer[20];
+
+ snprintf(buffer, 20, "%d", num);
+
+ draw(buffer, surface, x, y);
+}
+
int Font::getTextWidth(const Common::String &text) const {
const uint8 *character = (const uint8 *)text.c_str();
diff --git a/engines/bladerunner/font.h b/engines/bladerunner/font.h
index 9302520153..4af25468c6 100644
--- a/engines/bladerunner/font.h
+++ b/engines/bladerunner/font.h
@@ -69,6 +69,7 @@ public:
void draw(const Common::String &text, Graphics::Surface &surface, int x, int y) const;
void drawColor(const Common::String &text, Graphics::Surface &surface, int x, int y, uint16 color);
+ void drawNumber(int num, Graphics::Surface &surface, int x, int y) const;
int getTextWidth(const Common::String &text) const;
int getTextHeight(const Common::String &text) const;
diff --git a/engines/bladerunner/game_constants.h b/engines/bladerunner/game_constants.h
index af4728aaad..79381975f7 100644
--- a/engines/bladerunner/game_constants.h
+++ b/engines/bladerunner/game_constants.h
@@ -535,6 +535,8 @@ enum Flags {
enum Variables {
kVariableChapter = 1,
kVariableChinyen = 2,
+ kVariablePoliceMazeScore = 9,
+ kVariablePoliceMazePS10TargetCounter = 10,
kVariableGenericWalkerAModel = 32,
kVariableGenericWalkerBModel = 33,
kVariableGenericWalkerCModel = 34,
@@ -597,14 +599,17 @@ enum AnimationModes {
kAnimationModeTalk = 3,
kAnimationModeCombatIdle = 4,
kAnimationModeCombatAim = 5,
- kAnimationModeCombatShoot = 6,
+ kAnimationModeCombatAttack = 6,
kAnimationModeCombatWalk = 7,
kAnimationModeCombatRun = 8,
+ kAnimationModeHit = 21,
+ kAnimationModeCombatHit = 22,
kAnimationModeWalkUp = 44,
kAnimationModeWalkDown = 45,
kAnimationModeCombatWalkUp = 46,
kAnimationModeCombatWalkDown = 47,
- kAnimationModeDie = 48, // TODO: check
+ kAnimationModeDie = 48,
+ kAnimationModeCombatDie = 49,
kAnimationModeFeeding = 52,
kAnimationModeSit = 53, // TODO: check
kAnimationModeClimbUp = 64,
@@ -842,6 +847,15 @@ enum Sets {
};
enum GameItems {
+ kItemPoliceMazeTarget1 = 0,
+ kItemPoliceMazeTarget2 = 1,
+ kItemPoliceMazeTarget3 = 2,
+ kItemPoliceMazeTarget4 = 3,
+ kItemPoliceMazeTarget5 = 4,
+ kItemPoliceMazeTarget6 = 5,
+ kItemPoliceMazeTarget7 = 6,
+ kItemPoliceMazeTarget8 = 7,
+ kItemPoliceMazeTarget9 = 8,
kItemChromeDebris = 66,
kItemCandy = 79,
kItemChopstickWrapper = 82,
@@ -871,6 +885,48 @@ enum SceneObjectOffset {
kSceneObjectOffsetObjects = 198
};
+enum ActorCombatStates {
+ kActorCombatStateIdle = 0,
+ kActorCombatStateCover = 1,
+ kActorCombatStateApproachCloseAttack = 2,
+ kActorCombatStateUncover = 3,
+ kActorCombatStateAim = 4,
+ kActorCombatStateRangedAttack = 5,
+ kActorCombatStateCloseAttack = 6,
+ kActorCombatStateFlee = 7,
+ kActorCombatStateApproachRangedAttack = 8
+};
+
+enum PoliceMazeTrackInstruction {
+ kPMTIActivate = -26,
+ kPMTILeave = -25,
+ kPMTIShoot = -24,
+ kPMTIEnemyReset = -23,
+ kPMTIEnemySet = -22,
+ kPMTIFlagReset = -21,
+ kPMTIFlagSet = -20,
+ kPMTIVariableDec = -19,
+ kPMTIVariableInc = -18,
+ kPMTIVariableReset = -17,
+ kPMTIVariableSet = -16,
+ kPMTITargetSet = -15,
+ kPMTI12 = -14,
+ kPMTI13 = -13,
+ kPMTIPausedSet = -12,
+ kPMTIPausedReset = -11,
+ kPMTIPlaySound = -10,
+ kPMTIObstacleReset = -9,
+ kPMTIObstacleSet = -8,
+ kPMTIWaitRandom = -7,
+ kPMTIRotate = -6,
+ kPMTIFacing = -5,
+ kPMTIRestart = -4,
+ kPMTIWait = -3,
+ kPMTIMove = -2,
+ kPMTIPosition = -1,
+ kPMTI26 = 0
+};
+
} // End of namespace BladeRunner
#endif
diff --git a/engines/bladerunner/game_flags.cpp b/engines/bladerunner/game_flags.cpp
index 81fe6a0a4f..6fdcb89363 100644
--- a/engines/bladerunner/game_flags.cpp
+++ b/engines/bladerunner/game_flags.cpp
@@ -22,6 +22,8 @@
#include "bladerunner/game_flags.h"
+#include "bladerunner/savefile.h"
+
#include "common/debug.h"
namespace BladeRunner {
@@ -38,7 +40,7 @@ void GameFlags::setFlagCount(int count) {
assert(count > 0);
_flagCount = count;
- _flags = new uint32[count / 32 + 1];
+ _flags = new uint32[count / 32 + 1]();
for (int i = 0; i <= _flagCount; ++i)
reset(i);
@@ -71,4 +73,16 @@ bool GameFlags::query(int flag) const {
return !!(_flags[flag / 32] & (1 << (flag % 32)));
}
+void GameFlags::save(SaveFileWriteStream &f) {
+ for (int i = 0; i != _flagCount / 32 + 1; ++i) {
+ f.writeUint32LE(_flags[i]);
+ }
+}
+
+void GameFlags::load(SaveFileReadStream &f) {
+ for (int i = 0; i != _flagCount / 32 + 1; ++i) {
+ _flags[i] = f.readUint32LE();
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/game_flags.h b/engines/bladerunner/game_flags.h
index 83cbdbc086..837537f689 100644
--- a/engines/bladerunner/game_flags.h
+++ b/engines/bladerunner/game_flags.h
@@ -27,6 +27,9 @@
namespace BladeRunner {
+class SaveFileReadStream;
+class SaveFileWriteStream;
+
class GameFlags {
uint32 *_flags;
int _flagCount;
@@ -40,6 +43,9 @@ public:
void set(int flag);
void reset(int flag);
bool query(int flag) const;
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/game_info.cpp b/engines/bladerunner/game_info.cpp
index db664c0f2d..9dc261bc31 100644
--- a/engines/bladerunner/game_info.cpp
+++ b/engines/bladerunner/game_info.cpp
@@ -31,10 +31,6 @@ namespace BladeRunner {
GameInfo::GameInfo(BladeRunnerEngine *vm) {
_vm = vm;
- _sceneNames = nullptr;
- _sfxTracks = nullptr;
- _musicTracks = nullptr;
- _outtakes = nullptr;
_actorCount = 0;
_playerId = 0;
_flagCount = 0;
@@ -53,18 +49,12 @@ GameInfo::GameInfo(BladeRunnerEngine *vm) {
_fleeWaypointCount = 0;
}
-GameInfo::~GameInfo() {
- delete[] _sceneNames;
- delete[] _sfxTracks;
- delete[] _musicTracks;
- delete[] _outtakes;
-}
-
bool GameInfo::open(const Common::String &name) {
Common::SeekableReadStream *s = _vm->getResourceStream(name);
- if (!s)
+ if (!s) {
return false;
+ }
uint32 unk;
_actorCount = s->readUint32LE(); /* 00 */
@@ -88,25 +78,33 @@ bool GameInfo::open(const Common::String &name) {
(void)unk;
- _sceneNames = new char[_sceneNamesCount][5];
- for (uint32 i = 0; i != _sceneNamesCount; ++i)
- s->read(_sceneNames[i], 5);
+ char buf[9];
+
+ _sceneNames.resize(_sceneNamesCount);
+ for (uint32 i = 0; i != _sceneNamesCount; ++i) {
+ s->read(buf, 5);
+ _sceneNames[i] = buf;
+ }
- _sfxTracks = new char[_sfxTrackCount][13];
+ _sfxTracks.resize(_sfxTrackCount);
for (uint32 i = 0; i != _sfxTrackCount; ++i) {
- s->read(_sfxTracks[i], 9);
- strcat(_sfxTracks[i], ".AUD");
+ s->read(buf, 9);
+ _sfxTracks[i] = buf;
+ _sfxTracks[i] += ".AUD";
}
- _musicTracks = new char[_musicTrackCount][13];
+ _musicTracks.resize(_musicTrackCount);
for (uint32 i = 0; i != _musicTrackCount; ++i) {
- s->read(_musicTracks[i], 9);
- strcat(_musicTracks[i], ".AUD");
+ s->read(buf, 9);
+ _musicTracks[i] = buf;
+ _musicTracks[i] += ".AUD";
}
- _outtakes = new char[_outtakeCount][13];
- for (uint32 i = 0; i != _outtakeCount; ++i)
- s->read(_outtakes[i], 9);
+ _outtakes.resize(_outtakeCount);
+ for (uint32 i = 0; i != _outtakeCount; ++i) {
+ s->read(buf, 9);
+ _outtakes[i] = buf;
+ }
#if BLADERUNNER_DEBUG_CONSOLE
debug("\nScene names\n----------------");
@@ -135,34 +133,38 @@ bool GameInfo::open(const Common::String &name) {
return !err;
}
-const char *GameInfo::getSceneName(int i) const {
+const Common::String &GameInfo::getSceneName(int i) const {
if (i < 0 || i >= (int)_sceneNamesCount) {
warning("GameInfo::getSceneName: unknown id \"%i\"", i);
- return nullptr;
+ static Common::String str("UNKNOWN_SCENE");
+ return str;
}
return _sceneNames[i];
}
-const char *GameInfo::getSfxTrack(int i) const {
+const Common::String &GameInfo::getSfxTrack(int i) const {
if (i < 0 || i >= (int)_sfxTrackCount) {
warning("GameInfo::getSfxTrack: unknown id \"%i\"", i);
- return nullptr;
+ static Common::String str("UNKNOWN_SFX_TRACK");
+ return str;
}
return _sfxTracks[i];
}
-const char *GameInfo::getMusicTrack(int i) const {
+const Common::String &GameInfo::getMusicTrack(int i) const {
if (i < 0 || i >= (int)_musicTrackCount) {
warning("GameInfo::getMusicTrack: unknown id \"%i\"", i);
- return nullptr;
+ static Common::String str("UNKNOWN_MUSIC_TRACK");
+ return str;
}
return _musicTracks[i];
}
-const char *GameInfo::getOuttake(int i) const {
+const Common::String &GameInfo::getOuttake(int i) const {
if (i < 0 || i >= (int)_outtakeCount) {
warning("GameInfo::getOuttake: unknown id \"%i\"", i);
- return nullptr;
+ static Common::String str("UNKNOWN_OUTTAKE");
+ return str;
}
return _outtakes[i];
}
diff --git a/engines/bladerunner/game_info.h b/engines/bladerunner/game_info.h
index bc7fc1eeec..857efa9e0b 100644
--- a/engines/bladerunner/game_info.h
+++ b/engines/bladerunner/game_info.h
@@ -23,6 +23,7 @@
#ifndef BLADERUNNER_GAME_INFO_H
#define BLADERUNNER_GAME_INFO_H
+#include "common/array.h"
#include "common/str.h"
namespace BladeRunner {
@@ -49,14 +50,13 @@ class GameInfo {
uint32 _coverWaypointCount;
uint32 _fleeWaypointCount;
- char (*_sceneNames)[5];
- char (*_sfxTracks)[13];
- char (*_musicTracks)[13];
- char (*_outtakes)[13];
+ Common::Array<Common::String> _sceneNames;
+ Common::Array<Common::String> _sfxTracks;
+ Common::Array<Common::String> _musicTracks;
+ Common::Array<Common::String> _outtakes;
public:
GameInfo(BladeRunnerEngine *vm);
- ~GameInfo();
bool open(const Common::String &name);
@@ -77,10 +77,10 @@ public:
uint32 getCoverWaypointCount() const { return _coverWaypointCount; }
uint32 getFleeWaypointCount() const { return _fleeWaypointCount; }
- const char *getSceneName(int i) const;
- const char *getSfxTrack(int i) const;
- const char *getMusicTrack(int i) const;
- const char *getOuttake(int i) const;
+ const Common::String &getSceneName(int i) const;
+ const Common::String &getSfxTrack(int i) const;
+ const Common::String &getMusicTrack(int i) const;
+ const Common::String &getOuttake(int i) const;
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index af7b2ef4c2..2f82fc0b35 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -24,6 +24,7 @@
#include "bladerunner/bladerunner.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/slice_renderer.h"
#include "bladerunner/zbuffer.h"
@@ -73,13 +74,17 @@ bool Item::isTarget() const {
return _isTarget;
}
+bool Item::isPoliceMazeEnemy() const {
+ return _isPoliceMazeEnemy;
+}
+
bool Item::tick(Common::Rect *screenRect, bool special) {
if (!_isVisible) {
*screenRect = Common::Rect();
return false;
}
- bool isVisible = false;
+ bool isVisibleFlag = false;
Vector3 position(_position.x, -_position.z, _position.y);
int animationId = _animationId + (special ? 1 : 0);
@@ -88,7 +93,7 @@ bool Item::tick(Common::Rect *screenRect, bool special) {
if (!_screenRectangle.isEmpty()) {
*screenRect = _screenRectangle;
- isVisible = true;
+ isVisibleFlag = true;
} else {
*screenRect = Common::Rect();
}
@@ -120,7 +125,7 @@ bool Item::tick(Common::Rect *screenRect, bool special) {
}
}
- return isVisible;
+ return isVisibleFlag;
}
void Item::setXYZ(Vector3 position) {
@@ -134,7 +139,7 @@ void Item::setXYZ(Vector3 position) {
_depth = screenPosition.z * 25.5f;
}
-void Item::setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisible, bool isPoliceMazeEnemy) {
+void Item::setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag) {
_itemId = itemId;
_setId = setId;
_animationId = animationId;
@@ -143,8 +148,8 @@ void Item::setup(int itemId, int setId, int animationId, Vector3 position, int f
_width = width;
_height = height;
_isTarget = isTargetFlag;
- _isVisible = isVisible;
- _isPoliceMazeEnemy = isPoliceMazeEnemy;
+ _isVisible = isVisibleFlag;
+ _isPoliceMazeEnemy = isPoliceMazeEnemyFlag;
setXYZ(position);
_screenRectangle.bottom = -1;
_screenRectangle.right = -1;
@@ -152,6 +157,15 @@ void Item::setup(int itemId, int setId, int animationId, Vector3 position, int f
_screenRectangle.left = -1;
}
+void Item::spinInWorld() {
+ _isSpinning = true;
+ if (_vm->_rnd.getRandomNumberRng(1, 2) == 1) {
+ _facingChange = -340;
+ } else {
+ _facingChange = 340;
+ }
+}
+
bool Item::isUnderMouse(int mouseX, int mouseY) const {
return _isVisible
&& mouseX >= _screenRectangle.left - 10
@@ -160,4 +174,48 @@ bool Item::isUnderMouse(int mouseX, int mouseY) const {
&& mouseY <= _screenRectangle.bottom + 10;
}
+void Item::save(SaveFileWriteStream &f) {
+ f.writeInt(_setId);
+ f.writeInt(_itemId);
+ f.writeBoundingBox(_boundingBox);
+ f.writeRect(_screenRectangle);
+ f.writeInt(_animationId);
+ f.writeVector3(_position);
+ f.writeInt(_facing);
+ f.writeFloat(_angle);
+ f.writeInt(_width);
+ f.writeInt(_height);
+ f.writeInt(_screenX);
+ f.writeInt(_screenY);
+ f.writeFloat(_depth);
+ f.writeBool(_isTarget);
+ f.writeBool(_isSpinning);
+ f.writeInt(_facingChange);
+ f.writeFloat(0.0f); // _viewAngle
+ f.writeBool(_isVisible);
+ f.writeBool(_isPoliceMazeEnemy);
+}
+
+void Item::load(SaveFileReadStream &f) {
+ _setId = f.readInt();
+ _itemId = f.readInt();
+ _boundingBox = f.readBoundingBox();
+ _screenRectangle = f.readRect();
+ _animationId = f.readInt();
+ _position = f.readVector3();
+ _facing = f.readInt();
+ _angle = f.readFloat();
+ _width = f.readInt();
+ _height = f.readInt();
+ _screenX = f.readInt();
+ _screenY = f.readInt();
+ _depth = f.readFloat();
+ _isTarget = f.readBool();
+ _isSpinning = f.readBool();
+ _facingChange = f.readInt();
+ f.skip(4);
+ _isVisible = f.readBool();
+ _isPoliceMazeEnemy = f.readBool();
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h
index 89bec5590b..a6420d1857 100644
--- a/engines/bladerunner/item.h
+++ b/engines/bladerunner/item.h
@@ -32,6 +32,8 @@ namespace BladeRunner {
class BladeRunnerEngine;
class Items;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class Item {
friend class Items;
@@ -65,12 +67,28 @@ public:
void setXYZ(Vector3 position);
void getWidthHeight(int *width, int *height) const;
+ const BoundingBox &getBoundingBox() { return _boundingBox; }
+ const Common::Rect &getScreenRectangle() { return _screenRectangle; }
+ int getFacing() const { return _facing; }
+ void setFacing(int facing) { _facing = facing; }
+
+ void setIsTarget(bool val) { _isTarget = val; }
+
bool isTarget() const;
+ bool isSpinning() const { return _isSpinning; }
+ bool isVisible() const { return _isVisible; }
+ void setVisible(bool val) { _isVisible = val; }
+ bool isPoliceMazeEnemy() const;
+ void setPoliceMazeEnemy(bool val) { _isPoliceMazeEnemy = val; }
+ void spinInWorld();
bool tick(Common::Rect *screenRect, bool special);
- void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisible, bool isPoliceMazeEnemy);
+ void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag);
bool isUnderMouse(int mouseX, int mouseY) const;
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
};
}
diff --git a/engines/bladerunner/item_pickup.h b/engines/bladerunner/item_pickup.h
index 97d98ead36..0328bf428e 100644
--- a/engines/bladerunner/item_pickup.h
+++ b/engines/bladerunner/item_pickup.h
@@ -43,7 +43,7 @@ class ItemPickup {
int _timeLeft;
int _timeLast;
Common::Rect _screenRect;
-
+
public:
ItemPickup(BladeRunnerEngine *vm);
~ItemPickup();
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index 9d9efd6a38..a2cb9da194 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -23,6 +23,7 @@
#include "bladerunner/items.h"
#include "bladerunner/game_constants.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/scene.h"
#include "bladerunner/scene_objects.h"
#include "bladerunner/zbuffer.h"
@@ -46,6 +47,13 @@ void Items::getXYZ(int itemId, float *x, float *y, float *z) const {
_items[itemIndex]->getXYZ(x, y, z);
}
+void Items::setXYZ(int itemId, Vector3 position) {
+ int itemIndex = findItem(itemId);
+ assert(itemIndex != -1);
+
+ _items[itemIndex]->setXYZ(position);
+}
+
void Items::getWidthHeight(int itemId, int *width, int *height) const {
int itemIndex = findItem(itemId);
assert(itemIndex != -1);
@@ -67,7 +75,7 @@ void Items::tick() {
}
}
-bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisible, bool isPoliceMazeEnemy, bool addToSetFlag) {
+bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag, bool addToSetFlag) {
if (_items.size() >= 100) {
return false;
}
@@ -78,10 +86,10 @@ bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position,
}
Item *item = _items[itemIndex];
- item->setup(itemId, setId, animationId, position, facing, height, width, isTargetFlag, isVisible, isPoliceMazeEnemy);
+ item->setup(itemId, setId, animationId, position, facing, height, width, isTargetFlag, isVisibleFlag, isPoliceMazeEnemyFlag);
if (addToSetFlag && setId == _vm->_scene->getSetId()) {
- return _vm->_sceneObjects->addItem(itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, isTargetFlag, isVisible);
+ return _vm->_sceneObjects->addItem(itemId + kSceneObjectOffsetItems, item->_boundingBox, item->_screenRectangle, isTargetFlag, isVisibleFlag);
}
return true;
}
@@ -94,7 +102,7 @@ bool Items::addToSet(int setId) {
for (int i = 0; i < itemCount; i++) {
Item *item = _items[i];
if (item->_setId == setId) {
- _vm->_sceneObjects->addItem(item->_itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, item->isTarget(), item->_isVisible);
+ _vm->_sceneObjects->addItem(item->_itemId + kSceneObjectOffsetItems, item->_boundingBox, item->_screenRectangle, item->isTarget(), item->_isVisible);
}
}
return true;
@@ -118,6 +126,15 @@ bool Items::remove(int itemId) {
return true;
}
+void Items::setIsTarget(int itemId, bool val) {
+ int itemIndex = findItem(itemId);
+ if (itemIndex == -1) {
+ return;
+ }
+ _items[itemIndex]->setIsTarget(val);
+ _vm->_sceneObjects->setIsTarget(itemId + kSceneObjectOffsetItems, val);
+}
+
bool Items::isTarget(int itemId) const {
int itemIndex = findItem(itemId);
if (itemIndex == -1) {
@@ -126,6 +143,87 @@ bool Items::isTarget(int itemId) const {
return _items[itemIndex]->isTarget();
}
+bool Items::isSpinning(int itemId) const {
+ int itemIndex = findItem(itemId);
+ if (itemIndex == -1) {
+ return false;
+ }
+ return _items[itemIndex]->isSpinning();
+}
+
+bool Items::isVisible(int itemId) const {
+ int itemIndex = findItem(itemId);
+ if (itemIndex == -1) {
+ return false;
+ }
+ return _items[itemIndex]->isVisible();
+}
+
+bool Items::isPoliceMazeEnemy(int itemId) const {
+ int itemIndex = findItem(itemId);
+ if (itemIndex == -1) {
+ return false;
+ }
+ return _items[itemIndex]->isTarget();
+}
+
+void Items::setPoliceMazeEnemy(int itemId, bool val) {
+ int itemIndex = findItem(itemId);
+ if (itemIndex == -1) {
+ return;
+ }
+ _items[itemIndex]->setPoliceMazeEnemy(val);
+}
+
+void Items::setIsObstacle(int itemId, bool val) {
+ int itemIndex = findItem(itemId);
+ if (itemIndex == -1) {
+ return;
+ }
+ _items[itemIndex]->setVisible(val);
+ _vm->_sceneObjects->setIsClickable(itemId + kSceneObjectOffsetItems, val);
+}
+
+const BoundingBox &Items::getBoundingBox(int itemId) {
+ int itemIndex = findItem(itemId);
+ // if (itemIndex == -1) {
+ // return nullptr;
+ // }
+ return _items[itemIndex]->getBoundingBox();
+}
+
+const Common::Rect &Items::getScreenRectangle(int itemId) {
+ int itemIndex = findItem(itemId);
+ // if (itemIndex == -1) {
+ // return nullptr;
+ // }
+ return _items[itemIndex]->getScreenRectangle();
+}
+
+int Items::getFacing(int itemId) const {
+ int itemIndex = findItem(itemId);
+ if (itemIndex == -1) {
+ return 0;
+ }
+ return _items[itemIndex]->getFacing();
+}
+
+void Items::setFacing(int itemId, int facing) {
+ int itemIndex = findItem(itemId);
+ if (itemIndex == -1) {
+ return;
+ }
+ _items[itemIndex]->setFacing(facing);
+}
+
+void Items::spinInWorld(int itemId) {
+ int itemIndex = findItem(itemId);
+ if (itemIndex == -1) {
+ return;
+ }
+ _items[itemIndex]->spinInWorld();
+}
+
int Items::findTargetUnderMouse(int mouseX, int mouseY) const {
int setId = _vm->_scene->getSetId();
for (int i = 0 ; i < (int)_items.size(); ++i) {
@@ -145,4 +243,39 @@ int Items::findItem(int itemId) const {
return -1;
}
+void Items::save(SaveFileWriteStream &f) {
+ int size = (int)_items.size();
+
+ f.writeInt(size);
+ int i;
+ for (i = 0; i != size; ++i) {
+ _items[i]->save(f);
+ }
+
+ // Always write out 100 items
+ for (; i != 100; ++i) {
+ f.padBytes(0x174); // bbox + rect + 18 float fields
+ }
+}
+
+void Items::load(SaveFileReadStream &f) {
+ for (int i = _items.size() - 1; i >= 0; i--) {
+ delete _items.remove_at(i);
+ }
+ _items.resize(f.readInt());
+
+ int size = (int)_items.size();
+
+ int i;
+ for (i = 0; i != size; ++i) {
+ _items[i] = new Item(_vm);
+ _items[i]->load(f);
+ }
+
+ // Always read out 100 items
+ for (; i != 100; ++i) {
+ f.skip(0x174); // bbox + rect + 18 float fields
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h
index 1aac82e8da..ce29a77787 100644
--- a/engines/bladerunner/items.h
+++ b/engines/bladerunner/items.h
@@ -30,6 +30,9 @@
namespace BladeRunner {
+class SaveFileReadStream;
+class SaveFileWriteStream;
+
class Items {
BladeRunnerEngine *_vm;
@@ -40,16 +43,33 @@ public:
~Items();
void getXYZ(int itemId, float *x, float *y, float *z) const;
+ void setXYZ(int itemId, Vector3 position);
void getWidthHeight(int itemId, int *width, int *height) const;
void tick();
- bool addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisible, bool isPoliceMazeEnemy, bool addToSetFlag);
+ bool addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag, bool addToSetFlag);
bool addToSet(int itemId);
bool remove(int itemId);
+ void setIsTarget(int itemId, bool val);
bool isTarget(int itemId) const;
+ bool isSpinning(int itemId) const;
+ bool isPoliceMazeEnemy(int itemId) const;
+ void setPoliceMazeEnemy(int itemId, bool val);
+ void setIsObstacle(int itemId, bool val);
+ bool isVisible(int itemId) const;
int findTargetUnderMouse(int mouseX, int mouseY) const;
+ const BoundingBox &getBoundingBox(int itemId);
+ const Common::Rect &getScreenRectangle(int itemId);
+ int getFacing(int itemId) const;
+ void setFacing(int itemId, int facing);
+
+ void spinInWorld(int itemId);
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
private:
int findItem(int itemId) const;
};
diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp
index 615958281a..2231e0460e 100644
--- a/engines/bladerunner/light.cpp
+++ b/engines/bladerunner/light.cpp
@@ -69,7 +69,9 @@ void Light::read(Common::ReadStream *stream, int frameCount, int frame, int anim
int size = stream->readUint32LE();
size = size - 32;
- stream->read(_name, 20);
+ char buf[20];
+ stream->read(buf, sizeof(buf));
+ _name = buf;
_animatedParameters = stream->readUint32LE();
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
index 1ef9f3082c..31e40e0b45 100644
--- a/engines/bladerunner/light.h
+++ b/engines/bladerunner/light.h
@@ -42,7 +42,8 @@ class Light {
friend class SliceRenderer;
protected:
- char _name[20];
+ Common::String _name;
+
int _frameCount;
int _animated;
int _animatedParameters;
diff --git a/engines/bladerunner/matrix.h b/engines/bladerunner/matrix.h
index 5343eb6b8e..d5922b403f 100644
--- a/engines/bladerunner/matrix.h
+++ b/engines/bladerunner/matrix.h
@@ -57,8 +57,8 @@ inline Matrix3x2 operator*(const Matrix3x2 &a, const Matrix3x2 &b) {
inline Matrix3x2 operator+(const Matrix3x2 &a, Vector2 b) {
Matrix3x2 t(a);
- t(0,2) += b.x;
- t(1,2) += b.y;
+ t(0, 2) += b.x;
+ t(1, 2) += b.y;
return t;
}
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 67827030cd..b0bae4f7bd 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -41,6 +41,7 @@ MODULE_OBJS = \
outtake.o \
overlays.o \
regions.o \
+ savefile.o \
scene.o \
scene_objects.o \
screen_effects.o \
@@ -49,19 +50,24 @@ MODULE_OBJS = \
script/kia_script.o \
script/vk_script.o \
script/esper_script.o \
+ script/police_maze.o \
script/ai_script.o \
script/ai/answering_machine.o \
script/ai/baker.o \
script/ai/blimp_guy.o \
script/ai/bryant.o \
+ script/ai/bullet_bob.o \
script/ai/chew.o \
script/ai/clovis.o \
script/ai/crazylegs.o \
script/ai/dektora.o \
script/ai/desk_clerk.o \
script/ai/dispatcher.o \
+ script/ai/early_q.o \
script/ai/early_q_bartender.o \
script/ai/fish_dealer.o \
+ script/ai/free_slot_a.o \
+ script/ai/free_slot_b.o \
script/ai/gaff.o \
script/ai/general_doll.o \
script/ai/generic_walker_a.o \
@@ -71,6 +77,8 @@ MODULE_OBJS = \
script/ai/governor_kolvig.o \
script/ai/grigorian.o \
script/ai/guzza.o \
+ script/ai/hanoi.o \
+ script/ai/hasan.o \
script/ai/hawkers_barkeep.o \
script/ai/hawkers_parrot.o \
script/ai/holloway.o \
@@ -86,6 +94,7 @@ MODULE_OBJS = \
script/ai/leon.o \
script/ai/lockup_guard.o \
script/ai/lucy.o \
+ script/ai/luther.o \
script/ai/maggie.o \
script/ai/male_announcer.o \
script/ai/marcus.o \
@@ -97,11 +106,13 @@ MODULE_OBJS = \
script/ai/mutant2.o \
script/ai/mutant3.o \
script/ai/newscaster.o \
+ script/ai/officer_grayford.o \
script/ai/officer_leary.o \
script/ai/photographer.o \
script/ai/rachael.o \
script/ai/rajif.o \
script/ai/runciter.o \
+ script/ai/sadik.o \
script/ai/sebastian.o \
script/ai/sergeant_walls.o \
script/ai/shoeshine_man.o \
@@ -235,7 +246,9 @@ MODULE_OBJS = \
slice_renderer.o \
suspects_database.o \
text_resource.o \
+ time.o \
ui/elevator.o \
+ ui/end_credits.o \
ui/esper.o \
ui/kia.o \
ui/kia_log.o \
@@ -248,6 +261,7 @@ MODULE_OBJS = \
ui/kia_section_settings.o \
ui/kia_section_suspects.o \
ui/kia_shapes.o \
+ ui/scores.o \
ui/spinner.o \
ui/ui_check_box.o \
ui/ui_container.o \
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
index 7d67e98de5..093c73fcff 100644
--- a/engines/bladerunner/mouse.cpp
+++ b/engines/bladerunner/mouse.cpp
@@ -51,6 +51,11 @@ Mouse::Mouse(BladeRunnerEngine *vm) {
_disabledCounter = 0;
_lastFrameTime = 0;
_animCounter = 0;
+
+ _randomCountdownX = 0;
+ _randomCountdownY = 0;
+ _randomX = 0;
+ _randomY = 0;
}
Mouse::~Mouse() {
@@ -161,8 +166,55 @@ void Mouse::getXY(int *x, int *y) const {
*y = _y;
}
+void Mouse::setMouseJitterUp() {
+ switch (_vm->_settings->getDifficulty()) {
+ case 0:
+ _randomCountdownX = 2;
+ _randomX = _vm->_rnd.getRandomNumberRng(0, 6) - 3;
+ _randomY = _vm->_rnd.getRandomNumberRng(0, 10) - 20;
+ break;
+
+ case 1:
+ _randomCountdownX = 3;
+ _randomX = _vm->_rnd.getRandomNumberRng(0, 8) - 4;
+ _randomY = _vm->_rnd.getRandomNumberRng(0, 10) - 25;
+ break;
+
+ case 2:
+ _randomCountdownX = 4;
+ _randomX = _vm->_rnd.getRandomNumberRng(0, 10) - 5;
+ _randomY = _vm->_rnd.getRandomNumberRng(0, 10) - 30;
+ break;
+ }
+}
+
+void Mouse::setMouseJitterDown() {
+ switch (_vm->_settings->getDifficulty()) {
+ case 0:
+ _randomCountdownY = 2;
+ _randomX = _vm->_rnd.getRandomNumberRng(0, 6) - 3;
+ _randomY = _vm->_rnd.getRandomNumberRng(10, 20);
+ break;
+
+ case 1:
+ _randomCountdownY = 3;
+ _randomX = _vm->_rnd.getRandomNumberRng(0, 8) - 4;
+ _randomY = _vm->_rnd.getRandomNumberRng(15, 25);
+ break;
+
+ case 2:
+ _randomCountdownY = 4;
+ _randomX = _vm->_rnd.getRandomNumberRng(0, 10) - 5;
+ _randomY = _vm->_rnd.getRandomNumberRng(20, 30);
+ break;
+ }
+}
+
void Mouse::disable() {
++_disabledCounter;
+
+ _randomCountdownX = 0;
+ _randomCountdownY = 0;
}
void Mouse::enable() {
@@ -177,9 +229,24 @@ bool Mouse::isDisabled() const {
void Mouse::draw(Graphics::Surface &surface, int x, int y) {
if (_disabledCounter) {
+ _randomCountdownX = 0;
+ _randomCountdownY = 0;
return;
}
+ if (_randomCountdownX > 0) {
+ _randomCountdownX--;
+ x += _randomX;
+ y += _randomY;
+
+ if (!_randomCountdownX)
+ setMouseJitterDown();
+ } else if (_randomCountdownY > 0){
+ _randomCountdownY--;
+ x += _randomX;
+ y += _randomY;
+ }
+
_x = CLIP(x, 0, surface.w - 1);
_y = CLIP(y, 0, surface.h - 1);
diff --git a/engines/bladerunner/mouse.h b/engines/bladerunner/mouse.h
index 2f33d72583..31ba17a6c3 100644
--- a/engines/bladerunner/mouse.h
+++ b/engines/bladerunner/mouse.h
@@ -46,6 +46,11 @@ class Mouse {
int _lastFrameTime;
int _animCounter;
+ int _randomCountdownX;
+ int _randomCountdownY;
+ int _randomX;
+ int _randomY;
+
public:
Mouse(BladeRunnerEngine *vm);
~Mouse();
@@ -53,6 +58,8 @@ public:
void setCursor(int cursor);
void getXY(int *x, int *y) const;
+ void setMouseJitterUp();
+ void setMouseJitterDown();
void disable();
void enable();
diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp
index 47eb56a098..322d92ef31 100644
--- a/engines/bladerunner/movement_track.cpp
+++ b/engines/bladerunner/movement_track.cpp
@@ -22,6 +22,8 @@
#include "bladerunner/movement_track.h"
+#include "bladerunner/savefile.h"
+
namespace BladeRunner {
MovementTrack::MovementTrack() {
@@ -107,4 +109,32 @@ bool MovementTrack::next(int *waypointId, int *delay, int *angle, bool *run) {
}
}
+void MovementTrack::save(SaveFileWriteStream &f) {
+ f.writeInt(_currentIndex);
+ f.writeInt(_lastIndex);
+ f.writeBool(_hasNext);
+ f.writeBool(_paused);
+ for (int i = 0; i < kSize; ++i) {
+ Entry &e = _entries[i];
+ f.writeInt(e.waypointId);
+ f.writeInt(e.delay);
+ f.writeInt(e.angle);
+ f.writeBool(e.run);
+ }
+}
+
+void MovementTrack::load(SaveFileReadStream &f) {
+ _currentIndex = f.readInt();
+ _lastIndex = f.readInt();
+ _hasNext = f.readBool();
+ _paused = f.readBool();
+ for (int i = 0; i < kSize; ++i) {
+ Entry &e = _entries[i];
+ e.waypointId = f.readInt();
+ e.delay = f.readInt();
+ e.angle = f.readInt();
+ e.run = f.readBool();
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h
index cba9b690ff..2eab4cdedb 100644
--- a/engines/bladerunner/movement_track.h
+++ b/engines/bladerunner/movement_track.h
@@ -29,6 +29,8 @@ namespace BladeRunner {
class BladeRunnerEngine;
class BoundingBox;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class MovementTrack {
static const int kSize = 100;
@@ -59,7 +61,8 @@ public:
bool hasNext() const;
bool next(int *waypointId, int *delay, int *angle, bool *run);
- //int saveGame();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
private:
void reset();
diff --git a/engines/bladerunner/music.cpp b/engines/bladerunner/music.cpp
index 818d412ba9..05412dd8e0 100644
--- a/engines/bladerunner/music.cpp
+++ b/engines/bladerunner/music.cpp
@@ -26,6 +26,7 @@
#include "bladerunner/aud_stream.h"
#include "bladerunner/bladerunner.h"
#include "bladerunner/game_info.h"
+#include "bladerunner/savefile.h"
#include "common/timer.h"
@@ -167,6 +168,68 @@ void Music::playSample() {
}
}
+void Music::save(SaveFileWriteStream &f) {
+ f.writeBool(_isNextPresent);
+ f.writeBool(_isPlaying);
+ f.writeBool(_isPaused);
+ f.writeStringSz(_current.name, 13);
+ f.writeInt(_current.volume);
+ f.writeInt(_current.pan);
+ f.writeInt(_current.timeFadeIn);
+ f.writeInt(_current.timePlay);
+ f.writeInt(_current.loop);
+ f.writeInt(_current.timeFadeOut);
+ f.writeStringSz(_next.name, 13);
+ f.writeInt(_next.volume);
+ f.writeInt(_next.pan);
+ f.writeInt(_next.timeFadeIn);
+ f.writeInt(_next.timePlay);
+ f.writeInt(_next.loop);
+ f.writeInt(_next.timeFadeOut);
+}
+
+void Music::load(SaveFileReadStream &f) {
+ _isNextPresent = f.readBool();
+ _isPlaying = f.readBool();
+ _isPaused = f.readBool();
+ _current.name = f.readStringSz(13);
+ _current.volume = f.readInt();
+ _current.pan = f.readInt();
+ _current.timeFadeIn = f.readInt();
+ _current.timePlay = f.readInt();
+ _current.loop = f.readInt();
+ _current.timeFadeOut = f.readInt();
+ _next.name = f.readStringSz(13);
+ _next.volume = f.readInt();
+ _next.pan = f.readInt();
+ _next.timeFadeIn = f.readInt();
+ _next.timePlay = f.readInt();
+ _next.loop = f.readInt();
+ _next.timeFadeOut = f.readInt();
+
+ stop(2);
+ if (_isPlaying) {
+ if (_channel == -1) {
+ play(_current.name,
+ _current.volume,
+ _current.pan,
+ _current.timeFadeIn,
+ _current.timePlay,
+ _current.loop,
+ _current.timeFadeOut);
+ } else {
+ _isNextPresent = true;
+ _next.name = _current.name;
+ _next.volume = _current.volume;
+ _next.pan = _current.pan;
+ _next.timeFadeIn = _current.timeFadeIn;
+ _next.timePlay = _current.timePlay;
+ _next.loop = _current.loop;
+ _next.timeFadeOut = _current.timeFadeOut;
+ }
+ }
+}
+
void Music::adjustVolume(int volume, int delay) {
if (_channel >= 0) {
_vm->_audioMixer->adjustVolume(_channel, volume, delay);
diff --git a/engines/bladerunner/music.h b/engines/bladerunner/music.h
index de19942a20..b4dc284def 100644
--- a/engines/bladerunner/music.h
+++ b/engines/bladerunner/music.h
@@ -30,6 +30,8 @@ namespace BladeRunner {
class AudStream;
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class Music {
struct Track {
@@ -47,9 +49,9 @@ class Music {
Common::Mutex _mutex;
int _musicVolume;
int _channel;
- int _isNextPresent;
- int _isPlaying;
- int _isPaused;
+ bool _isNextPresent;
+ bool _isPlaying;
+ bool _isPaused;
Track _current;
Track _next;
byte *_data;
@@ -68,6 +70,9 @@ public:
int getVolume();
void playSample();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
private:
void adjustVolume(int volume, int delay);
void adjustPan(int pan, int delay);
diff --git a/engines/bladerunner/obstacles.cpp b/engines/bladerunner/obstacles.cpp
index 8061e782f2..06c19ad4af 100644
--- a/engines/bladerunner/obstacles.cpp
+++ b/engines/bladerunner/obstacles.cpp
@@ -24,23 +24,42 @@
#include "bladerunner/bladerunner.h"
+#include "bladerunner/savefile.h"
+#include "bladerunner/scene.h" // for debug
+#include "bladerunner/view.h"
+
+#include "common/debug.h"
+
+#define WITHIN_TOLERANCE(a, b) (((a) - 0.009) < (b) && ((a) + 0.009) > (b))
+
namespace BladeRunner {
Obstacles::Obstacles(BladeRunnerEngine *vm) {
_vm = vm;
- _vertices = new Vector2[150];
+ _polygons = new Polygon[kPolygonCount];
+ _polygonsBackup = new Polygon[kPolygonCount];
+ _vertices = new Vector2[kVertexCount];
clear();
}
Obstacles::~Obstacles() {
+ clear();
+
+ delete[] _polygons;
+ _polygons = nullptr;
+
+ delete[] _polygonsBackup;
+ _polygonsBackup = nullptr;
+
delete[] _vertices;
+ _vertices = nullptr;
}
void Obstacles::clear() {
for (int i = 0; i < kPolygonCount; i++) {
_polygons[i].isPresent = false;
_polygons[i].verticeCount = 0;
- for (int j = 0; j < kVertexCount; j++) {
+ for (int j = 0; j < kPolygonVertexCount; j++) {
_polygons[i].vertices[j].x = 0.0f;
_polygons[i].vertices[j].y = 0.0f;
}
@@ -50,7 +69,250 @@ void Obstacles::clear() {
_count = 0;
}
-void Obstacles::add(float x0, float z0, float x1, float z1) {
+#define IN_RANGE(v, start, end) ((start) <= (v) && (v) <= (end))
+
+/*
+ * This function is limited to finding intersections between
+ * horizontal and vertical lines!
+ *
+ * The original implementation is more general but obstacle
+ * polygons only consists of horizontal and vertical lines,
+ * and this is more numerically stable.
+ */
+bool Obstacles::lineLineIntersection(LineSegment a, LineSegment b, Vector2 *intersection) {
+ assert(a.start.x == a.end.x || a.start.y == a.end.y);
+ assert(b.start.x == b.end.x || b.start.y == b.end.y);
+
+ if (a.start.x > a.end.x) SWAP(a.start.x, a.end.x);
+ if (a.start.y > a.end.y) SWAP(a.start.y, a.end.y);
+ if (b.start.x > b.end.x) SWAP(b.start.x, b.end.x);
+ if (b.start.y > b.end.y) SWAP(b.start.y, b.end.y);
+
+ if (a.start.x == a.end.x && b.start.y == b.end.y && IN_RANGE(a.start.x, b.start.x, b.end.x) && IN_RANGE(b.start.y, a.start.y, a.end.y)) {
+ // A is vertical, B is horizontal
+ *intersection = Vector2(a.start.x, b.start.y);
+ return true;
+ }
+
+ if (a.start.y == a.end.y && b.start.x == b.end.x && IN_RANGE(a.start.y, b.start.y, b.end.y) && IN_RANGE(b.start.x, a.start.x, a.end.x)) {
+ // A is horizontal, B is vertical
+ *intersection = Vector2(b.start.x, a.start.y);
+ return true;
+ }
+
+ return false;
+}
+
+bool Obstacles::linePolygonIntersection(LineSegment lineA, VertexType lineAType, Polygon *polyB, Vector2 *intersectionPoint, int *intersectionIndex) {
+ bool hasIntersection = false;
+ float nearestIntersectionDistance = 0.0f;
+
+ for (int i = 0; i != polyB->verticeCount; ++i) {
+ LineSegment lineB;
+ lineB.start = polyB->vertices[i];
+ lineB.end = polyB->vertices[(i+1) % polyB->verticeCount];
+
+ VertexType lineBType = polyB->vertexType[i];
+
+ Vector2 newIntersectionPoint;
+
+ if (lineLineIntersection(lineA, lineB, &newIntersectionPoint)) {
+ if ((lineAType == TOP_RIGHT && lineBType == TOP_LEFT)
+ || (lineAType == BOTTOM_RIGHT && lineBType == TOP_RIGHT)
+ || (lineAType == BOTTOM_LEFT && lineBType == BOTTOM_RIGHT)
+ || (lineAType == TOP_LEFT && lineBType == BOTTOM_LEFT)
+ ) {
+ if (!WITHIN_TOLERANCE(lineB.end.x, intersectionPoint->x)
+ || !WITHIN_TOLERANCE(lineB.end.y, intersectionPoint->y)) {
+ if (newIntersectionPoint != *intersectionPoint) {
+ float newIntersectionDistance = getLength(lineA.start.x, lineA.start.y, newIntersectionPoint.x, newIntersectionPoint.y);
+ if (!hasIntersection || newIntersectionDistance < nearestIntersectionDistance) {
+ hasIntersection = true;
+ nearestIntersectionDistance = newIntersectionDistance;
+ *intersectionPoint = newIntersectionPoint;
+ *intersectionIndex = i;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return hasIntersection;
+}
+
+/*
+ * Polygons vertices are defined in clock-wise order
+ * starting at the top-most, right-most corner.
+ *
+ * When merging two polygons, we start at the top-most, right-most vertex.
+ * The polygon with this vertex starts is the primary polygon.
+ * We follow the edges until we find an intersection with the secondary polygon,
+ * in which case we switch primary and secondary and continue following the new edges.
+ *
+ * Luckily the first two polygons added in RC01 (A, then B) are laid as as below,
+ * making an ideal test case.
+ *
+ * Merge order: (B0,B1) (B1,B2) (B2,J) (J,A2) (A2,A3) (A3,A0) (A0,I) (I,B0)
+ *
+ * 0,0 ---> x
+ * |
+ * | primary
+ * | B 0 ----- 1
+ * | | |
+ * | A 0 --I-- 1 |
+ * | | | | |
+ * | | 3 --J-- 2
+ * | | |
+ * | 3 ----- 2
+ * | secondary
+ * v y
+ */
+
+bool Obstacles::mergePolygons(Polygon &polyA, Polygon &polyB) {
+ bool flagDidMergePolygons = false;
+ Polygon polyMerged;
+ polyMerged.rect = merge(polyA.rect, polyB.rect);
+
+ Polygon *polyPrimary, *polySecondary;
+ if (polyA.rect.y0 < polyB.rect.y0 || (polyA.rect.y0 == polyB.rect.y0 && polyA.rect.x0 < polyB.rect.x0)) {
+ polyPrimary = &polyA;
+ polySecondary = &polyB;
+ } else {
+ polyPrimary = &polyB;
+ polySecondary = &polyA;
+ }
+
+ Vector2 intersectionPoint;
+ LineSegment polyLine;
+ bool flagAddVertexToVertexList = true;
+ bool flagDidFindIntersection = false;
+ int vertIndex = 0;
+
+ Polygon *startingPolygon = polyPrimary;
+ int flagDone = false;
+ while (!flagDone) {
+ VertexType polyPrimaryType;
+
+ polyLine.start = flagDidFindIntersection ? intersectionPoint : polyPrimary->vertices[vertIndex];
+ polyLine.end = polyPrimary->vertices[(vertIndex + 1) % polyPrimary->verticeCount];
+
+ // TODO(madmoose): How does this work when adding a new intersection point?
+ polyPrimaryType = polyPrimary->vertexType[vertIndex];
+
+ if (flagAddVertexToVertexList) {
+ assert(polyMerged.verticeCount < kPolygonVertexCount);
+ polyMerged.vertices[polyMerged.verticeCount] = polyLine.start;
+ polyMerged.vertexType[polyMerged.verticeCount] = polyPrimaryType;
+ polyMerged.verticeCount++;
+ }
+
+ flagAddVertexToVertexList = true;
+ int polySecondaryIntersectionIndex = -1;
+
+ if (linePolygonIntersection(polyLine, polyPrimaryType, polySecondary, &intersectionPoint, &polySecondaryIntersectionIndex)) {
+ if (WITHIN_TOLERANCE(intersectionPoint.x, polyLine.start.x) && WITHIN_TOLERANCE(intersectionPoint.y, polyLine.start.y)) {
+ warning("Set: %d Scene: %d", _vm->_scene->getSetId(), _vm->_scene->getSceneId());
+ assert(0 && "Report instances of this to madmoose!");
+ flagAddVertexToVertexList = false;
+ polyMerged.verticeCount--; // TODO(madmoose): How would this work?
+ } else {
+ // Obstacles::nop
+ }
+ vertIndex = polySecondaryIntersectionIndex;
+ flagDidFindIntersection = true;
+
+ SWAP(polyPrimary, polySecondary);
+
+ flagDidMergePolygons = true;
+ } else {
+ vertIndex = (vertIndex + 1) % polyPrimary->verticeCount;
+ flagDidFindIntersection = false;
+ }
+ if (polyPrimary->vertices[vertIndex] == startingPolygon->vertices[0]) {
+ flagDone = true;
+ }
+ }
+
+ if (flagDidMergePolygons) {
+ *startingPolygon = polyMerged;
+ startingPolygon->isPresent = true;
+ if (startingPolygon == &polyA) {
+ polyB.isPresent = false;
+ } else {
+ polyA.isPresent = false;
+ }
+ }
+
+ return flagDidMergePolygons;
+}
+
+void Obstacles::add(Rect rect) {
+ int polygonIndex = findEmptyPolygon();
+ if (polygonIndex < 0) {
+ return;
+ }
+
+ rect.expand(12.0f);
+ rect.trunc_2_decimals();
+
+ Polygon &poly = _polygons[polygonIndex];
+
+ poly.rect = rect;
+
+ poly.vertices[0] = Vector2(rect.x0, rect.y0);
+ poly.vertexType[0] = TOP_LEFT;
+
+ poly.vertices[1] = Vector2(rect.x1, rect.y0);
+ poly.vertexType[1] = TOP_RIGHT;
+
+ poly.vertices[2] = Vector2(rect.x1, rect.y1);
+ poly.vertexType[2] = BOTTOM_RIGHT;
+
+ poly.vertices[3] = Vector2(rect.x0, rect.y1);
+ poly.vertexType[3] = BOTTOM_LEFT;
+
+ poly.isPresent = true;
+ poly.verticeCount = 4;
+
+restart:
+ for (int i = 0; i < kPolygonCount; ++i) {
+ Polygon &polyA = _polygons[i];
+ if (!polyA.isPresent) {
+ continue;
+ }
+
+ for (int j = i+1; j < kPolygonCount; ++j) {
+ Polygon &polyB = _polygons[j];
+ if (!polyB.isPresent) {
+ continue;
+ }
+
+ if (!overlaps(polyA.rect, polyB.rect)) {
+ continue;
+ }
+
+ if (mergePolygons(polyA, polyB)) {
+ goto restart;
+ }
+ }
+ }
+}
+
+int Obstacles::findEmptyPolygon() const {
+ for (int i = 0; i < kPolygonCount; i++) {
+ if (!_polygons[i].isPresent) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+float Obstacles::getLength(float x0, float z0, float x1, float z1) {
+ if (x0 == x1) {
+ return fabs(z1 - z0);
+ }
+ return fabs(x1 - x0);
}
bool Obstacles::find(const Vector3 &from, const Vector3 &to, Vector3 *next) const {
@@ -59,10 +321,242 @@ bool Obstacles::find(const Vector3 &from, const Vector3 &to, Vector3 *next) cons
return true;
}
+bool Obstacles::findIntersectionNearest(int polygonIndex, Vector2 from, Vector2 to,
+ int *outVertexIndex, float *outDistance, Vector2 *out) const
+{
+ float minDistance = 0.0f;
+ Vector2 minIntersection;
+ int minVertexIndex = -1;
+
+ bool hasDistance = false;
+
+ for (int i = 0; i < _polygons[polygonIndex].verticeCount; ++i) {
+ int nextIndex = (i + 1) % _polygons[polygonIndex].verticeCount;
+ Vector2 *vertices = _polygons[polygonIndex].vertices;
+ Vector2 intersection;
+ bool intersects = lineIntersection(from, to, vertices[i], vertices[nextIndex], &intersection);
+ if (intersects) {
+ float distance2 = distance(from, intersection);
+ if (!hasDistance || distance2 < minDistance) {
+ minDistance = distance2;
+ minIntersection = intersection;
+ minVertexIndex = i;
+ hasDistance = true;
+ }
+ }
+ }
+
+ *outDistance = minDistance;
+ *outVertexIndex = minVertexIndex;
+ *out = minIntersection;
+
+ return minVertexIndex != -1;
+}
+
+bool Obstacles::findIntersectionFarthest(int polygonIndex, Vector2 from, Vector2 to,
+ int *outVertexIndex, float *outDistance, Vector2 *out) const
+{
+ float maxDistance = 0.0f;
+ Vector2 maxIntersection;
+ int maxVertexIndex = -1;
+
+ bool hasDistance = false;
+
+ for (int i = 0; i < _polygons[polygonIndex].verticeCount; ++i) {
+ int nextIndex = (i + 1) % _polygons[polygonIndex].verticeCount;
+ Vector2 *vertices = _polygons[polygonIndex].vertices;
+ Vector2 intersection;
+ bool intersects = lineIntersection(from, to, vertices[i], vertices[nextIndex], &intersection);
+ if (intersects) {
+ float distance2 = distance(from, intersection);
+ if (!hasDistance || distance2 > maxDistance) {
+ maxDistance = distance2;
+ maxIntersection = intersection;
+ maxVertexIndex = i;
+ hasDistance = true;
+ }
+ }
+ }
+
+ *outDistance = maxDistance;
+ *outVertexIndex = maxVertexIndex;
+ *out = maxIntersection;
+
+ return maxVertexIndex != -1;
+}
+
+bool Obstacles::findPolygonVerticeByXZ(int *polygonIndex, int *verticeIndex, int *verticeCount, float x, float z) const {
+ *polygonIndex = -1;
+ *verticeIndex = -1;
+ *verticeCount = -1;
+
+ for (int i = 0; i != kPolygonCount; ++i) {
+ if (!_polygons[i].isPresent || _polygons[i].verticeCount == 0) {
+ continue;
+ }
+
+ for (int j = 0; j != kPolygonVertexCount; ++j) {
+ if (_polygons[i].vertices[j].x == x && _polygons[i].vertices[j].y == z) {
+ *polygonIndex = i;
+ *verticeIndex = j;
+ *verticeCount = _polygons[i].verticeCount;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Obstacles::findPolygonVerticeByXZWithinTolerance(float x, float z, int *polygonIndex, int *verticeIndex) const {
+ *polygonIndex = -1;
+ *verticeIndex = -1;
+
+ for (int i = 0; i != kPolygonCount; ++i) {
+ if (!_polygons[i].isPresent || _polygons[i].verticeCount == 0) {
+ continue;
+ }
+
+ for (int j = 0; j != kPolygonVertexCount; ++j) {
+ if (WITHIN_TOLERANCE(_polygons[i].vertices[j].x, x)) {
+ if (WITHIN_TOLERANCE(_polygons[i].vertices[j].y, z)) {
+ *polygonIndex = i;
+ *verticeIndex = j;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+void Obstacles::clearVertices() {
+ _verticeCount = 0;
+}
+
+void Obstacles::copyVerticesReverse() {
+
+}
+
+void Obstacles::copyVertices() {
+
+}
+
void Obstacles::backup() {
+ for (int i = 0; i != kPolygonCount; ++i) {
+ _polygonsBackup[i].isPresent = false;
+ }
+
+ int count = 0;
+ for (int i = 0; i != kPolygonCount; ++i) {
+ if (_polygons[i].isPresent) {
+ _polygonsBackup[count] = _polygons[i];
+ ++count;
+ }
+ }
+
+ for (int i = 0; i != kPolygonCount; ++i) {
+ _polygons[i] = _polygonsBackup[count];
+ }
+
+ _count = count;
+ _backup = true;
+}
+
+void Obstacles::restore() {
+ for (int i = 0; i != kPolygonCount; ++i) {
+ _polygons[i].isPresent = false;
+ }
+ for (int i = 0; i != kPolygonCount; ++i) {
+ _polygons[i] = _polygonsBackup[i];
+ }
}
-void Obstacles::restore() {}
+void Obstacles::save(SaveFileWriteStream &f) {
+ f.writeBool(_backup);
+ f.writeInt(_count);
+ for (int i = 0; i < _count; ++i) {
+ Polygon &p = _polygonsBackup[i];
+ f.writeBool(p.isPresent);
+ f.writeInt(p.verticeCount);
+ f.writeFloat(p.rect.x0);
+ f.writeFloat(p.rect.y0);
+ f.writeFloat(p.rect.x1);
+ f.writeFloat(p.rect.y1);
+ for (int j = 0; j < kPolygonVertexCount; ++j) {
+ f.writeVector2(p.vertices[j]);
+ }
+ for (int j = 0; j < kPolygonVertexCount; ++j) {
+ f.writeInt(p.vertexType[j]);
+ }
+ }
+ for (int i = 0; i < kVertexCount; ++i) {
+ f.writeVector2(_vertices[i]);
+ }
+ f.writeInt(_verticeCount);
+}
+void Obstacles::load(SaveFileReadStream &f) {
+ for (int i = 0; i < kPolygonCount; ++i) {
+ _polygons[i].isPresent = false;
+ _polygons[i].verticeCount = 0;
+ _polygonsBackup[i].isPresent = false;
+ _polygonsBackup[i].verticeCount = 0;
+ }
+
+ _backup = f.readBool();
+ _count = f.readInt();
+ for (int i = 0; i < _count; ++i) {
+ Polygon &p = _polygonsBackup[i];
+ p.isPresent = f.readBool();
+ p.verticeCount = f.readInt();
+ p.rect.x0 = f.readFloat();
+ p.rect.y0 = f.readFloat();
+ p.rect.x1 = f.readFloat();
+ p.rect.y1 = f.readFloat();
+ for (int j = 0; j < kPolygonVertexCount; ++j) {
+ p.vertices[j] = f.readVector2();
+ }
+ for (int j = 0; j < kPolygonVertexCount; ++j) {
+ p.vertexType[j] = (VertexType)f.readInt();
+ }
+ }
+
+ for (int i = 0; i < kPolygonCount; ++i) {
+ _polygons[i] = _polygonsBackup[i];
+ }
+
+ for (int i = 0; i < kVertexCount; ++i) {
+ _vertices[i] = f.readVector2();
+ }
+ _verticeCount = f.readInt();
+}
+
+void Obstacles::draw() {
+ for (int i = 0; i != kPolygonCount; ++i) {
+ if (!_polygons[i].isPresent) {
+ continue;
+ }
+
+ Vector3 p0 = _vm->_view->calculateScreenPosition(Vector3(
+ _polygons[i].vertices[_polygons[i].verticeCount - 1].x,
+ 0,
+ _polygons[i].vertices[_polygons[i].verticeCount - 1].y
+ ));
+
+ for (int j = 0; j != _polygons[i].verticeCount; ++j) {
+ Vector3 p1 = _vm->_view->calculateScreenPosition(Vector3(
+ _polygons[i].vertices[j].x,
+ 0.0f,
+ _polygons[i].vertices[j].y
+ ));
+
+ _vm->_surfaceFront.drawLine(p0.x, p0.y, p1.x, p1.y, 0x7FE0);
+
+ p0 = p1;
+ }
+ }
+}
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/obstacles.h b/engines/bladerunner/obstacles.h
index c2c84c3bfa..25124904ef 100644
--- a/engines/bladerunner/obstacles.h
+++ b/engines/bladerunner/obstacles.h
@@ -23,45 +23,87 @@
#ifndef BLADERUNNER_OBSTACLES_H
#define BLADERUNNER_OBSTACLES_H
+#include "bladerunner/rect.h"
#include "bladerunner/vector.h"
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class Obstacles {
- static const int kPolygonCount = 50;
- static const int kVertexCount = 160;
+ static const int kVertexCount = 150;
+ static const int kPolygonCount = 50;
+ static const int kPolygonVertexCount = 160;
+
+ enum VertexType {
+ BOTTOM_LEFT,
+ TOP_LEFT,
+ TOP_RIGHT,
+ BOTTOM_RIGHT
+ };
+
+ struct LineSegment {
+ Vector2 start;
+ Vector2 end;
+ };
struct Polygon {
- bool isPresent;
- int verticeCount;
- float left;
- float bottom;
- float right;
- float top;
- Vector2 vertices[kVertexCount];
- int vertexType[kVertexCount];
+ bool isPresent;
+ int verticeCount;
+ Rect rect;
+ Vector2 vertices[kPolygonVertexCount];
+ VertexType vertexType[kPolygonVertexCount];
+
+ Polygon() : isPresent(false), verticeCount(0)
+ {}
};
BladeRunnerEngine *_vm;
- Polygon _polygons[kPolygonCount];
- Polygon _polygonsBackup[kPolygonCount];
+ Polygon *_polygons;
+ Polygon *_polygonsBackup;
Vector2 *_vertices;
int _verticeCount;
int _count;
bool _backup;
+ static bool lineLineIntersection(LineSegment a, LineSegment b, Vector2 *intersectionPoint);
+ static bool linePolygonIntersection(LineSegment lineA, VertexType lineAType, Polygon *polyB, Vector2 *intersectionPoint, int *intersectionIndex);
+
+ bool mergePolygons(Polygon &polyA, Polygon &PolyB);
+
public:
Obstacles(BladeRunnerEngine *vm);
~Obstacles();
void clear();
- void add(float x0, float z0, float x1, float z1);
+ void add(Rect rect);
+ void add(float x0, float z0, float x1, float z1) { add(Rect(x0, z0, x1, z1)); }
+ int findEmptyPolygon() const;
+ static float getLength(float x0, float z0, float x1, float z1);
bool find(const Vector3 &from, const Vector3 &to, Vector3 *next) const;
+
+ bool findIntersectionNearest(int polygonIndex, Vector2 from, Vector2 to,
+ int *outVertexIndex, float *outDistance, Vector2 *out) const;
+ bool findIntersectionFarthest(int polygonIndex, Vector2 from, Vector2 to,
+ int *outVertexIndex, float *outDistance, Vector2 *out) const;
+
+ bool findPolygonVerticeByXZ(int *polygonIndex, int *verticeIndex, int *verticeCount, float x, float z) const;
+ bool findPolygonVerticeByXZWithinTolerance(float x, float z, int *polygonIndex, int *verticeIndex) const;
+
+ void clearVertices();
+ void copyVerticesReverse();
+ void copyVertices();
+
void backup();
void restore();
+ void reset();
+
+ void draw();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/overlays.cpp b/engines/bladerunner/overlays.cpp
index b5cb130678..65ba83f15d 100644
--- a/engines/bladerunner/overlays.cpp
+++ b/engines/bladerunner/overlays.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/bladerunner.h"
#include "bladerunner/archive.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/vqa_player.h"
#include "graphics/surface.h"
@@ -56,19 +57,22 @@ Overlays::~Overlays() {
}
int Overlays::play(const Common::String &name, int loopId, bool loopForever, bool startNow, int a6) {
- int id = mix_id(name);
- int index = findById(id);
+ assert(name.size() <= 12);
+
+ int32 hash = MIXArchive::getHash(name);
+ int index = findByHash(hash);
if (index < 0) {
index = findEmpty();
if (index < 0) {
return index;
}
- _videos[index].id = id;
+ _videos[index].loaded = true;
+ _videos[index].name = name;
+ _videos[index].hash = hash;
_videos[index].vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront);
// repeat forever
_videos[index].vqaPlayer->setBeginAndEndFrame(0, 0, -1, kLoopSetModeJustStart, nullptr, nullptr);
- _videos[index].loaded = true;
}
Common::String resourceName = Common::String::format("%s.VQA", name.c_str());
@@ -83,8 +87,7 @@ int Overlays::play(const Common::String &name, int loopId, bool loopForever, boo
}
void Overlays::remove(const Common::String &name) {
- int id = mix_id(name);
- int index = findById(id);
+ int index = findByHash(MIXArchive::getHash(name));
if (index >= 0) {
resetSingle(index);
}
@@ -109,9 +112,9 @@ void Overlays::tick() {
}
}
-int Overlays::findById(int32 id) const {
+int Overlays::findByHash(int32 hash) const {
for (int i = 0; i < kOverlayVideos; ++i) {
- if (_videos[i].loaded && _videos[i].id == id) {
+ if (_videos[i].loaded && _videos[i].hash == hash) {
return i;
}
}
@@ -134,12 +137,44 @@ void Overlays::resetSingle(int i) {
_videos[i].vqaPlayer = nullptr;
}
_videos[i].loaded = false;
- _videos[i].id = 0;
+ _videos[i].hash = 0;
_videos[i].field2 = -1;
+ _videos[i].name.clear();
}
void Overlays::reset() {
_videos.clear();
}
+void Overlays::save(SaveFileWriteStream &f) {
+ for (int i = 0; i < kOverlayVideos; ++i) {
+ // 37 bytes per overlay
+ Video &ov = _videos[i];
+
+ f.writeBool(ov.loaded);
+ f.writeInt(0); // vqaPlayer pointer
+ f.writeStringSz(ov.name, 13);
+ f.writeSint32LE(ov.hash);
+ f.writeInt(ov.field0);
+ f.writeInt(ov.field1);
+ f.writeInt(ov.field2);
+ }
+}
+
+void Overlays::load(SaveFileReadStream &f) {
+ for (int i = 0; i < kOverlayVideos; ++i) {
+ // 37 bytes per overlay
+ Video &ov = _videos[i];
+
+ ov.loaded = f.readBool();
+ f.skip(4); // vqaPlayer pointer
+ ov.vqaPlayer = nullptr;
+ ov.name = f.readStringSz(13);
+ ov.hash = f.readSint32LE();
+ ov.field0 = f.readInt();
+ ov.field1 = f.readInt();
+ ov.field2 = f.readInt();
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/overlays.h b/engines/bladerunner/overlays.h
index 38edf7459b..405acbc264 100644
--- a/engines/bladerunner/overlays.h
+++ b/engines/bladerunner/overlays.h
@@ -33,20 +33,21 @@ struct Surface;
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class VQAPlayer;
-
class Overlays {
static const int kOverlayVideos = 5;
struct Video {
- bool loaded;
- VQAPlayer *vqaPlayer;
- // char name[13];
- int32 id;
- int field0;
- int field1;
- int field2;
+ bool loaded;
+ VQAPlayer *vqaPlayer;
+ Common::String name;
+ int32 hash;
+ int field0;
+ int field1;
+ int field2;
};
BladeRunnerEngine *_vm;
@@ -62,8 +63,11 @@ public:
void removeAll();
void tick();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
private:
- int findById(int32 id) const;
+ int findByHash(int32 hash) const;
int findEmpty() const;
void resetSingle(int i);
diff --git a/engines/bladerunner/rect.h b/engines/bladerunner/rect.h
new file mode 100644
index 0000000000..da01af389d
--- /dev/null
+++ b/engines/bladerunner/rect.h
@@ -0,0 +1,75 @@
+/* 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 BLADERUNNER_RECT_H
+#define BLADERUNNER_RECT_H
+
+#include "common/debug.h"
+#include "common/types.h"
+#include "common/util.h"
+
+namespace BladeRunner {
+
+struct Rect {
+ float x0;
+ float y0;
+ float x1;
+ float y1;
+
+ Rect()
+ : x0(0.0f), y0(0.0f), x1(0.0f), y1(0.0f)
+ {}
+ Rect(float x0, float y0, float x1, float y1)
+ : x0(x0), y0(y0), x1(x1), y1(y1)
+ {}
+
+ void expand(float d) {
+ x0 -= d;
+ y0 -= d;
+ x1 += d;
+ y1 += d;
+ }
+
+ void trunc_2_decimals() {
+ x0 = truncf(x0 * 100.0f) / 100.0f;
+ y0 = truncf(y0 * 100.0f) / 100.0f;
+ x1 = truncf(x1 * 100.0f) / 100.0f;
+ y1 = truncf(y1 * 100.0f) / 100.0f;
+ }
+};
+
+inline bool overlaps(const Rect &a, const Rect &b) {
+ return !(a.y1 < b.y0 || a.y0 > b.y1 || a.x0 > b.x1 || a.x1 < b.x0);
+}
+
+inline Rect merge(const Rect &a, const Rect &b) {
+ Rect c;
+ c.x0 = MIN(a.x0, b.x0);
+ c.y0 = MIN(a.y0, b.y0);
+ c.x1 = MAX(a.x1, b.x1);
+ c.y1 = MAX(a.y1, b.y1);
+ return c;
+}
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/regions.cpp b/engines/bladerunner/regions.cpp
index 80dabf2989..f74186240b 100644
--- a/engines/bladerunner/regions.cpp
+++ b/engines/bladerunner/regions.cpp
@@ -22,6 +22,8 @@
#include "bladerunner/regions.h"
+#include "bladerunner/savefile.h"
+
namespace BladeRunner {
Regions::Regions() {
@@ -99,4 +101,22 @@ void Regions::enable() {
_enabled = true;
}
+void Regions::save(SaveFileWriteStream &f) {
+ f.writeBool(_enabled);
+ for (int i = 0; i != 10; ++i) {
+ f.writeRect(_regions[i].rectangle);
+ f.writeInt(_regions[i].type);
+ f.writeInt(_regions[i].present);
+ }
+}
+
+void Regions::load(SaveFileReadStream &f) {
+ _enabled = f.readBool();
+ for (int i = 0; i != 10; ++i) {
+ _regions[i].rectangle = f.readRect();
+ _regions[i].type = f.readInt();
+ _regions[i].present = f.readInt();
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/regions.h b/engines/bladerunner/regions.h
index 9868f46ac0..aae3627650 100644
--- a/engines/bladerunner/regions.h
+++ b/engines/bladerunner/regions.h
@@ -30,6 +30,9 @@
namespace BladeRunner {
+class SaveFileReadStream;
+class SaveFileWriteStream;
+
class Regions {
friend class Debugger;
@@ -54,6 +57,9 @@ public:
void setEnabled(bool enabled);
void enable();
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/savefile.cpp b/engines/bladerunner/savefile.cpp
new file mode 100644
index 0000000000..3528a6bb82
--- /dev/null
+++ b/engines/bladerunner/savefile.cpp
@@ -0,0 +1,166 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/savefile.h"
+
+#include "bladerunner/boundingbox.h"
+#include "bladerunner/vector.h"
+
+#include "common/rect.h"
+#include "common/savefile.h"
+
+namespace BladeRunner {
+
+SaveFileWriteStream::SaveFileWriteStream()
+ : MemoryWriteStreamDynamic(DisposeAfterUse::YES) {
+}
+
+void SaveFileWriteStream::debug(char *p) {
+ write(p, strlen(p) + 1);
+}
+
+void SaveFileWriteStream::padBytes(int count) {
+ for (int i = 0; i < count; ++i) {
+ writeByte(0);
+ }
+}
+
+void SaveFileWriteStream::writeInt(int v) {
+ writeUint32LE(v);
+}
+
+void SaveFileWriteStream::writeFloat(int v) {
+ writeFloatLE(v);
+}
+
+void SaveFileWriteStream::writeBool(bool v) {
+ writeUint32LE(v);
+}
+
+void SaveFileWriteStream::writeStringSz(const Common::String &s, int sz) {
+ assert(s.size() < (uint)sz);
+ write(s.begin(), s.size());
+ padBytes((uint)sz - s.size());
+}
+
+void SaveFileWriteStream::writeVector2(const Vector2 &v) {
+ writeFloatLE(v.x);
+ writeFloatLE(v.y);
+}
+
+void SaveFileWriteStream::writeVector3(const Vector3 &v) {
+ writeFloatLE(v.x);
+ writeFloatLE(v.y);
+ writeFloatLE(v.z);
+}
+
+void SaveFileWriteStream::writeRect(const Common::Rect &v) {
+ writeUint32LE(v.left);
+ writeUint32LE(v.top);
+ writeUint32LE(v.right);
+ writeUint32LE(v.bottom);
+}
+
+void SaveFileWriteStream::writeBoundingBox(const BoundingBox &v) {
+ float x0, y0, z0, x1, y1, z1;
+
+ v.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
+ writeFloatLE(x0);
+ writeFloatLE(y0);
+ writeFloatLE(z0);
+ writeFloatLE(x1);
+ writeFloatLE(y1);
+ writeFloatLE(z1);
+
+ // Bounding boxes have a lot of extra data that's never actually used
+ for (int i = 0; i != 96; ++i) {
+ writeFloatLE(0.0f);
+ }
+}
+
+SaveFileReadStream::SaveFileReadStream(const byte *dataPtr, uint32 dataSize)
+ : MemoryReadStream(dataPtr, dataSize, DisposeAfterUse::YES) {
+}
+
+int SaveFileReadStream::readInt() {
+ return readUint32LE();
+}
+
+float SaveFileReadStream::readFloat() {
+ return readFloatLE();
+}
+
+bool SaveFileReadStream::readBool() {
+ return readUint32LE();
+}
+
+Common::String SaveFileReadStream::readStringSz(int sz) {
+ char *buf = (char *)malloc(sz);
+ read(buf, sz);
+ Common::String result = buf;
+ free(buf);
+ return result;
+}
+
+Vector2 SaveFileReadStream::readVector2() {
+ Vector2 result;
+ result.x = readFloatLE();
+ result.y = readFloatLE();
+ return result;
+}
+
+Vector3 SaveFileReadStream::readVector3() {
+ Vector3 result;
+ result.x = readFloatLE();
+ result.y = readFloatLE();
+ result.z = readFloatLE();
+ return result;
+}
+
+Common::Rect SaveFileReadStream::readRect() {
+ Common::Rect result;
+ result.left = readUint32LE();
+ result.top = readUint32LE();
+ result.right = readUint32LE();
+ result.bottom = readUint32LE();
+ return result;
+}
+
+BoundingBox SaveFileReadStream::readBoundingBox() {
+ float x0, y0, z0, x1, y1, z1;
+
+ x0 = readFloatLE();
+ y0 = readFloatLE();
+ z0 = readFloatLE();
+ x1 = readFloatLE();
+ y1 = readFloatLE();
+ z1 = readFloatLE();
+
+ // Bounding boxes have a lot of extra data that's never actually used
+ skip(384);
+
+ return BoundingBox(x0, y0, z0, x1, y1, z1);
+}
+
+
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/savefile.h b/engines/bladerunner/savefile.h
new file mode 100644
index 0000000000..4dfdb20bd4
--- /dev/null
+++ b/engines/bladerunner/savefile.h
@@ -0,0 +1,75 @@
+/* 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 BLADERUNNER_SAVEFILE_H
+#define BLADERUNNER_SAVEFILE_H
+
+#include "common/memstream.h"
+#include "common/types.h"
+
+namespace Common {
+class OutSaveFile;
+class String;
+struct Rect;
+}
+
+namespace BladeRunner {
+
+class Vector2;
+class Vector3;
+class BoundingBox;
+
+class SaveFileWriteStream : public Common::MemoryWriteStreamDynamic {
+public:
+ SaveFileWriteStream();
+
+ void debug(char *p);
+
+ void padBytes(int count);
+
+ void writeInt(int v);
+ void writeFloat(int v);
+ void writeBool(bool v);
+ void writeStringSz(const Common::String &s, int sz);
+ void writeVector2(const Vector2 &v);
+ void writeVector3(const Vector3 &v);
+ void writeRect(const Common::Rect &v);
+ void writeBoundingBox(const BoundingBox &v);
+};
+
+class SaveFileReadStream : public Common::MemoryReadStream {
+public:
+ SaveFileReadStream(const byte *dataPtr, uint32 dataSize);
+
+ int readInt();
+ float readFloat();
+ bool readBool();
+ Common::String readStringSz(int sz);
+ Vector2 readVector2();
+ Vector3 readVector3();
+ Common::Rect readRect();
+ BoundingBox readBoundingBox();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 123134ed96..fe8dbc7b61 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -30,11 +30,13 @@
#include "bladerunner/items.h"
#include "bladerunner/overlays.h"
#include "bladerunner/regions.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/scene_objects.h"
#include "bladerunner/screen_effects.h"
#include "bladerunner/set.h"
#include "bladerunner/settings.h"
#include "bladerunner/slice_renderer.h"
+#include "bladerunner/script/police_maze.h"
#include "bladerunner/script/scene_script.h"
#include "bladerunner/ui/spinner.h"
#include "bladerunner/vqa_player.h"
@@ -187,7 +189,8 @@ bool Scene::close(bool isLoadingGame) {
return true;
}
- //_vm->_policeMaze->clear(!isLoadingGame);
+ _vm->_policeMaze->clear(!isLoadingGame);
+
if (isLoadingGame) {
_vm->_sceneScript->playerWalkedOut();
}
@@ -328,7 +331,7 @@ void Scene::loopStartSpecial(int specialLoopMode, int loopId, bool immediately)
}
}
-int Scene::findObject(const char *objectName) {
+int Scene::findObject(const Common::String &objectName) {
return _set->findObject(objectName);
}
@@ -374,7 +377,7 @@ void Scene::objectSetIsTarget(int objectId, bool isTarget, bool sceneLoaded) {
}
}
-const char *Scene::objectGetName(int objectId) {
+const Common::String &Scene::objectGetName(int objectId) {
return _set->objectGetName(objectId);
}
@@ -410,4 +413,37 @@ void Scene::loopEnded(int frame, int loopId) {
void Scene::loopEndedStatic(void *data, int frame, int loopId) {
((Scene *)data)->loopEnded(frame, loopId);
}
+
+void Scene::save(SaveFileWriteStream &f) {
+ f.writeInt(_setId);
+ f.writeInt(_sceneId);
+ f.writeInt(_defaultLoop);
+ f.writeBool(_defaultLoopSet);
+ f.writeBool(_defaultLoopPreloadedSet);
+ f.writeInt(_specialLoopMode);
+ f.writeInt(_specialLoop);
+ f.writeInt(_nextSetId);
+ f.writeInt(_nextSceneId);
+ f.writeInt(_frame);
+ f.writeVector3(_actorStartPosition);
+ f.writeInt(_actorStartFacing);
+ f.writeBool(_playerWalkedIn);
+}
+
+void Scene::load(SaveFileReadStream &f) {
+ _setId = f.readInt();
+ _sceneId = f.readInt();
+ _defaultLoop = f.readInt();
+ _defaultLoopSet = f.readBool();
+ _defaultLoopPreloadedSet = f.readBool();
+ _specialLoopMode = f.readInt();
+ _specialLoop = f.readInt();
+ _nextSetId = f.readInt();
+ _nextSceneId = f.readInt();
+ _frame = f.readInt();
+ _actorStartPosition = f.readVector3();
+ _actorStartFacing = f.readInt();
+ _playerWalkedIn = f.readBool();
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index 91cd2ed604..0403cd331e 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -25,11 +25,15 @@
#include "bladerunner/vector.h"
+#include "common/str.h"
+
namespace BladeRunner {
class BladeRunnerEngine;
class BoundingBox;
class Regions;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class Set;
class VQAPlayer;
@@ -80,14 +84,17 @@ public:
bool didPlayerWalkIn() { bool r = _playerWalkedIn; _playerWalkedIn = false; return r; }
- int findObject(const char *objectName);
+ int findObject(const Common::String &objectName);
bool objectSetHotMouse(int objectId);
bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox);
void objectSetIsClickable(int objectId, bool isClickable, bool sceneLoaded);
void objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded, bool updateWalkpath);
void objectSetIsObstacleAll(bool isObstacle, bool sceneLoaded);
void objectSetIsTarget(int objectId, bool isTarget, bool sceneLoaded);
- const char *objectGetName(int objectId);
+ const Common::String &objectGetName(int objectId);
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
private:
void loopEnded(int frame, int loopId);
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index 87320a3fa4..30802a8d64 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/bladerunner.h"
#include "bladerunner/obstacles.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/view.h"
namespace BladeRunner {
@@ -35,9 +36,7 @@ SceneObjects::SceneObjects(BladeRunnerEngine *vm, View *view) {
_count = 0;
- for (int i = 0; i < kSceneObjectCount; ++i) {
- _sceneObjectsSortedByDistance[i] = -1;
- }
+ clear();
}
SceneObjects::~SceneObjects() {
@@ -64,16 +63,16 @@ void SceneObjects::clear() {
_count = 0;
}
-bool SceneObjects::addActor(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isClickable, bool isMoving, bool isTarget, bool isRetired) {
+bool SceneObjects::addActor(int sceneObjectId, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isClickable, bool isMoving, bool isTarget, bool isRetired) {
return addSceneObject(sceneObjectId, kSceneObjectTypeActor, boundingBox, screenRectangle, isClickable, false, 0, isTarget, isMoving, isRetired);
}
-bool SceneObjects::addObject(int sceneObjectId, BoundingBox *boundingBox, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget) {
+bool SceneObjects::addObject(int sceneObjectId, const BoundingBox &boundingBox, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget) {
Common::Rect rect(-1, -1, -1, -1);
- return addSceneObject(sceneObjectId, kSceneObjectTypeObject, boundingBox, &rect, isClickable, isObstacle, unknown1, isTarget, false, false);
+ return addSceneObject(sceneObjectId, kSceneObjectTypeObject, boundingBox, rect, isClickable, isObstacle, unknown1, isTarget, false, false);
}
-bool SceneObjects::addItem(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isTarget, bool isObstacle) {
+bool SceneObjects::addItem(int sceneObjectId, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isTarget, bool isObstacle) {
return addSceneObject(sceneObjectId, kSceneObjectTypeItem, boundingBox, screenRectangle, isObstacle, 0, 0, isTarget, 0, 0);
}
@@ -110,7 +109,7 @@ int SceneObjects::findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget,
if ((findClickables && sceneObject->isClickable) ||
(findObstacles && sceneObject->isObstacle) ||
(findTargets && sceneObject->isTarget)) {
- BoundingBox boundingBox = *sceneObject->boundingBox;
+ BoundingBox boundingBox = sceneObject->boundingBox;
if (sceneObject->type == kSceneObjectTypeActor) {
boundingBox.expand(-4.0, 0.0, -4.0, 4.0, 0.0, 4.0);
@@ -155,7 +154,7 @@ bool SceneObjects::existsOnXZ(int exceptSceneObjectId, float x, float z, bool mo
if (isObstacle && sceneObject->id != exceptSceneObjectId) {
float x1, y1, z1, x2, y2, z2;
- sceneObject->boundingBox->getXYZ(&x1, &y1, &z1, &x2, &y2, &z2);
+ sceneObject->boundingBox.getXYZ(&x1, &y1, &z1, &x2, &y2, &z2);
if (z1 <= zMax && z2 >= zMin && x1 <= xMax && x2 >= xMin) {
return true;
}
@@ -176,7 +175,7 @@ int SceneObjects::findById(int sceneObjectId) const {
return -1;
}
-bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget, bool isMoving, bool isRetired) {
+bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget, bool isMoving, bool isRetired) {
int index = findEmpty();
if (index == -1) {
return false;
@@ -194,7 +193,7 @@ bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObject
_sceneObjects[index].isMoving = isMoving;
_sceneObjects[index].isRetired = isRetired;
- float centerZ = (_sceneObjects[index].boundingBox->getZ0() + _sceneObjects[index].boundingBox->getZ1()) / 2.0f;
+ float centerZ = (_sceneObjects[index].boundingBox.getZ0() + _sceneObjects[index].boundingBox.getZ1()) / 2.0f;
float distanceToCamera = fabs(-centerZ - _view->_cameraPosition.y); // y<->z is intentional, not a bug
_sceneObjects[index].distanceToCamera = distanceToCamera;
@@ -246,7 +245,7 @@ bool SceneObjects::isBetween(float sourceX, float sourceZ, float targetX, float
}
float objectX1, objectY1, objectZ1, objectX2, objectY2, objectZ2;
- _sceneObjects[i].boundingBox->getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
+ _sceneObjects[i].boundingBox.getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
Vector2 intersection;
return lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX1, objectZ1), Vector2(objectX2, objectZ1), &intersection)
@@ -255,7 +254,7 @@ bool SceneObjects::isBetween(float sourceX, float sourceZ, float targetX, float
|| lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX1, objectZ2), Vector2(objectX1, objectZ1), &intersection);
}
-bool SceneObjects::isObstacleBetween(float sourceX, float sourceZ, float targetX, float targetZ, float altitude, int exceptSceneObjectId) const {
+bool SceneObjects::isObstacleBetween(const Vector3 &source, const Vector3 &target, int exceptSceneObjectId) const {
for (int i = 0; i < _count; ++i) {
const SceneObject *sceneObject = &_sceneObjects[_sceneObjectsSortedByDistance[i]];
@@ -264,9 +263,9 @@ bool SceneObjects::isObstacleBetween(float sourceX, float sourceZ, float targetX
}
float objectX1, objectY1, objectZ1, objectX2, objectY2, objectZ2;
- _sceneObjects[i].boundingBox->getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
+ sceneObject->boundingBox.getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
- if (84.0f <= objectY1 - altitude || 72.0f >= objectY2 - altitude) {
+ if (84.0f <= objectY1 - source.y || 72.0f >= objectY2 - source.y) {
continue;
}
@@ -279,10 +278,10 @@ bool SceneObjects::isObstacleBetween(float sourceX, float sourceZ, float targetX
objectZ2 = objectZ2 - zAdjustement;
Vector2 intersection;
- if (lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX1, objectZ1), Vector2(objectX2, objectZ1), &intersection)
- || lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX2, objectZ1), Vector2(objectX2, objectZ2), &intersection)
- || lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX2, objectZ2), Vector2(objectX1, objectZ2), &intersection)
- || lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX1, objectZ2), Vector2(objectX1, objectZ1), &intersection)) {
+ if (lineIntersection(Vector2(source.x, source.z), Vector2(target.x, target.z), Vector2(objectX1, objectZ1), Vector2(objectX2, objectZ1), &intersection)
+ || lineIntersection(Vector2(source.x, source.z), Vector2(target.x, target.z), Vector2(objectX2, objectZ1), Vector2(objectX2, objectZ2), &intersection)
+ || lineIntersection(Vector2(source.x, source.z), Vector2(target.x, target.z), Vector2(objectX2, objectZ2), Vector2(objectX1, objectZ2), &intersection)
+ || lineIntersection(Vector2(source.x, source.z), Vector2(target.x, target.z), Vector2(objectX1, objectZ2), Vector2(objectX1, objectZ1), &intersection)) {
return true;
}
}
@@ -320,11 +319,53 @@ void SceneObjects::updateObstacles() {
const SceneObject *sceneObject = &_sceneObjects[index];
if (sceneObject->isObstacle) {
float x0, y0, z0, x1, y1, z1;
- sceneObject->boundingBox->getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
+ sceneObject->boundingBox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
_vm->_obstacles->add(x0, z0, x1, z1);
}
}
_vm->_obstacles->backup();
}
+void SceneObjects::save(SaveFileWriteStream &f) {
+ f.writeInt(_count);
+ for (int i = 0; i < kSceneObjectCount; ++i) {
+ f.writeInt(_sceneObjects[i].id);
+ f.writeInt(_sceneObjects[i].type);
+ f.writeBoundingBox(_sceneObjects[i].boundingBox);
+ f.writeRect(_sceneObjects[i].screenRectangle);
+ f.writeFloat(_sceneObjects[i].distanceToCamera);
+ f.writeBool(_sceneObjects[i].isPresent);
+ f.writeBool(_sceneObjects[i].isClickable);
+ f.writeBool(_sceneObjects[i].isObstacle);
+ f.writeInt(_sceneObjects[i].unknown1);
+ f.writeBool(_sceneObjects[i].isTarget);
+ f.writeBool(_sceneObjects[i].isMoving);
+ f.writeBool(_sceneObjects[i].isRetired);
+ }
+ for (int i = 0; i < kSceneObjectCount; ++i) {
+ f.writeInt(_sceneObjectsSortedByDistance[i]);
+ }
+}
+
+void SceneObjects::load(SaveFileReadStream &f) {
+ _count = f.readInt();
+ for (int i = 0; i < kSceneObjectCount; ++i) {
+ _sceneObjects[i].id = f.readInt();
+ _sceneObjects[i].type = (SceneObjectType)f.readInt();
+ _sceneObjects[i].boundingBox = f.readBoundingBox();
+ _sceneObjects[i].screenRectangle = f.readRect();
+ _sceneObjects[i].distanceToCamera = f.readFloat();
+ _sceneObjects[i].isPresent = f.readBool();
+ _sceneObjects[i].isClickable = f.readBool();
+ _sceneObjects[i].isObstacle = f.readBool();
+ _sceneObjects[i].unknown1 = f.readInt();
+ _sceneObjects[i].isTarget = f.readBool();
+ _sceneObjects[i].isMoving = f.readBool();
+ _sceneObjects[i].isRetired = f.readBool();
+ }
+ for (int i = 0; i < kSceneObjectCount; ++i) {
+ _sceneObjectsSortedByDistance[i] = f.readInt();
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index dbd61b6dc5..a6d552017c 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -30,6 +30,8 @@
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class View;
enum SceneObjectType {
@@ -45,18 +47,18 @@ class SceneObjects {
static const int kSceneObjectCount = 115;
struct SceneObject {
- int id;
- SceneObjectType type;
- const BoundingBox *boundingBox;
- const Common::Rect *screenRectangle;
- float distanceToCamera;
- bool isPresent;
- bool isClickable;
- bool isObstacle;
- int unknown1;
- bool isTarget;
- bool isMoving;
- bool isRetired;
+ int id;
+ SceneObjectType type;
+ BoundingBox boundingBox;
+ Common::Rect screenRectangle;
+ float distanceToCamera;
+ bool isPresent;
+ bool isClickable;
+ bool isObstacle;
+ int unknown1;
+ bool isTarget;
+ bool isMoving;
+ bool isRetired;
};
BladeRunnerEngine *_vm;
@@ -70,9 +72,9 @@ public:
SceneObjects(BladeRunnerEngine *vm, View *view);
~SceneObjects();
- bool addActor(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isClickable, bool isMoving, bool isTarget, bool isRetired);
- bool addObject(int sceneObjectId, BoundingBox *boundingBox, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget);
- bool addItem(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isTarget, bool isObstacle);
+ bool addActor(int sceneObjectId, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isClickable, bool isMoving, bool isTarget, bool isRetired);
+ bool addObject(int sceneObjectId, const BoundingBox &boundingBox, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget);
+ bool addItem(int sceneObjectId, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isTarget, bool isObstacle);
bool remove(int sceneObjectId);
void clear();
int findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget, Vector3 &position, bool findClickables, bool findObstacles, bool findTargets) const;
@@ -80,16 +82,18 @@ public:
void setMoving(int sceneObjectId, bool isMoving);
void setRetired(int sceneObjectId, bool isRetired);
bool isBetween(float sourceX, float sourceZ, float targetX, float targetZ, int sceneObjectId) const;
- bool isObstacleBetween(float sourceX, float sourceZ, float targetX, float targetZ, float altitude, int exceptSceneObjectId) const;
+ bool isObstacleBetween(const Vector3 &source, const Vector3 &target, int exceptSceneObjectId) const;
void setIsClickable(int sceneObjectId, bool isClickable);
void setIsObstacle(int sceneObjectId, bool isObstacle);
void setIsTarget(int sceneObjectId, bool isTarget);
void updateObstacles();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
private:
int findById(int sceneObjectId) const;
- bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget, bool isMoving, bool isRetired);
+ bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget, bool isMoving, bool isRetired);
int findEmpty() const;
};
diff --git a/engines/bladerunner/screen_effects.h b/engines/bladerunner/screen_effects.h
index ad0fb5090f..d16f1cf284 100644
--- a/engines/bladerunner/screen_effects.h
+++ b/engines/bladerunner/screen_effects.h
@@ -39,12 +39,12 @@ class ScreenEffects {
public:
struct Entry {
Color256 palette[16];
- uint16 x;
- uint16 y;
- uint16 width;
- uint16 height;
- uint16 z;
- uint8 *data;
+ uint16 x;
+ uint16 y;
+ uint16 width;
+ uint16 height;
+ uint16 z;
+ uint8 *data;
};
BladeRunnerEngine *_vm;
@@ -58,7 +58,7 @@ public:
~ScreenEffects();
void readVqa(Common::SeekableReadStream *stream);
- void getColor(Color256 *outColor, uint16 x, uint16 y, uint16 z) const ;
+ void getColor(Color256 *outColor, uint16 x, uint16 y, uint16 z) const;
//TODO
//bool isAffectingArea(int x, int y, int width, int height, int unk);
diff --git a/engines/bladerunner/script/ai/bullet_bob.cpp b/engines/bladerunner/script/ai/bullet_bob.cpp
new file mode 100644
index 0000000000..87394fa44e
--- /dev/null
+++ b/engines/bladerunner/script/ai/bullet_bob.cpp
@@ -0,0 +1,555 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptBulletBob::AIScriptBulletBob(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+ _var1 = 0;
+ _var2 = 6;
+ _var3 = 1;
+ _var4 = 0;
+}
+
+void AIScriptBulletBob::Initialize() {
+ _animationFrame = 0;
+ _animationState = 0;
+ _animationStateNext = 0;
+ _animationNext = 0;
+
+ _var1 = 0;
+ _var2 = 6;
+ _var3 = 1;
+ _var4 = 0;
+
+ Actor_Set_Goal_Number(kActorBulletBob, 0);
+ Actor_Set_Targetable(kActorBulletBob, 1);
+}
+
+bool AIScriptBulletBob::Update() {
+ if (Game_Flag_Query(289) && Actor_Query_Goal_Number(kActorBulletBob) != 4) {
+ Actor_Set_Goal_Number(kActorBulletBob, 4);
+ }
+ if (Player_Query_Combat_Mode() != 1
+ || Player_Query_Current_Scene() != kSceneRC04
+ || Game_Flag_Query(296)
+ || Global_Variable_Query(kVariableChapter) >= 4) {
+ if (Actor_Query_Goal_Number(kActorBulletBob) == 1 && !Player_Query_Combat_Mode()) {
+ AI_Countdown_Timer_Reset(kActorBulletBob, 2);
+ Game_Flag_Reset(296);
+ Game_Flag_Set(303);
+ Actor_Set_Goal_Number(kActorBulletBob, 0);
+ }
+ } else {
+ AI_Countdown_Timer_Reset(kActorBulletBob, 2);
+ AI_Countdown_Timer_Start(kActorBulletBob, 2, 10);
+ Actor_Set_Goal_Number(kActorBulletBob, 1);
+ Actor_Modify_Friendliness_To_Other(kActorBulletBob, kActorMcCoy, -15);
+ Game_Flag_Set(296);
+ }
+ if (Actor_Query_Goal_Number(kActorBulletBob) != 2 || Game_Flag_Query(295) || _animationState) {
+ if (Game_Flag_Query(303) == 1 && Player_Query_Combat_Mode() == 1 && Actor_Query_Goal_Number(kActorBulletBob) != 4) {
+ Actor_Set_Goal_Number(kActorBulletBob, 2);
+ } else {
+ return false;
+ }
+ } else {
+ Actor_Face_Heading(kActorBulletBob, 208, 0);
+ _animationFrame = 0;
+ _animationState = 2;
+ Actor_Set_Goal_Number(kActorBulletBob, 3);
+ Game_Flag_Set(295);
+ }
+
+ return true;
+}
+
+void AIScriptBulletBob::TimerExpired(int timer) {
+ if (timer != 2 || Actor_Query_Goal_Number(kActorBulletBob) != 1)
+ return; //false;
+
+ Actor_Set_Goal_Number(kActorBulletBob, 2);
+ AI_Countdown_Timer_Reset(kActorBulletBob, 2);
+
+ return; //true;
+}
+
+void AIScriptBulletBob::CompletedMovementTrack() {
+ //return false;
+}
+
+void AIScriptBulletBob::ReceivedClue(int clueId, int fromActorId) {
+ //return false;
+}
+
+void AIScriptBulletBob::ClickedByPlayer() {
+ //return false;
+}
+
+void AIScriptBulletBob::EnteredScene(int sceneId) {
+ // return false;
+}
+
+void AIScriptBulletBob::OtherAgentEnteredThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptBulletBob::OtherAgentExitedThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptBulletBob::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+ // return false;
+}
+
+void AIScriptBulletBob::ShotAtAndMissed() {
+ // return false;
+}
+
+bool AIScriptBulletBob::ShotAtAndHit() {
+ Global_Variable_Increment(24, 1);
+ if (Global_Variable_Query(24) > 0) {
+ Actor_Set_Targetable(kActorBulletBob, 0);
+ Actor_Set_Goal_Number(kActorBulletBob, 99);
+ _animationFrame = 0;
+ _animationState = 3;
+ Ambient_Sounds_Play_Speech_Sound(2, 9000, 100, 0, 0, 0);
+ Actor_Face_Heading(kActorBulletBob, 281, 0);
+ }
+
+ return false;
+}
+
+void AIScriptBulletBob::Retired(int byActorId) {
+ // return false;
+}
+
+int AIScriptBulletBob::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+ return 0;
+}
+
+bool AIScriptBulletBob::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+ if (newGoalNumber || Game_Flag_Query(303) != 1 || Player_Query_Current_Scene() != kSceneRC04) {
+ if (newGoalNumber == 1 && !Game_Flag_Query(303) && Player_Query_Current_Scene() == kSceneRC04) {
+ Actor_Says(kActorBulletBob, 120, 37);
+ Actor_Says(kActorMcCoy, 4915, 13);
+ return true;
+ }
+ if (newGoalNumber == 6) {
+ Scene_Exits_Disable();
+ Actor_Force_Stop_Walking(kActorMcCoy);
+ Ambient_Sounds_Play_Speech_Sound(kActorMcCoy, 9900, 100, 0, 0, 0);
+ Actor_Change_Animation_Mode(kActorMcCoy, 48);
+ Actor_Retired_Here(kActorMcCoy, 6, 6, 1, -1);
+ Scene_Exits_Enable();
+ }
+ if (newGoalNumber != 4) {
+ return false;
+ }
+ if (Actor_Clue_Query(kActorMcCoy, 164) != 1) {
+ Delay(2000);
+ Actor_Voice_Over(2100, kActorVoiceOver);
+ Actor_Voice_Over(2110, kActorVoiceOver);
+ Actor_Voice_Over(2120, kActorVoiceOver);
+ Actor_Voice_Over(2130, kActorVoiceOver);
+ }
+ } else {
+ Actor_Says(kActorBulletBob, 140, 16);
+ }
+
+ return true;
+}
+
+bool AIScriptBulletBob::UpdateAnimation(int *animation, int *frame) {
+ switch (_animationState) {
+ case 0:
+ if (_var1 == 1) {
+ *animation = 516;
+ if (_var4) {
+ _var4--;
+ } else {
+ if (++_animationFrame == 6) {
+ _var4 = Random_Query(4, 8);
+ }
+ if (_animationFrame == 11) {
+ _var4 = Random_Query(2, 6);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(515)) {
+ _animationFrame = 0;
+ _var1 = 0;
+ _var3 = 2 * Random_Query(0, 1) - 1;
+ _var2 = Random_Query(3, 7);
+ _var4 = Random_Query(0, 4);
+ }
+ }
+ } else if (_var1 == 0) {
+ *animation = 514;
+ if (_var4) {
+ _var4--;
+ } else {
+ _animationFrame += _var3;
+ if (_animationFrame < 0) {
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(514) - 1;
+ } else if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(514)) {
+ _animationFrame = 0;
+ }
+ if (!--_var2) {
+ _var3 = 2 * Random_Query(0, 1) - 1;
+ _var2 = Random_Query(3, 7);
+ _var4 = Random_Query(0, 4);
+ }
+ if (!_animationFrame) {
+ _var1 = Random_Query(0, 1);
+ }
+ }
+ }
+ break;
+
+ case 1:
+ *animation = 506;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(506)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 2:
+ *animation = 513;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(513)) {
+ _animationFrame = 0;
+ _animationState = 1;
+ *animation = 506;
+ }
+ if (_animationFrame == 10) {
+ Sound_Play(492, 75, 0, 0, 50);
+ }
+ if (_animationFrame == 5) {
+ Sound_Play(493, 90, 0, 0, 50);
+ Actor_Set_Goal_Number(kActorBulletBob, 6);
+ }
+ break;
+
+ case 3:
+ *animation = 510;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(510) - 1) {
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(510) - 1;
+ _animationState = 16;
+ Game_Flag_Set(289);
+ }
+ break;
+
+ case 4:
+ break;
+
+ case 5:
+ *animation = 525;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(525)) {
+ *animation = 514;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 6:
+ *animation = 517;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(517)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 7:
+ *animation = 518;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(518)) {
+ _animationFrame = 0;
+ _animationState = 6;
+ *animation = 517;
+ }
+ break;
+
+ case 8:
+ *animation = 519;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(519)) {
+ _animationFrame = 0;
+ _animationState = 6;
+ *animation = 517;
+ }
+ break;
+
+ case 9:
+ *animation = 520;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(520)) {
+ _animationFrame = 0;
+ _animationState = 6;
+ *animation = 517;
+ }
+ break;
+
+ case 10:
+ *animation = 521;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(521)) {
+ _animationFrame = 0;
+ _animationState = 6;
+ *animation = 517;
+ }
+ break;
+
+ case 11:
+ *animation = 522;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(522)) {
+ _animationFrame = 0;
+ _animationState = 6;
+ *animation = 517;
+ }
+ break;
+
+ case 12:
+ *animation = 523;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(523)) {
+ _animationFrame = 0;
+ _animationState = 6;
+ *animation = 517;
+ }
+ break;
+
+ case 13:
+ *animation = 524;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(524)) {
+ _animationFrame = 0;
+ _animationState = 6;
+ *animation = 517;
+ }
+ break;
+
+ case 14:
+ *animation = 512;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(512)) {
+ _animationFrame = 0;
+ _animationState = 1;
+ *animation = 506;
+ }
+ break;
+
+ case 15:
+ if (_var1 == 1) {
+ *animation = 516;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(516)) {
+ _animationFrame += 2;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(516)) {
+ _animationFrame = 0;
+ *animation = _animationNext;
+ _animationState = _animationStateNext;
+ }
+ } else {
+ _animationFrame -= 2;
+ if (_animationFrame <= 0) {
+ _animationFrame = 0;
+ *animation = _animationNext;
+ _animationState = _animationStateNext;
+ }
+ }
+ } else if (_var1 == 0) {
+ *animation = 514;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(514)) {
+ _animationFrame += 2;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(514)) {
+ _animationFrame = 0;
+ *animation = _animationNext;
+ _animationState = _animationStateNext;
+ }
+ } else {
+ _animationFrame -= 2;
+ if (_animationFrame <= 0) {
+ _animationFrame = 0;
+ *animation = _animationNext;
+ _animationState = _animationStateNext;
+ }
+ }
+ }
+ break;
+
+ case 16:
+ *animation = 510;
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(510) - 1;
+ break;
+
+ default:
+ break;
+ }
+ *frame = _animationFrame;
+
+ return true;
+}
+
+bool AIScriptBulletBob::ChangeAnimationMode(int mode) {
+ switch (mode) {
+ case 0:
+ if (_animationState > 4 || _animationState) {
+ _animationState = 0;
+ _animationFrame = 0;
+ }
+ break;
+
+ case 3:
+ case 9:
+ case 30:
+ if (_animationState < 6 || _animationState > 13) {
+ _animationState = 15;
+ _animationStateNext = 6;
+ _animationNext = 517;
+ }
+ break;
+
+ case 4:
+ if (_animationState <= 4 && !_animationState) {
+ _animationState = 14;
+ _animationFrame = 0;
+ }
+ break;
+
+ case 6:
+ _animationState = 2;
+ _animationFrame = 0;
+ break;
+
+ case 10:
+ case 31:
+ if (_animationState < 6 || _animationState > 13) {
+ _animationState = 15;
+ _animationStateNext = 7;
+ _animationNext = 518;
+ }
+ break;
+
+ case 11:
+ case 33:
+ if (_animationState < 6 || _animationState > 13) {
+ _animationState = 15;
+ _animationStateNext = 9;
+ _animationNext = 520;
+ }
+ break;
+
+ case 21:
+ case 22:
+ _animationState = 3;
+ _animationFrame = 0;
+ break;
+
+ case 23:
+ _animationState = 5;
+ _animationFrame = 0;
+ break;
+
+ case 32:
+ if (_animationState < 6 || _animationState > 13) {
+ _animationState = 15;
+ _animationStateNext = 8;
+ _animationNext = 519;
+ }
+ break;
+
+ case 34:
+ if (_animationState < 6 || _animationState > 13) {
+ _animationState = 15;
+ _animationStateNext = 10;
+ _animationNext = 521;
+ }
+ break;
+
+ case 35:
+ if (_animationState < 6 || _animationState > 13) {
+ _animationState = 15;
+ _animationStateNext = 11;
+ _animationNext = 522;
+ }
+ break;
+
+ case 36:
+ if (_animationState < 6 || _animationState > 13) {
+ _animationState = 15;
+ _animationStateNext = 12;
+ _animationNext = 523;
+ }
+ break;
+
+ case 37:
+ if (_animationState < 6 || _animationState > 13) {
+ _animationState = 15;
+ _animationStateNext = 13;
+ _animationNext = 524;
+ }
+ break;
+
+ case 48:
+ _animationState = 4;
+ _animationFrame = 0;
+ break;
+
+ case 88:
+ _animationState = 16;
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(510) - 1;
+ break;
+
+ default:
+ _animationState = 0;
+ _animationFrame = 0;
+ break;
+ }
+ return true;
+}
+
+void AIScriptBulletBob::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ *animationState = _animationState;
+ *animationFrame = _animationFrame;
+ *animationStateNext = _animationStateNext;
+ *animationNext = _animationNext;
+}
+
+void AIScriptBulletBob::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ _animationState = animationState;
+ _animationFrame = animationFrame;
+ _animationStateNext = animationStateNext;
+ _animationNext = animationNext;
+}
+
+bool AIScriptBulletBob::ReachedMovementTrackWaypoint(int waypointId) {
+ return true;
+}
+
+void AIScriptBulletBob::FledCombat() {
+ // return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/clovis.cpp b/engines/bladerunner/script/ai/clovis.cpp
index 9c8976e02d..58180f3699 100644
--- a/engines/bladerunner/script/ai/clovis.cpp
+++ b/engines/bladerunner/script/ai/clovis.cpp
@@ -56,24 +56,23 @@ bool AIScriptClovis::Update() {
} else if (Global_Variable_Query(kVariableChapter) == 3 && Actor_Query_Goal_Number(kActorClovis) < 350) {
Actor_Set_Goal_Number(kActorClovis, 350);
return true;
- } else if (Global_Variable_Query(kVariableChapter) != 4 || Game_Flag_Query(542)) {
+ } else if (Global_Variable_Query(kVariableChapter) == 4 && !Game_Flag_Query(542)) {
+ Game_Flag_Set(542);
+ Actor_Set_Goal_Number(kActorClovis, 400);
+ return true;
+ } else {
if (Global_Variable_Query(kVariableChapter) == 5 && Actor_Query_Goal_Number(kActorClovis) < 500) {
Actor_Set_Goal_Number(kActorClovis, 500);
}
if (Actor_Query_Goal_Number(kActorClovis) == 511 && Game_Flag_Query(657)) {
Actor_Set_Goal_Number(kActorClovis, 512);
}
- if (Game_Flag_Query(653) != 1 || Game_Flag_Query(696) || Game_Flag_Query(697) != 1) {
- return true;
- } else {
+ if (Game_Flag_Query(653) && !Game_Flag_Query(696) && Game_Flag_Query(697)) {
Actor_Set_Goal_Number(kActorClovis, 517);
Game_Flag_Set(696);
return true;
}
- } else {
- Game_Flag_Set(542);
- Actor_Set_Goal_Number(kActorClovis, 400);
- return true;
+ return false;
}
}
@@ -83,11 +82,11 @@ void AIScriptClovis::TimerExpired(int timer) {
void AIScriptClovis::CompletedMovementTrack() {
switch (Actor_Query_Goal_Number(kActorClovis)) {
- case 100:
+ case 101:
Actor_Set_Goal_Number(kActorClovis, 103);
break;
- case 101:
+ case 102:
Actor_Set_Goal_Number(kActorClovis, 102);
break;
@@ -114,7 +113,7 @@ void AIScriptClovis::ReceivedClue(int clueId, int fromActorId) {
void AIScriptClovis::ClickedByPlayer() {
if (Actor_Query_Goal_Number(kActorClovis) == 599) {
- Actor_Face_Actor(kActorMcCoy, kActorClovis, 1);
+ Actor_Face_Actor(kActorMcCoy, kActorClovis, true);
Actor_Says(kActorMcCoy, 8630, 16);
}
}
@@ -132,14 +131,12 @@ void AIScriptClovis::OtherAgentExitedThisScene(int otherActorId) {
}
void AIScriptClovis::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
- if (Game_Flag_Query(653) != 1 || !Actor_Query_In_Set(kActorMcCoy, kSetKP07)) {
- return; //false;
+ if (Game_Flag_Query(653) && Actor_Query_In_Set(kActorMcCoy, kSetKP07)) {
+ Game_Flag_Set(697);
+ Game_Flag_Set(714);
+ // return true;
}
-
- Game_Flag_Set(697);
- Game_Flag_Set(714);
-
- return; //true;
+ // return false;
}
void AIScriptClovis::ShotAtAndMissed() {
@@ -152,14 +149,14 @@ bool AIScriptClovis::ShotAtAndHit() {
ADQ_Flush();
Actor_Set_Goal_Number(kActorClovis, 599);
shotAnim();
- Actor_Set_Targetable(kActorClovis, 0);
+ Actor_Set_Targetable(kActorClovis, false);
ADQ_Add(kActorMcCoy, 2340, -1);
Music_Stop(3);
} else if (Actor_Query_Goal_Number(kActorClovis) == 513 || Actor_Query_Goal_Number(kActorClovis) == 518) {
ADQ_Flush();
Actor_Set_Goal_Number(kActorClovis, 599);
shotAnim();
- Actor_Set_Targetable(kActorClovis, 0);
+ Actor_Set_Targetable(kActorClovis, false);
Music_Stop(3);
}
}
@@ -167,7 +164,7 @@ bool AIScriptClovis::ShotAtAndHit() {
}
void AIScriptClovis::Retired(int byActorId) {
- if (Game_Flag_Query(653) == 1) {
+ if (Game_Flag_Query(653)) {
if (Actor_Query_In_Set(kActorClovis, kSetKP07)) {
Global_Variable_Decrement(51, 1);
Actor_Set_Goal_Number(kActorClovis, 599);
@@ -175,8 +172,8 @@ void AIScriptClovis::Retired(int byActorId) {
if (!Global_Variable_Query(51)) {
Player_Loses_Control();
Delay(2000);
- Player_Set_Combat_Mode(0);
- Loop_Actor_Walk_To_XYZ(kActorMcCoy, -12.0f, -41.58f, 72.0f, 0, 1, 0, 0);
+ Player_Set_Combat_Mode(false);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, -12.0f, -41.58f, 72.0f, 0, true, false, 0);
Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
Ambient_Sounds_Remove_All_Looping_Sounds(1);
Game_Flag_Set(579);
@@ -188,40 +185,38 @@ void AIScriptClovis::Retired(int byActorId) {
}
int AIScriptClovis::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
- if (otherActorId != kActorMcCoy)
+ if (otherActorId != kActorMcCoy) {
return 0;
+ }
switch (clueId) {
- case 212:
- case 230:
+ case kClueMcCoyKilledRunciter1:
+ case kClueMcCoyKilledRunciter2:
return 6;
- break;
- case 214:
- case 239:
- case 240:
+ case kClueMcCoyIsABladeRunner:
+ case kClueMcCoyIsStupid:
+ case kClueMcCoyIsAnnoying:
return -2;
- case 215:
- case 217:
- case 218:
- case 219:
- case 220:
- case 221:
- case 241:
+ case kClueMcCoyLetZubenEscape:
+ case kClueMcCoyHelpedIzoIzoIsAReplicant:
+ case kClueMcCoyHelpedDektora:
+ case kClueMcCoyHelpedLucy:
+ case kClueMcCoyHelpedGordo:
+ case kClueMcCoyShotGuzza:
+ case kClueMcCoyIsKind:
return 4;
- case 216:
+ case kClueMcCoyWarnedIzo:
return 2;
- case 222:
+ case kClueMcCoyRetiredZuben:
return -3;
- case 223:
- case 224:
+ case kClueMcCoyRetiredLucy:
+ case kClueMcCoyRetiredDektora:
return -10;
- case 226:
- case 227:
- case 228:
- case 242:
+ case kClueMcCoyRetiredSadik:
+ case kClueMcCoyShotZubenInTheBack:
+ case kClueMcCoyRetiredLutherLance:
+ case kClueMcCoyIsInsane:
return -5;
- default:
- return 0;
}
return 0;
}
@@ -251,30 +246,30 @@ bool AIScriptClovis::GoalChanged(int currentGoalNumber, int newGoalNumber) {
case 103:
Actor_Set_Goal_Number(kActorSadik, 107);
Actor_Says(kActorClovis, 10, 15);
- Actor_Says(kActorSadik, 0, 3);
- Actor_Face_Actor(kActorClovis, kActorSadik, 1);
+ Actor_Says(kActorSadik, 0, kAnimationModeTalk);
+ Actor_Face_Actor(kActorClovis, kActorSadik, true);
Actor_Says(kActorClovis, 20, 13);
Actor_Says(kActorClovis, 30, 12);
- Actor_Face_Actor(kActorSadik, kActorClovis, 1);
- Actor_Says(kActorSadik, 10, 3);
+ Actor_Face_Actor(kActorSadik, kActorClovis, true);
+ Actor_Says(kActorSadik, 10, kAnimationModeTalk);
Actor_Says(kActorClovis, 40, 17);
- Actor_Says(kActorSadik, 20, 3);
- Actor_Face_Actor(kActorClovis, 0, 1);
- Actor_Face_Actor(kActorSadik, 0, 1);
+ Actor_Says(kActorSadik, 20, kAnimationModeTalk);
+ Actor_Face_Actor(kActorClovis, kActorMcCoy, true);
+ Actor_Face_Actor(kActorSadik, kActorMcCoy, true);
Actor_Says(kActorClovis, 50, 14);
- Actor_Change_Animation_Mode(kActorClovis, 53);
+ Actor_Change_Animation_Mode(kActorClovis, kAnimationModeSit);
return true;
case 105:
Actor_Says(kActorClovis, 60, 30);
- Actor_Says(kActorSadik, 30, 3);
+ Actor_Says(kActorSadik, 30, kAnimationModeTalk);
Actor_Says(kActorClovis, 70, 30);
Actor_Says(kActorClovis, 80, 30);
Actor_Change_Animation_Mode(kActorClovis, 29);
- Actor_Says(kActorSadik, 40, 3);
- Actor_Says(kActorSadik, 50, 3);
+ Actor_Says(kActorSadik, 40, kAnimationModeTalk);
+ Actor_Says(kActorSadik, 50, kAnimationModeTalk);
Actor_Says(kActorClovis, 90, 13);
- Actor_Face_Current_Camera(5, 1);
+ Actor_Face_Current_Camera(5, true);
Actor_Says(kActorClovis, 100, 17);
Delay(1000);
if (!Game_Flag_Query(48)) {
@@ -343,7 +338,7 @@ bool AIScriptClovis::GoalChanged(int currentGoalNumber, int newGoalNumber) {
return true;
case 510:
- if (Game_Flag_Query(653) == 1) {
+ if (Game_Flag_Query(653)) {
Actor_Set_Goal_Number(kActorClovis, 513);
} else {
Actor_Set_Goal_Number(kActorClovis, 511);
@@ -357,26 +352,26 @@ bool AIScriptClovis::GoalChanged(int currentGoalNumber, int newGoalNumber) {
return true;
case 512:
- Actor_Says(kActorClovis, 110, 3);
- Actor_Says(kActorMcCoy, 2255, 3);
- Actor_Says(kActorClovis, 120, 3);
- Actor_Says(kActorClovis, 130, 3);
- Actor_Says(kActorClovis, 140, 3);
- Actor_Says(kActorMcCoy, 2260, 3);
- Actor_Says(kActorClovis, 150, 3);
+ Actor_Says(kActorClovis, 110, kAnimationModeTalk);
+ Actor_Says(kActorMcCoy, 2255, kAnimationModeTalk);
+ Actor_Says(kActorClovis, 120, kAnimationModeTalk);
+ Actor_Says(kActorClovis, 130, kAnimationModeTalk);
+ Actor_Says(kActorClovis, 140, kAnimationModeTalk);
+ Actor_Says(kActorMcCoy, 2260, kAnimationModeTalk);
+ Actor_Says(kActorClovis, 150, kAnimationModeTalk);
Actor_Set_Goal_Number(kActorClovis, 513);
return true;
case 513:
Actor_Put_In_Set(kActorClovis, kSetKP07);
- Actor_Set_Targetable(kActorClovis, 1);
- if (Game_Flag_Query(653) == 1) {
+ Actor_Set_Targetable(kActorClovis, true);
+ if (Game_Flag_Query(653)) {
Global_Variable_Set(51, 0);
Global_Variable_Increment(51, 1);
Actor_Set_At_XYZ(kActorClovis, 45.0f, -41.52f, -85.0f, 750);
} else {
Actor_Set_At_XYZ(kActorClovis, 84.85f, -50.56f, -68.87f, 800);
- Actor_Face_Heading(kActorClovis, 1022, 0);
+ Actor_Face_Heading(kActorClovis, 1022, false);
}
someAnim();
return true;
@@ -384,15 +379,15 @@ bool AIScriptClovis::GoalChanged(int currentGoalNumber, int newGoalNumber) {
case 514:
Actor_Says(kActorMcCoy, 2345, 16);
Actor_Says(kActorClovis, 170, -1);
- Actor_Says(kActorClovis, 180, 3);
+ Actor_Says(kActorClovis, 180, kAnimationModeTalk);
Actor_Says(kActorMcCoy, 2350, 17);
if (!Game_Flag_Query(714)) {
Actor_Says(kActorMcCoy, 2355, 11);
}
Actor_Says(kActorClovis, 190, -1);
- Actor_Says(kActorClovis, 200, 3);
+ Actor_Says(kActorClovis, 200, kAnimationModeTalk);
Actor_Says(kActorMcCoy, 2360, 18);
- Actor_Says(kActorClovis, 210, 3);
+ Actor_Says(kActorClovis, 210, kAnimationModeTalk);
Actor_Says(kActorClovis, 220, -1);
Actor_Set_Goal_Number(kActorClovis, 515);
return true;
@@ -409,15 +404,15 @@ bool AIScriptClovis::GoalChanged(int currentGoalNumber, int newGoalNumber) {
return true;
case 516:
- Actor_Says(kActorMcCoy, 8501, 3);
- Actor_Says(kActorClovis, 1260, 3);
- Actor_Says(kActorMcCoy, 8502, 3);
- Actor_Says(kActorClovis, 1270, 3);
- Actor_Says(kActorMcCoy, 8504, 3);
- Actor_Says(kActorClovis, 1290, 3);
- Actor_Says(kActorMcCoy, 8505, 3);
- Actor_Says(kActorClovis, 1300, 3);
- Actor_Says(kActorClovis, 1310, 3);
+ Actor_Says(kActorMcCoy, 8501, kAnimationModeTalk);
+ Actor_Says(kActorClovis, 1260, kAnimationModeTalk);
+ Actor_Says(kActorMcCoy, 8502, kAnimationModeTalk);
+ Actor_Says(kActorClovis, 1270, kAnimationModeTalk);
+ Actor_Says(kActorMcCoy, 8504, kAnimationModeTalk);
+ Actor_Says(kActorClovis, 1290, kAnimationModeTalk);
+ Actor_Says(kActorMcCoy, 8505, kAnimationModeTalk);
+ Actor_Says(kActorClovis, 1300, kAnimationModeTalk);
+ Actor_Says(kActorClovis, 1310, kAnimationModeTalk);
Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
Ambient_Sounds_Remove_All_Looping_Sounds(1);
Outtake_Play(20, 0, -1);
@@ -440,29 +435,29 @@ bool AIScriptClovis::GoalChanged(int currentGoalNumber, int newGoalNumber) {
Global_Variable_Decrement(51, 1);
}
if (Global_Variable_Query(kVariableChapter) == 5 && Actor_Query_In_Set(kActorDektora, kSetKP07)) {
- Non_Player_Actor_Combat_Mode_On(kActorDektora, 0, 0, 0, 19, 4, 7, 8, 0, 0, 100, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorDektora, kActorCombatStateIdle, false, kActorMcCoy, 19, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 10, 300, false);
}
if (Global_Variable_Query(kVariableChapter) == 5 && Actor_Query_In_Set(kActorZuben, kSetKP07)) {
- Non_Player_Actor_Combat_Mode_On(kActorZuben, 0, 0, 0, 19, 4, 7, 8, 0, 0, 100, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorZuben, kActorCombatStateIdle, false, kActorMcCoy, 19, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 10, 300, false);
}
if (Global_Variable_Query(kVariableChapter) == 5 && Actor_Query_In_Set(kActorSadik, kSetKP07)) {
- Non_Player_Actor_Combat_Mode_On(kActorSadik, 0, 1, 0, 19, 4, 7, 8, 0, 0, 100, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorSadik, kActorCombatStateIdle, true, kActorMcCoy, 19, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 10, 300, false);
}
if (Global_Variable_Query(kVariableChapter) == 5 && Actor_Query_In_Set(kActorIzo, kSetKP07)) {
- Non_Player_Actor_Combat_Mode_On(kActorIzo, 0, 0, 0, 19, 4, 7, 8, 0, 0, 100, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorIzo, kActorCombatStateIdle, false, kActorMcCoy, 19, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 10, 300, false);
}
if (Global_Variable_Query(kVariableChapter) == 5 && Actor_Query_In_Set(kActorGordo, kSetKP07)) {
- Non_Player_Actor_Combat_Mode_On(kActorGordo, 0, 1, 0, 19, 4, 7, 8, 0, 0, 100, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorGordo, kActorCombatStateIdle, true, kActorMcCoy, 19, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 10, 300, false);
}
if (Global_Variable_Query(kVariableChapter) == 5 && Actor_Query_In_Set(kActorClovis, kSetKP07)) {
- Non_Player_Actor_Combat_Mode_On(kActorClovis, 0, 0, 0, 19, 4, 7, 8, 0, 0, 100, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorClovis, kActorCombatStateIdle, false, kActorMcCoy, 19, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 10, 300, false);
}
return true;
case 518:
Actor_Set_At_XYZ(kActorClovis, 84.85f, -50.56f, -68.87f, 800);
- Actor_Face_Heading(kActorClovis, 1022, 0);
- Actor_Set_Targetable(kActorClovis, 1);
+ Actor_Face_Heading(kActorClovis, 1022, false);
+ Actor_Set_Targetable(kActorClovis, true);
Game_Flag_Set(685);
someAnim();
return true;
@@ -702,7 +697,7 @@ bool AIScriptClovis::UpdateAnimation(int *animation, int *frame) {
if (!_animationFrame && _flag) {
_animationState = 2;
_animationFrame = 0;
- Actor_Change_Animation_Mode(kActorClovis, 53);
+ Actor_Change_Animation_Mode(kActorClovis, kAnimationModeSit);
} else {
_animationFrame++;
if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(241)) {
@@ -1163,11 +1158,11 @@ bool AIScriptClovis::UpdateAnimation(int *animation, int *frame) {
bool AIScriptClovis::ChangeAnimationMode(int mode) {
switch (mode) {
- case 0:
+ case kAnimationModeIdle:
if (!Game_Flag_Query(685)) {
switch (_animationState) {
case 2:
- Actor_Change_Animation_Mode(kActorClovis, 53);
+ Actor_Change_Animation_Mode(kActorClovis, kAnimationModeSit);
break;
case 4:
break;
@@ -1199,17 +1194,17 @@ bool AIScriptClovis::ChangeAnimationMode(int mode) {
_animationFrame = 0;
break;
- case 1:
+ case kAnimationModeWalk:
_animationState = 21;
_animationFrame = 0;
break;
- case 2:
+ case kAnimationModeRun:
_animationState = 22;
_animationFrame = 0;
break;
- case 3:
+ case kAnimationModeTalk:
case 9:
if (Game_Flag_Query(685)) {
_animationFrame = 0;
@@ -1224,7 +1219,7 @@ bool AIScriptClovis::ChangeAnimationMode(int mode) {
}
break;
- case 4:
+ case kAnimationModeCombatIdle:
switch (_animationState) {
case 13:
case 14:
@@ -1244,28 +1239,17 @@ bool AIScriptClovis::ChangeAnimationMode(int mode) {
}
break;
- case 5:
- case 18:
- case 19:
- case 23:
- case 24:
- case 25:
- case 26:
- case 27:
- case 28:
- break;
-
- case 6:
+ case kAnimationModeCombatAttack:
_animationState = 16;
_animationFrame = 0;
break;
- case 7:
+ case kAnimationModeCombatWalk:
_animationState = 21;
_animationFrame = 0;
break;
- case 8:
+ case kAnimationModeCombatRun:
_animationState = 22;
_animationFrame = 0;
break;
@@ -1331,7 +1315,7 @@ bool AIScriptClovis::ChangeAnimationMode(int mode) {
_animationFrame = 0;
break;
- case 21:
+ case kAnimationModeHit:
if ((unsigned int)(_animationState - 13) > 3) {
if ((unsigned int)(_animationState - 32) > 8) {
if (Random_Query(0, 1)) {
@@ -1354,7 +1338,7 @@ bool AIScriptClovis::ChangeAnimationMode(int mode) {
}
break;
- case 22:
+ case kAnimationModeCombatHit:
if (Random_Query(0, 1)) {
_animationState = 17;
} else {
@@ -1379,12 +1363,12 @@ bool AIScriptClovis::ChangeAnimationMode(int mode) {
_animationFrame = Slice_Animation_Query_Number_Of_Frames(226) - 1;
break;
- case 48:
+ case kAnimationModeDie:
_animationState = 41;
_animationFrame = 0;
break;
- case 53:
+ case kAnimationModeSit:
switch (_animationState) {
case 4:
case 5:
@@ -1465,7 +1449,7 @@ void AIScriptClovis::someAnim() {
switch (_animationState) {
case 2:
- Actor_Change_Animation_Mode(kActorClovis, 53);
+ Actor_Change_Animation_Mode(kActorClovis, kAnimationModeSit);
break;
case 4:
break;
diff --git a/engines/bladerunner/script/ai/dektora.cpp b/engines/bladerunner/script/ai/dektora.cpp
index 905c3d16da..28bdf3c83d 100644
--- a/engines/bladerunner/script/ai/dektora.cpp
+++ b/engines/bladerunner/script/ai/dektora.cpp
@@ -280,7 +280,7 @@ void AIScriptDektora::Retired(int byActorId) {
}
if (byActorId == kActorSteele && Actor_Query_In_Set(kActorSteele, kSetHF06) && Actor_Query_In_Set(kActorMcCoy, kSetHF06)) {
- Non_Player_Actor_Combat_Mode_On(kActorSteele, 3, 1, 0, 15, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorSteele, kActorCombatStateUncover, true, kActorMcCoy, 15, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 25, 300, false);
}
if (Actor_Query_In_Set(kActorDektora, kSetKP07)) {
@@ -290,8 +290,8 @@ void AIScriptDektora::Retired(int byActorId) {
if (!Global_Variable_Query(51)) {
Player_Loses_Control();
Delay(2000);
- Player_Set_Combat_Mode(0);
- Loop_Actor_Walk_To_XYZ(0, -12.0, -41.580002, 72.0, 0, 1, 0, 0);
+ Player_Set_Combat_Mode(false);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, -12.0f, -41.58f, 72.0f, 0, true, false, 0);
Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
Ambient_Sounds_Remove_All_Looping_Sounds(1);
Game_Flag_Set(579);
@@ -1095,11 +1095,11 @@ void AIScriptDektora::checkCombat() {
&& Global_Variable_Query(kVariableChapter) == 5
&& Actor_Query_Goal_Number(kActorDektora) != 450) {
if (Global_Variable_Query(kVariableAffectionTowards) == 2) {
- Global_Variable_Set(45, 0);
+ Global_Variable_Set(kVariableAffectionTowards, 0);
}
Actor_Set_Goal_Number(kActorDektora, 450);
- Non_Player_Actor_Combat_Mode_On(kActorDektora, 0, 0, kActorMcCoy, 4, 4, 7, 8, 0, -1, -1, 20, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorDektora, kActorCombatStateIdle, false, kActorMcCoy, 4, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, -1, -1, 20, 300, false);
}
}
diff --git a/engines/bladerunner/script/ai/early_q.cpp b/engines/bladerunner/script/ai/early_q.cpp
new file mode 100644
index 0000000000..180493fb6e
--- /dev/null
+++ b/engines/bladerunner/script/ai/early_q.cpp
@@ -0,0 +1,1037 @@
+/* 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 "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptEarlyQ::AIScriptEarlyQ(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+ _var1 = 0;
+ _var2 = 0;
+ _var3 = 1;
+ _flag = false;
+}
+
+void AIScriptEarlyQ::Initialize() {
+ _animationFrame = 0;
+ _animationState = 0;
+ _animationStateNext = 0;
+ _animationNext = 0;
+
+ _var1 = 0;
+ _var2 = 0;
+ _var3 = 1;
+ _flag = 0;
+}
+
+bool AIScriptEarlyQ::Update() {
+ if (Global_Variable_Query(kVariableChapter) != 1 || Game_Flag_Query(490)) {
+ if (Global_Variable_Query(kVariableChapter) != 2 || Game_Flag_Query(491)) {
+ if (Global_Variable_Query(kVariableChapter) != 3 || Game_Flag_Query(564)) {
+ return false;
+ } else {
+ Game_Flag_Set(564);
+ Actor_Put_In_Set(kActorEarlyQ, kSetFreeSlotH);
+ Actor_Set_At_Waypoint(kActorEarlyQ, 40, 0);
+ Actor_Set_Goal_Number(kActorEarlyQ, 200);
+ }
+ } else {
+ Game_Flag_Set(491);
+ Actor_Put_In_Set(kActorEarlyQ, kSetFreeSlotH);
+ Actor_Set_At_Waypoint(kActorEarlyQ, 40, 0);
+ Actor_Set_Goal_Number(kActorEarlyQ, 100);
+ }
+ } else {
+ Game_Flag_Set(490);
+ Actor_Put_In_Set(kActorEarlyQ, kSetFreeSlotH);
+ Actor_Set_At_Waypoint(kActorEarlyQ, 40, 0);
+ Actor_Set_Goal_Number(kActorEarlyQ, 0);
+ }
+
+ return true;
+}
+
+void AIScriptEarlyQ::TimerExpired(int timer) {
+ if (Actor_Query_Goal_Number(kActorEarlyQ) == 221 && !timer) {
+ if (Player_Query_Current_Scene() == 58) {
+ AI_Countdown_Timer_Reset(kActorEarlyQ, 0);
+ Actor_Set_Goal_Number(kActorEarlyQ, 222);
+ } else {
+ Actor_Set_Goal_Number(kActorEarlyQ, 220);
+ }
+ }
+ if (Actor_Query_Goal_Number(kActorEarlyQ) != 205 || timer) {
+ if (Actor_Query_Goal_Number(kActorEarlyQ) == 211 && timer == 1) {
+ AI_Countdown_Timer_Reset(kActorEarlyQ, 1);
+ Player_Loses_Control();
+ Actor_Change_Animation_Mode(kActorEarlyQ, 29);
+ Delay(2500);
+ Actor_Face_Actor(kActorEarlyQ, kActorMcCoy, 1);
+ Actor_Change_Animation_Mode(kActorEarlyQ, 6);
+ Delay(100);
+ _vm->_aiScripts->callChangeAnimationMode(kActorMcCoy, 22);
+ Delay(250);
+ _vm->_aiScripts->callChangeAnimationMode(kActorMcCoy, 48);
+ Actor_Retired_Here(kActorMcCoy, 12, 12, 1, -1);
+ } else {
+ return; //false;
+ }
+ } else {
+ Player_Loses_Control();
+ AI_Countdown_Timer_Reset(kActorEarlyQ, 0);
+ Actor_Set_Goal_Number(kActorEarlyQ, 215);
+ }
+
+ return; //true;
+}
+
+void AIScriptEarlyQ::CompletedMovementTrack() {
+ switch (Actor_Query_Goal_Number(kActorEarlyQ)) {
+ case 0:
+ if (Random_Query(1, 2) == 1) {
+ Actor_Set_Goal_Number(kActorEarlyQ, 1);
+ } else {
+ Actor_Set_Goal_Number(kActorEarlyQ, 2);
+ }
+ break;
+
+ case 1:
+ case 2:
+ Actor_Set_Goal_Number(kActorEarlyQ, 0);
+ break;
+
+ case 100:
+ if (Random_Query(1, 2) != 1) {
+ Actor_Set_Goal_Number(kActorEarlyQ, 102);
+ break;
+ }
+ Actor_Set_Goal_Number(kActorEarlyQ, 101);
+ break;
+
+ case 101:
+ Actor_Set_Goal_Number(kActorEarlyQ, 100);
+ break;
+
+ case 102:
+ Actor_Set_Goal_Number(kActorEarlyQ, 100);
+ break;
+
+ case 201:
+ Game_Flag_Set(569);
+ Player_Set_Combat_Mode(0);
+ Actor_Set_Targetable(kActorEarlyQ, 1);
+ Actor_Set_Goal_Number(kActorEarlyQ, 202);
+ break;
+
+ case 203:
+ Actor_Set_Goal_Number(kActorEarlyQ, 204);
+ break;
+
+ case 222:
+ Actor_Set_Goal_Number(kActorEarlyQ, 223);
+ return; //false;
+
+ case 230:
+ Actor_Set_Goal_Number(kActorEarlyQ, 200);
+ return; //false;
+
+ default:
+ return; //false;
+ }
+
+ return; //true;
+}
+
+void AIScriptEarlyQ::ReceivedClue(int clueId, int fromActorId) {
+ //return false;
+}
+
+void AIScriptEarlyQ::ClickedByPlayer() {
+ //return false;
+}
+
+void AIScriptEarlyQ::EnteredScene(int sceneId) {
+ // return false;
+}
+
+void AIScriptEarlyQ::OtherAgentEnteredThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptEarlyQ::OtherAgentExitedThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptEarlyQ::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+ if (Game_Flag_Query(569) != 1 || otherActorId || combatMode != 1 || Game_Flag_Query(609)) {
+ if (Actor_Query_Goal_Number(kActorEarlyQ) != 211 || otherActorId || combatMode) {
+ return; //false;
+ } else {
+ if (Game_Flag_Query(565) == 1) {
+ Game_Flag_Reset(565);
+ }
+ AI_Countdown_Timer_Reset(kActorEarlyQ, 1);
+ Actor_Set_Goal_Number(kActorEarlyQ, 213);
+ }
+ } else {
+ if (!Game_Flag_Query(565)) {
+ Game_Flag_Set(565);
+ }
+ Game_Flag_Set(609);
+ AI_Countdown_Timer_Reset(kActorEarlyQ, 0);
+ Actor_Set_Goal_Number(kActorEarlyQ, 206);
+ }
+
+ return; //true;
+}
+
+void AIScriptEarlyQ::ShotAtAndMissed() {
+ if (Actor_Query_Goal_Number(kActorEarlyQ) != 211)
+ return; //false;
+
+ Actor_Set_Goal_Number(kActorEarlyQ, 216);
+ return; //true;
+}
+
+bool AIScriptEarlyQ::ShotAtAndHit() {
+ if (Actor_Query_Goal_Number(kActorEarlyQ) < 201 || Actor_Query_Goal_Number(kActorEarlyQ) > 217)
+ return 0;
+
+ Actor_Set_Goal_Number(kActorEarlyQ, 216);
+
+ return true;
+}
+
+void AIScriptEarlyQ::Retired(int byActorId) {
+ // return false;
+}
+
+int AIScriptEarlyQ::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+ return 0;
+}
+
+bool AIScriptEarlyQ::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+ switch (newGoalNumber) {
+ case 0:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 40, 0);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ case 1:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 291, 0);
+ AI_Movement_Track_Append(kActorEarlyQ, 285, 0);
+ AI_Movement_Track_Append(kActorEarlyQ, 292, 30);
+ AI_Movement_Track_Append(kActorEarlyQ, 293, 30);
+ AI_Movement_Track_Append(kActorEarlyQ, 294, 30);
+ AI_Movement_Track_Append(kActorEarlyQ, 295, 30);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ case 2:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 40, 120);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ case 100:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 40, 0);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ case 101:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 291, 0);
+ AI_Movement_Track_Append(kActorEarlyQ, 285, 0);
+ AI_Movement_Track_Append(kActorEarlyQ, 292, 30);
+ AI_Movement_Track_Append(kActorEarlyQ, 293, 30);
+ AI_Movement_Track_Append(kActorEarlyQ, 294, 30);
+ AI_Movement_Track_Append(kActorEarlyQ, 295, 30);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ case 102:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 40, 120);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ case 200:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ Actor_Put_In_Set(kActorEarlyQ, kSetFreeSlotH);
+ Actor_Set_At_Waypoint(kActorEarlyQ, 40, 0);
+ if (Game_Flag_Query(47) == 1 && Game_Flag_Query(592) && Game_Flag_Query(593)) {
+ Actor_Set_Goal_Number(kActorEarlyQ, 220);
+ } else if (Game_Flag_Query(47)) {
+ Actor_Set_Goal_Number(kActorEarlyQ, 230);
+ } else {
+ Actor_Set_Goal_Number(kActorEarlyQ, 220);
+ }
+ break;
+
+ case 201:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 40, 0);
+ AI_Movement_Track_Append(kActorEarlyQ, 322, 0);
+ AI_Movement_Track_Append(kActorEarlyQ, 354, 0);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ case 203:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 355, 0);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ Actor_Face_Object(kActorMcCoy, "BAR", 1);
+ break;
+
+ case 205:
+ Loop_Actor_Walk_To_Actor(kActorEarlyQ, 0, 36, 0, 0);
+ AI_Countdown_Timer_Reset(kActorEarlyQ, 0);
+ AI_Countdown_Timer_Start(kActorEarlyQ, 0, 4);
+ break;
+
+ case 206:
+ Player_Set_Combat_Mode(kActorSteele);
+ Actor_Face_Actor(kActorEarlyQ, kActorMcCoy, 1);
+ Actor_Face_Actor(kActorMcCoy, kActorEarlyQ, 1);
+ Actor_Change_Animation_Mode(kActorMcCoy, kAnimationModeCombatIdle);
+ _vm->_aiScripts->callChangeAnimationMode(kActorMcCoy, 5);
+ Actor_Says(kActorEarlyQ, 130, 3);
+ Actor_Says(kActorMcCoy, 3400, 5);
+ Actor_Says_With_Pause(kActorEarlyQ, 140, 1.0, 3);
+ Actor_Says_With_Pause(kActorEarlyQ, 150, 1.0, 3);
+ Actor_Says(kActorMcCoy, 3405, 5);
+ Actor_Says(kActorEarlyQ, 160, 3);
+ Actor_Says(kActorMcCoy, 3410, 5);
+ _vm->_aiScripts->callChangeAnimationMode(kActorMcCoy, 4);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, 31.22f, 0.0f, 267.51f, 0, 1, 0, 0);
+ Actor_Set_Goal_Number(kActorEarlyQ, 207);
+ break;
+
+ case 208:
+ if (Game_Flag_Query(374) == 1) {
+ Actor_Set_Goal_Number(kActorEarlyQ, 210);
+ } else {
+ Actor_Set_Goal_Number(kActorEarlyQ, 209);
+ }
+ break;
+
+ case 210:
+ Actor_Set_Targetable(kActorEarlyQ, 0);
+ Game_Flag_Set(606);
+ Delay(3500);
+ Actor_Change_Animation_Mode(kActorEarlyQ, 76);
+ Delay(2000);
+ Actor_Set_At_XYZ(kActorEarlyQ, 109.0, 0.0, 374.0, 0);
+ Actor_Retired_Here(kActorEarlyQ, 12, 12, 1, -1);
+ Actor_Voice_Over(4180, kActorVoiceOver);
+ Scene_Exits_Enable();
+ break;
+
+ case 211:
+ AI_Countdown_Timer_Reset(kActorEarlyQ, 1);
+ AI_Countdown_Timer_Start(kActorEarlyQ, 1, 5);
+ break;
+
+ case 212:
+ Actor_Says(kActorEarlyQ, 0, 3);
+ Actor_Says(kActorEarlyQ, 10, 3);
+ Actor_Says(kActorEarlyQ, 20, 3);
+ Actor_Clue_Lose(kActorMcCoy, 89);
+ Scene_Exits_Enable();
+ Player_Gains_Control();
+ Game_Flag_Set(627);
+ Actor_Set_Goal_Number(kActorHanoi, 220);
+ break;
+
+ case 215:
+ if (Actor_Query_Inch_Distance_From_Actor(kActorMcCoy, kActorEarlyQ) > 36) {
+ Loop_Actor_Walk_To_Actor(kActorEarlyQ, kActorMcCoy, 36, kActorMcCoy, kActorMcCoy);
+ }
+ Actor_Face_Actor(kActorMcCoy, kActorEarlyQ, 1);
+ Actor_Face_Actor(kActorEarlyQ, kActorMcCoy, 1);
+ Actor_Change_Animation_Mode(kActorEarlyQ, 23);
+ Scene_Loop_Start_Special(2, 2, 0);
+ Ambient_Sounds_Play_Sound(582, 50, 99, 0, 0);
+ Actor_Set_Goal_Number(kActorMcCoy, 220);
+ break;
+
+ case 216:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ Actor_Change_Animation_Mode(kActorEarlyQ, 48);
+ Delay(250);
+ Actor_Set_At_XYZ(kActorEarlyQ, 109.0, 0.0, 374.0, 0);
+ Actor_Set_Goal_Number(kActorHanoi, 240);
+ Player_Set_Combat_Mode(0);
+ break;
+
+ case 217:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 354, 0);
+ AI_Movement_Track_Append(kActorEarlyQ, 322, 0);
+ AI_Movement_Track_Append(kActorEarlyQ, 40, 0);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ case 220:
+ if (Player_Query_Current_Set() == 13) {
+ Actor_Set_Goal_Number(kActorEarlyQ, 230);
+ } else {
+ Actor_Put_In_Set(kActorEarlyQ, kSetNR05_NR08);
+ Actor_Set_At_XYZ(kActorEarlyQ, -671.56f, 0.0f, -287.02f, 849);
+ }
+ break;
+
+ case 221:
+ AI_Countdown_Timer_Reset(kActorEarlyQ, 0);
+ AI_Countdown_Timer_Start(kActorEarlyQ, 0, 20);
+ break;
+
+ case 222:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Movement_Track_Append(kActorEarlyQ, 429, 0);
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ case 223:
+ if (Player_Query_Current_Scene() == 58) {
+ Actor_Says(kActorEarlyQ, 670, 3);
+ Actor_Says(kActorEarlyQ, 690, 3);
+ Actor_Set_Goal_Number(kActorDektora, 210);
+ Actor_Set_Goal_Number(kActorEarlyQ, 224);
+ Actor_Set_Goal_Number(kActorHanoi, 230);
+ } else {
+ Actor_Set_Goal_Number(kActorEarlyQ, 220);
+ }
+ break;
+
+ case 224:
+ Game_Flag_Set(620);
+ break;
+
+ case 229:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ AI_Countdown_Timer_Reset(kActorEarlyQ, 0);
+ break;
+
+ case 230:
+ AI_Movement_Track_Flush(kActorEarlyQ);
+ if (Random_Query(1, 3) > 1) {
+ AI_Movement_Track_Append(kActorEarlyQ, 322, Random_Query(15, 30));
+ AI_Movement_Track_Append(kActorEarlyQ, 39, Random_Query(15, 45));
+ AI_Movement_Track_Append(kActorEarlyQ, 40, Random_Query(15, 30));
+ } else {
+ AI_Movement_Track_Append(kActorEarlyQ, 322, Random_Query(5, 15));
+ AI_Movement_Track_Append(kActorEarlyQ, 39, Random_Query(5, 15));
+ AI_Movement_Track_Append(kActorEarlyQ, 40, Random_Query(5, 15));
+ AI_Movement_Track_Append(kActorEarlyQ, 39, Random_Query(5, 15));
+ AI_Movement_Track_Append(kActorEarlyQ, 34, Random_Query(10, 20));
+ }
+ AI_Movement_Track_Repeat(kActorEarlyQ);
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool AIScriptEarlyQ::UpdateAnimation(int *animation, int *frame) {
+ switch (_animationState) {
+ case 0:
+ if (_var2 == 1) {
+ *animation = 370;
+ if (_var1) {
+ _var1--;
+ } else {
+ if (++_animationFrame == 6) {
+ _var1 = Random_Query(8, 15);
+ }
+ if (_animationFrame < 6) {
+ _var1 = 1;
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(370)) {
+ _animationFrame = 0;
+ _var2 = 0;
+ }
+ }
+ } else if (_var2 == 0) {
+ *animation = 369;
+ if (_var1) {
+ _var1--;
+ if (!Random_Query(0, 6)) {
+ _var3 = -_var3;
+ }
+ } else {
+ _animationFrame += _var3;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(369)) {
+ _animationFrame = 0;
+ }
+ if (_animationFrame < 0) {
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(369) - 1;
+ }
+ _var1 = Random_Query(0, 1);
+ if (!_animationFrame) {
+ if (!Random_Query(0, 3)) {
+ _var2 = 1;
+ }
+ }
+ if (!_animationFrame || _animationFrame == 5) {
+ if (Random_Query(0, 1)) {
+ _var1 = Random_Query(2, 8);
+ }
+ }
+ }
+ }
+ break;
+
+ case 1:
+ *animation = 381;
+ _animationFrame++;
+ if (_animationFrame == 18) {
+ Ambient_Sounds_Play_Sound(255, 99, 0, 0, 20);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+ Actor_Change_Animation_Mode(kActorEarlyQ, 74);
+ _animationFrame = 0;
+ _animationState = 2;
+ *animation = 382;
+ }
+ break;
+
+ case 2:
+ *animation = 382;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(382)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 3:
+ *animation = 371;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(371)) {
+ *animation = 369;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorEarlyQ, 0);
+ }
+ break;
+
+ case 4:
+ *animation = 368;
+ if (_animationFrame < Slice_Animation_Query_Number_Of_Frames(368) - 1) {
+ _animationFrame++;
+ }
+ break;
+
+ case 5:
+ *animation = 365;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(365)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 6:
+ *animation = 361;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(361)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 7:
+ *animation = 383;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(383)) {
+ _animationFrame = 0;
+ _animationState = 9;
+ *animation = 384;
+ }
+ break;
+
+ case 8:
+ *animation = 387;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(387)) {
+ *animation = 369;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 9:
+ *animation = 384;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(384)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 10:
+ *animation = 385;
+ if (!_animationFrame && _flag) {
+ _flag = 0;
+ _animationState = 9;
+ _var2 = 0;
+ *animation = 384;
+ Actor_Change_Animation_Mode(kActorEarlyQ, 53);
+ } else {
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(385)) {
+ _animationFrame = 0;
+ }
+ }
+ break;
+
+ case 11:
+ *animation = 386;
+ if (_animationFrame < Slice_Animation_Query_Number_Of_Frames(386) - 1) {
+ _animationFrame++;
+ }
+ if (_animationFrame == 1) {
+ Ambient_Sounds_Play_Sound(555, 59, 0, 0, 20);
+ }
+ if (_animationFrame == 8) {
+ Ambient_Sounds_Play_Sound(254, 47, 0, 0, 20);
+ }
+ if (_animationFrame == 11) {
+ Ambient_Sounds_Play_Sound(560, 27, 0, 0, 20);
+ }
+ if (_animationFrame == 14) {
+ Ambient_Sounds_Play_Sound(206, 41, 0, 0, 20);
+ }
+ break;
+
+ case 12:
+ *animation = 360;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(360)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 13:
+ *animation = 362;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(362)) {
+ _animationFrame = 0;
+ _animationState = 12;
+ *animation = 360;
+ }
+ break;
+
+ case 14:
+ *animation = 363;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(363)) {
+ *animation = 369;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 15:
+ *animation = 364;
+ _animationFrame++;
+ if (_animationFrame == 2) {
+ Ambient_Sounds_Play_Sound(12, 60, 0, 0, 20);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(364)) {
+ _animationFrame = 0;
+ _animationState = 12;
+ *animation = 360;
+ Actor_Change_Animation_Mode(kActorEarlyQ, 4);
+ }
+ break;
+
+ case 16:
+ *animation = 366;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(366)) {
+ *animation = 369;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorEarlyQ, 0);
+ }
+ break;
+
+ case 17:
+ *animation = 367;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(367)) {
+ *animation = 369;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorEarlyQ, 0);
+ }
+ break;
+
+ case 18:
+ *animation = 366;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(366)) {
+ *animation = 369;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorEarlyQ, 0);
+ }
+ break;
+
+ case 19:
+ *animation = 367;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(367)) {
+ *animation = 369;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorEarlyQ, 0);
+ }
+ break;
+
+ case 20:
+ *animation = 372;
+ if (!_animationFrame && _flag) {
+ *animation = 369;
+ _animationFrame = 0;
+ _flag = 0;
+ _animationState = 0;
+ } else {
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(372)) {
+ _animationFrame = 0;
+ }
+ }
+ break;
+
+ case 21:
+ *animation = 373;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(373)) {
+ _animationFrame = 0;
+ _animationState = 20;
+ *animation = 372;
+ }
+ break;
+
+ case 22:
+ *animation = 374;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(374)) {
+ _animationFrame = 0;
+ _animationState = 20;
+ *animation = 372;
+ }
+ break;
+
+ case 23:
+ *animation = 375;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(375)) {
+ _animationFrame = 0;
+ _animationState = 20;
+ *animation = 372;
+ }
+ break;
+
+ case 24:
+ *animation = 376;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(376)) {
+ _animationFrame = 0;
+ _animationState = 20;
+ *animation = 372;
+ }
+ break;
+
+ case 25:
+ *animation = 377;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(377)) {
+ _animationFrame = 0;
+ _animationState = 20;
+ *animation = 372;
+ }
+ break;
+
+ case 26:
+ *animation = 378;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(378)) {
+ _animationFrame = 0;
+ _animationState = 20;
+ *animation = 372;
+ }
+ break;
+
+ case 27:
+ *animation = 379;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(379)) {
+ _animationFrame = 0;
+ _animationState = 20;
+ *animation = 372;
+ }
+ break;
+
+ case 28:
+ *animation = 380;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(380)) {
+ _animationFrame = 0;
+ _animationState = 20;
+ *animation = 372;
+ }
+ break;
+
+ default:
+ break;
+ }
+ *frame = _animationFrame;
+
+ return true;
+}
+
+bool AIScriptEarlyQ::ChangeAnimationMode(int mode) {
+ switch (mode) {
+ case 0:
+ switch (_animationState) {
+ case 1:
+ Actor_Change_Animation_Mode(kActorEarlyQ, 73);
+ break;
+
+ case 2:
+ Actor_Change_Animation_Mode(kActorEarlyQ, 74);
+ break;
+
+ case 9:
+ Actor_Change_Animation_Mode(kActorEarlyQ, 29);
+ break;
+
+ case 10:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ _flag = 1;
+ break;
+
+ case 12:
+ case 13:
+ case 15:
+ _animationState = 14;
+ _animationFrame = 0;
+ break;
+
+ case 14:
+ return 1;
+
+ default:
+ _animationState = 0;
+ _animationFrame = 0;
+ break;
+ }
+ break;
+
+ case 1:
+ _animationState = 5;
+ _animationFrame = 0;
+ break;
+
+ case 3:
+ _animationState = 20;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 4:
+ if ((unsigned int)(_animationState - 12) > 3 || (_animationState != 12 && _animationState != 13 && _animationState != 15)) {
+ _animationState = 13;
+ _animationFrame = 0;
+ }
+ break;
+
+ case 6:
+ _animationState = 15;
+ _animationFrame = 0;
+ break;
+
+ case 7:
+ _animationState = 6;
+ _animationFrame = 0;
+ break;
+
+ case 12:
+ _animationState = 21;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 13:
+ _animationState = 22;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 14:
+ _animationState = 23;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 15:
+ _animationState = 24;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 16:
+ _animationState = 25;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 17:
+ _animationState = 26;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 18:
+ _animationState = 27;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 19:
+ _animationState = 28;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 21:
+ if ((unsigned int)(_animationState - 12) > 3 || (_animationState != 12 && _animationState != 13 && _animationState != 15)) {
+ if (Random_Query(0, 1)) {
+ _animationState = 16;
+ } else {
+ _animationState = 17;
+ }
+ _animationFrame = 0;
+ } else {
+ if (Random_Query(0, 1)) {
+ _animationState = 18;
+ } else {
+ _animationState = 19;
+ }
+ _animationFrame = 0;
+ }
+ break;
+
+ case 23:
+ _animationState = 3;
+ _animationFrame = 0;
+ break;
+
+ case 29:
+ _animationState = 8;
+ _animationFrame = 0;
+ break;
+
+ case 30:
+ _animationState = 10;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 48:
+ _animationState = 4;
+ _animationFrame = 0;
+ break;
+
+ case 53:
+ _animationState = 9;
+ _animationFrame = 0;
+ break;
+
+ case 73:
+ if (_animationState != 1) {
+ _animationState = 1;
+ _animationFrame = 0;
+ }
+ break;
+
+ case 74:
+ if (_animationState != 2) {
+ _animationState = 2;
+ _animationFrame = 0;
+ }
+ break;
+
+ case 76:
+ _animationState = 11;
+ _animationFrame = 0;
+ break;
+
+ case 85:
+ _animationState = 7;
+ _animationFrame = 0;
+ break;
+
+ default:
+ return true;
+ }
+
+ return true;
+}
+
+void AIScriptEarlyQ::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ *animationState = _animationState;
+ *animationFrame = _animationFrame;
+ *animationStateNext = _animationStateNext;
+ *animationNext = _animationNext;
+}
+
+void AIScriptEarlyQ::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ _animationState = animationState;
+ _animationFrame = animationFrame;
+ _animationStateNext = animationStateNext;
+ _animationNext = animationNext;
+}
+
+bool AIScriptEarlyQ::ReachedMovementTrackWaypoint(int waypointId) {
+ return true;
+}
+
+void AIScriptEarlyQ::FledCombat() {
+ // return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/free_slot_a.cpp b/engines/bladerunner/script/ai/free_slot_a.cpp
new file mode 100644
index 0000000000..b017a9e3f2
--- /dev/null
+++ b/engines/bladerunner/script/ai/free_slot_a.cpp
@@ -0,0 +1,659 @@
+/* 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 "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptFreeSlotA::AIScriptFreeSlotA(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+ _var1 = 0;
+ _var2 = 1;
+ _var3 = 0.0f;
+ _var4 = 0.0f; // not initialized in original
+ _var5 = 0.0f; // not initialized in original
+}
+
+void AIScriptFreeSlotA::Initialize() {
+ _animationFrame = 0;
+ _animationState = 0;
+ _animationStateNext = 0;
+ _animationNext = 0;
+
+ _var1 = 0;
+ _var2 = 1;
+ _var3 = 0.0f;
+ _var4 = 0.0f; // not initialized in original
+ _var5 = 0.0f; // not initialized in original
+
+ World_Waypoint_Set(525, 45, -780.0f, -615.49f, 2611.0f);
+ World_Waypoint_Set(526, 45, -780.0f, -615.49f, 2759.0f);
+}
+
+bool AIScriptFreeSlotA::Update() {
+ switch (Global_Variable_Query(kVariableChapter)) {
+ case 4:
+ if (Actor_Query_Which_Set_In(kActorMcCoy) == kSceneUG02 && Actor_Query_Which_Set_In(kActorFreeSlotA) == kSceneUG02) {
+ int goal = Actor_Query_Goal_Number(kActorFreeSlotA);
+ if ((goal == 302 || goal == 303) && Actor_Query_Inch_Distance_From_Actor(kActorFreeSlotA, kActorMcCoy) <= 48) {
+ Actor_Set_Goal_Number(kActorFreeSlotA, 304);
+ } else if (goal == 309) {
+ float x, y, z;
+
+ Actor_Query_XYZ(kActorMcCoy, &x, &y, &z);
+ _var4 += _var3;
+ if (_var5 < _var4) {
+ _var3 -= 0.2f;
+ } else {
+ _var4 = _var5;
+ Actor_Set_Goal_Number(kActorFreeSlotA, 0);
+ }
+ Actor_Set_At_XYZ(kActorFreeSlotA, x, _var4, z, Actor_Query_Facing_1024(kActorFreeSlotA));
+ }
+ } else {
+ switch (Actor_Query_Goal_Number(kActorFreeSlotA)) {
+ case 306:
+ if (Actor_Query_Which_Set_In(kActorFreeSlotA) == Player_Query_Current_Set()
+ && Actor_Query_Inch_Distance_From_Actor(kActorFreeSlotA, kActorMcCoy) <= 48) {
+ Actor_Set_Goal_Number(kActorFreeSlotA, 308);
+ }
+ break;
+
+ case 308:
+ if (Actor_Query_Which_Set_In(kActorFreeSlotA) != Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorFreeSlotA, 306);
+ }
+ break;
+
+ case 599:
+ if (Actor_Query_Which_Set_In(kActorFreeSlotA) != Player_Query_Current_Set()) {
+ Game_Flag_Reset(631);
+ Game_Flag_Reset(677);
+ Actor_Set_Goal_Number(kActorFreeSlotA, 0);
+ }
+ break;
+
+ default:
+ if (!Game_Flag_Query(631)) {
+ Game_Flag_Set(631);
+ Actor_Set_Goal_Number(kActorFreeSlotA, 306);
+ Actor_Set_Targetable(kActorFreeSlotA, 1);
+ }
+ }
+ }
+ return true;
+
+ case 5:
+ if (Actor_Query_Goal_Number(kActorFreeSlotA) < 400) {
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ Actor_Set_Goal_Number(kActorFreeSlotA, 400);
+ } else if (Actor_Query_Goal_Number(kActorFreeSlotA) == 405 && Actor_Query_Which_Set_In(kActorMcCoy) == kSceneKP05) {
+ Actor_Set_Targetable(kActorFreeSlotA, 1);
+ Actor_Set_Goal_Number(kActorFreeSlotA, 406);
+ }
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+void AIScriptFreeSlotA::TimerExpired(int timer) {
+ //return false;
+}
+
+void AIScriptFreeSlotA::CompletedMovementTrack() {
+ switch (Actor_Query_Goal_Number(kActorFreeSlotA)) {
+ case 301:
+ Actor_Set_Goal_Number(kActorFreeSlotA, 302);
+ break;
+
+ case 302:
+ Actor_Set_Goal_Number(kActorFreeSlotA, 303);
+ break;
+
+ case 303:
+ Actor_Set_Goal_Number(kActorFreeSlotA, 300);
+ break;
+
+ case 306:
+ Actor_Set_Goal_Number(kActorFreeSlotA, 307);
+ break;
+
+ case 307:
+ Actor_Set_Goal_Number(kActorFreeSlotA, 306);
+ break;
+
+ case 400:
+ Actor_Set_Goal_Number(kActorFreeSlotA, 405);
+ break;
+
+ case 406:
+ Non_Player_Actor_Combat_Mode_On(kActorFreeSlotA, 0, 0, 0, 8, 4, 7, 8, 0, 0, 100, 5, 300, 0);
+ break;
+
+ default:
+ return; //false;
+ }
+
+ return; //true;
+}
+
+void AIScriptFreeSlotA::ReceivedClue(int clueId, int fromActorId) {
+ //return false;
+}
+
+void AIScriptFreeSlotA::ClickedByPlayer() {
+ if (Actor_Query_Goal_Number(kActorFreeSlotA) != 599) {
+ return; //false;
+ }
+
+ Actor_Face_Actor(kActorMcCoy, kActorFreeSlotA, 1);
+ if (Random_Query(1, 2) == 1) {
+ Actor_Says(kActorMcCoy, 8655, 16);
+ } else {
+ Actor_Says(kActorMcCoy, 8665, 16);
+ }
+}
+
+void AIScriptFreeSlotA::EnteredScene(int sceneId) {
+ // return false;
+}
+
+void AIScriptFreeSlotA::OtherAgentEnteredThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptFreeSlotA::OtherAgentExitedThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptFreeSlotA::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+ // return false;
+}
+
+void AIScriptFreeSlotA::ShotAtAndMissed() {
+ if (Actor_Query_In_Set(kActorFreeSlotA, kSetUG15) == 1)
+ calcHit();
+}
+
+bool AIScriptFreeSlotA::ShotAtAndHit() {
+ if (Actor_Query_In_Set(kActorFreeSlotA, kSetUG15) == 1) {
+ calcHit();
+ Actor_Set_Goal_Number(kActorFreeSlotA, 305);
+ return true;
+ }
+
+ return false;
+}
+
+void AIScriptFreeSlotA::Retired(int byActorId) {
+ Actor_Set_Goal_Number(kActorFreeSlotA, 599);
+}
+
+int AIScriptFreeSlotA::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+ return 0;
+}
+
+bool AIScriptFreeSlotA::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+ switch (newGoalNumber) {
+ case 300:
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ Actor_Change_Animation_Mode(kActorFreeSlotA, 0);
+ Actor_Set_Targetable(kActorFreeSlotA, 0);
+ break;
+
+ case 301:
+ Actor_Force_Stop_Walking(kActorMcCoy);
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ World_Waypoint_Set(444, 87, -48.75f, 44.66f, 87.57f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 444, 1);
+ AI_Movement_Track_Repeat(kActorFreeSlotA);
+ break;
+
+ case 302:
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ World_Waypoint_Set(444, 87, -237.0f, 48.07f, 208.0f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 444, 1);
+ AI_Movement_Track_Repeat(kActorFreeSlotA);
+ Actor_Set_Targetable(kActorFreeSlotA, 1);
+ break;
+
+ case 303:
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ World_Waypoint_Set(444, 87, 3.52f, 52.28f, 90.68f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 444, 0);
+ AI_Movement_Track_Repeat(kActorFreeSlotA);
+ break;
+
+ case 304:
+ Player_Loses_Control();
+ Actor_Force_Stop_Walking(kActorMcCoy);
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ Actor_Face_Actor(kActorFreeSlotA, kActorMcCoy, 1);
+ Actor_Change_Animation_Mode(kActorFreeSlotA, 6);
+ Actor_Change_Animation_Mode(kActorMcCoy, 48);
+ break;
+
+ case 305:
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ Actor_Set_Targetable(kActorFreeSlotA, 0);
+ Game_Flag_Set(676);
+ _animationState = 7;
+ _animationFrame = 0;
+ break;
+
+ case 306:
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ processGoal306();
+ AI_Movement_Track_Repeat(kActorFreeSlotA);
+ break;
+
+ case 307:
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ AI_Movement_Track_Append(kActorFreeSlotA, 39, 1);
+ AI_Movement_Track_Repeat(kActorFreeSlotA);
+ break;
+
+ case 308:
+ Actor_Set_Targetable(kActorFreeSlotA, 1);
+ Non_Player_Actor_Combat_Mode_On(kActorFreeSlotA, 0, 0, 0, 8, 4, 7, 8, 25, 0, 75, 5, 300, 0);
+ break;
+
+ case 309:
+ Actor_Force_Stop_Walking(kActorFreeSlotA);
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ _var4 = 52.46f;
+ _var3 = -4.0f;
+ _var5 = -10.0f;
+ if (_animationState != 7 && _animationState != 8) {
+ _animationState = 7;
+ _animationFrame = 0;
+ }
+ break;
+
+ case 310:
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ Actor_Put_In_Set(kActorFreeSlotA, kSetUG15);
+ Actor_Set_At_XYZ(kActorFreeSlotA, 3.52f, 52.28f, 90.68f, 700);
+ Actor_Set_Goal_Number(kActorFreeSlotA, 300);
+ break;
+
+ case 400:
+ AI_Movement_Track_Append(kActorFreeSlotA, 39, 0);
+ AI_Movement_Track_Repeat(kActorFreeSlotA);
+ break;
+
+ case 406:
+ AI_Movement_Track_Flush(kActorFreeSlotA);
+ AI_Movement_Track_Append(kActorFreeSlotA, 525, 0);
+ AI_Movement_Track_Repeat(kActorFreeSlotA);
+ break;
+
+ case 599:
+ Actor_Set_Health(kActorFreeSlotA, 20, 20);
+ Actor_Set_Friendliness_To_Other(kActorFreeSlotA, kActorMcCoy, 40);
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool AIScriptFreeSlotA::UpdateAnimation(int *animation, int *frame) {
+ switch (_animationState) {
+ case 0:
+ *animation = 861;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(861)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 1:
+ *animation = 862;
+ if (_var1) {
+ _var1--;
+ } else {
+ _animationFrame += _var2;
+ if (_animationFrame < 8) {
+ _var2 = 1;
+ } else {
+ if (_animationFrame > 8) {
+ _var2 = -1;
+ } else if (Random_Query(0, 4)) {
+ _var2 = -_var2;
+ }
+ }
+ if (_animationFrame >= 7 && _animationFrame <= 9) {
+ _var1 = Random_Query(0, 1);
+ }
+ }
+ break;
+
+ case 2:
+ *animation = 862;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(862) - 1) {
+ *animation = 861;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 3:
+ *animation = 858;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(858)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 4:
+ *animation = 857;
+ _animationFrame++;
+ if (_animationFrame == 1) {
+ int snd;
+ if (Random_Query(1, 2) == 1) {
+ snd = 9010;
+ } else {
+ snd = 9015;
+ }
+ Sound_Play_Speech_Line(64, snd, 75, 0, 99);
+ }
+ if (_animationFrame == 3) {
+ Ambient_Sounds_Play_Sound(438, 99, 0, 0, 20);
+ Actor_Combat_AI_Hit_Attempt(kActorFreeSlotA);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(857)) {
+ _animationState = 0;
+ _animationFrame = 0;
+ Actor_Change_Animation_Mode(kActorFreeSlotA, 4);
+ }
+ break;
+
+ case 5:
+ *animation = 874;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(874) - 1) { // bug? shuld not be '-1'
+ Actor_Change_Animation_Mode(kActorFreeSlotA, 0);
+ }
+ break;
+
+ case 6:
+ if (_animationFrame == 1) {
+ Ambient_Sounds_Play_Sound(437, 99, 0, 0, 20);
+ }
+ *animation = 860;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(860)) {
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorFreeSlotA, 0);
+ }
+ break;
+
+ case 7:
+ *animation = 859;
+ _animationFrame++;
+ if (_animationFrame == 0) {
+ Ambient_Sounds_Play_Sound(439, 99, 0, 0, 25);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(859) - 1) { // bug? shuld not be '-1'
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(859) - 1;
+ _animationState = 8;
+ Actor_Set_Goal_Number(kActorFreeSlotA, 599);
+ }
+ break;
+
+ case 8:
+ *animation = 859;
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(859) - 1;
+ break;
+
+ default:
+ break;
+ }
+ *frame = _animationFrame;
+ return true;
+}
+
+bool AIScriptFreeSlotA::ChangeAnimationMode(int mode) {
+ switch (mode) {
+ case 0:
+ if ((unsigned int)(_animationState - 1) > 1) {
+ _animationState = 0;
+ _animationFrame = 0;
+ } else if (_animationState == 1) {
+ _animationState = 2;
+ }
+ break;
+
+ case 1:
+ _animationState = 3;
+ _animationFrame = 0;
+ break;
+
+ case 4:
+ if ((unsigned int)(_animationState - 1) > 1) {
+ _animationState = 0;
+ _animationFrame = 0;
+ } else if (_animationState == 1) {
+ _animationState = 2;
+ }
+ break;
+
+ case 6:
+ _animationState = 4;
+ _animationFrame = 0;
+ break;
+
+ case 7:
+ _animationState = 3;
+ _animationFrame = 0;
+ break;
+
+ case 8:
+ _animationState = 3;
+ _animationFrame = 0;
+ break;
+
+ case 21:
+ _animationState = 6;
+ _animationFrame = 0;
+ break;
+
+ case 43:
+ _animationState = 1;
+ _animationFrame = 0;
+ break;
+
+ case 48:
+ _animationState = 7;
+ _animationFrame = 0;
+ break;
+ }
+ return true;
+}
+
+void AIScriptFreeSlotA::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ *animationState = _animationState;
+ *animationFrame = _animationFrame;
+ *animationStateNext = _animationStateNext;
+ *animationNext = _animationNext;
+}
+
+void AIScriptFreeSlotA::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ _animationState = animationState;
+ _animationFrame = animationFrame;
+ _animationStateNext = animationStateNext;
+ _animationNext = animationNext;
+}
+
+bool AIScriptFreeSlotA::ReachedMovementTrackWaypoint(int waypointId) {
+ if (Actor_Query_Which_Set_In(kActorFreeSlotA) == kSetUG01) {
+ if (waypointId == 465) {
+ Actor_Change_Animation_Mode(kActorFreeSlotA, 43);
+ }
+ } else if (Actor_Query_Goal_Number(kActorFreeSlotA) == 302) {
+ Actor_Face_Actor(kActorFreeSlotA, kActorMcCoy, 1);
+ }
+
+ return true;
+}
+
+void AIScriptFreeSlotA::FledCombat() {
+ // return false;
+}
+
+void AIScriptFreeSlotA::calcHit() {
+ float x, y, z;
+
+ Actor_Query_XYZ(kActorFreeSlotA, &x, &y, &z);
+
+ if (x >= -30.0f && x < -150.0f) {
+ Game_Flag_Set(677);
+ }
+}
+
+void AIScriptFreeSlotA::processGoal306() {
+ switch (Random_Query(1, 14)) {
+ case 1:
+ AI_Movement_Track_Append(kActorFreeSlotA, 450, 1);
+ AI_Movement_Track_Append(kActorFreeSlotA, 451, 5);
+ AI_Movement_Track_Append(kActorFreeSlotA, 450, 0);
+ break;
+
+ case 2:
+ World_Waypoint_Set(463, 74, 144.98f, -50.13f, -175.75f);
+ World_Waypoint_Set(464, 74, 105.6f, -50.13f, -578.46f);
+ World_Waypoint_Set(465, 74, 62.0f, -50.13f, -574.0f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 1);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 1);
+ AI_Movement_Track_Append(kActorFreeSlotA, 465, 5);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 5);
+ break;
+
+ case 3:
+ AI_Movement_Track_Append(kActorFreeSlotA, 446, 15);
+ AI_Movement_Track_Append(kActorFreeSlotA, 447, 1);
+ AI_Movement_Track_Append(kActorFreeSlotA, 449, 1);
+ AI_Movement_Track_Append(kActorFreeSlotA, 448, 2);
+ AI_Movement_Track_Append(kActorFreeSlotA, 449, 0);
+ break;
+
+ case 4:
+ World_Waypoint_Set(463, 77, -22.7f, 6.39f, 33.12f);
+ World_Waypoint_Set(464, 77, -6.70f, -1.74f, -362.88f);
+ World_Waypoint_Set(465, 77, 164.0f, 11.87f, -1013.0f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 2);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 0);
+ AI_Movement_Track_Append(kActorFreeSlotA, 465, 0);
+ break;
+
+ case 5:
+ AI_Movement_Track_Append(kActorFreeSlotA, 457, 15);
+ AI_Movement_Track_Append(kActorFreeSlotA, 458, 0);
+ AI_Movement_Track_Append(kActorFreeSlotA, 459, 15);
+ break;
+
+ case 6:
+ AI_Movement_Track_Append(kActorFreeSlotA, 460, 15);
+ AI_Movement_Track_Append(kActorFreeSlotA, 461, 5);
+ AI_Movement_Track_Append(kActorFreeSlotA, 460, 15);
+ break;
+
+ case 7:
+ if (Actor_Query_In_Set(kActorClovis, kSetUG07)) {
+ AI_Movement_Track_Append(kActorFreeSlotA, 39, 10);
+ } else {
+ World_Waypoint_Set(463, 80, -88.78f, -12.21f, -184.08f);
+ World_Waypoint_Set(464, 80, 250.0f, -12.21f, -342.0f);
+ World_Waypoint_Set(465, 80, -164.78f, -12.21f, -832.08f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 5);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 1);
+ }
+ break;
+
+ case 8:
+ World_Waypoint_Set(463, 80, -88.78f, -12.21f, -184.08f);
+ World_Waypoint_Set(464, 80, 250.0f, -12.21f, -342.0f);
+ World_Waypoint_Set(465, 80, -164.78f, -12.21f, -832.08f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 5);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 1);
+ break;
+
+ case 9:
+ World_Waypoint_Set(463, 80, -88.78f, -12.21f, -184.08f);
+ World_Waypoint_Set(464, 80, 250.0f, -12.21f, -342.0f);
+ World_Waypoint_Set(465, 80, -164.78f, -12.21f, -832.08f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 5);
+ AI_Movement_Track_Append(kActorFreeSlotA, 465, 1);
+ break;
+
+ case 10:
+ World_Waypoint_Set(463, 80, -88.78f, -12.21f, -184.08f);
+ World_Waypoint_Set(464, 80, 250.0f, -12.21f, -342.0f);
+ World_Waypoint_Set(465, 80, -164.78f, -12.21f, -832.08f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 465, 5);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 1);
+ break;
+
+ case 11:
+ World_Waypoint_Set(463, 82, 91.0f, 156.94f, -498.0f);
+ World_Waypoint_Set(464, 82, -149.0f, 156.94f, -498.0f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 5);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 1);
+ break;
+
+ case 12:
+ World_Waypoint_Set(463, 82, 91.0f, 156.94f, -498.0f);
+ World_Waypoint_Set(464, 82, -149.0f, 156.94f, -498.0f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 5);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 1);
+ break;
+
+ case 13:
+ World_Waypoint_Set(463, 82, -152.51f, 277.31f, 311.98f);
+ World_Waypoint_Set(464, 82, -124.51f, 275.08f, 319.98f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 1);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 8);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 1);
+ break;
+
+ case 14:
+ World_Waypoint_Set(463, 84, -360.67f, 21.39f, 517.55f);
+ World_Waypoint_Set(464, 84, -250.67f, 21.39f, 477.55f);
+ World_Waypoint_Set(465, 84, -248.67f, 21.39f, -1454.45f);
+ AI_Movement_Track_Append(kActorFreeSlotA, 463, 1);
+ AI_Movement_Track_Append(kActorFreeSlotA, 464, 8);
+ AI_Movement_Track_Append(kActorFreeSlotA, 465, 1);
+ break;
+
+ default:
+ AI_Movement_Track_Append(kActorFreeSlotA, 39, Random_Query(1, 10));
+ break;
+ }
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/free_slot_b.cpp b/engines/bladerunner/script/ai/free_slot_b.cpp
new file mode 100644
index 0000000000..431b27a062
--- /dev/null
+++ b/engines/bladerunner/script/ai/free_slot_b.cpp
@@ -0,0 +1,541 @@
+/* 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 "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptFreeSlotB::AIScriptFreeSlotB(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+ _var1 = 0;
+ _var2 = 1;
+}
+
+void AIScriptFreeSlotB::Initialize() {
+ _animationFrame = 0;
+ _animationState = 0;
+ _animationStateNext = 0;
+ _animationNext = 0;
+
+ _var1 = 0;
+ _var2 = 1;
+
+ World_Waypoint_Set(527, 45, -468.46f, -616.58f, 2840.60f);
+ World_Waypoint_Set(528, 45, -1024.46f, -615.49f, 2928.60f);
+ World_Waypoint_Set(529, 45, -1024.46f, -615.49f, 2788.60f);
+}
+
+bool AIScriptFreeSlotB::Update() {
+ if (Global_Variable_Query(kVariableChapter) > 5) {
+ return false;
+ }
+
+ if (Global_Variable_Query(kVariableChapter) == 4) {
+ switch (Actor_Query_Goal_Number(kActorFreeSlotB)) {
+ case 300:
+ Actor_Set_Goal_Number(kActorFreeSlotB, 301);
+ Actor_Set_Targetable(kActorFreeSlotB, 1);
+ break;
+
+ case 301:
+ if (Actor_Query_Which_Set_In(kActorFreeSlotB) == Player_Query_Current_Set()
+ && Actor_Query_Inch_Distance_From_Actor(kActorFreeSlotB, kActorMcCoy) <= 48) {
+ Actor_Set_Goal_Number(kActorFreeSlotB, 302);
+ }
+ break;
+
+ case 302:
+ if (Actor_Query_Which_Set_In(kActorFreeSlotB) != Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorFreeSlotB, 301);
+ }
+ break;
+
+ case 599:
+ if (Actor_Query_Which_Set_In(kActorFreeSlotB) != Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorFreeSlotB, 300);
+ }
+ break;
+
+ default:
+ Actor_Set_Goal_Number(kActorFreeSlotB, 300);
+ break;
+ }
+
+ return false;
+ }
+ if (Actor_Query_Goal_Number(kActorFreeSlotB) < 400) {
+ AI_Movement_Track_Flush(kActorFreeSlotB);
+ Actor_Set_Goal_Number(kActorFreeSlotB, 400);
+ return true;
+ } else {
+ if (Actor_Query_Goal_Number(kActorFreeSlotB) != 405 || Actor_Query_Which_Set_In(kActorMcCoy) != kSetKP02) {
+ if (Actor_Query_Goal_Number(kActorFreeSlotB) == 599) {
+ if (Actor_Query_Which_Set_In(kActorFreeSlotB) != Player_Query_Current_Set()) {
+ Non_Player_Actor_Combat_Mode_Off(kActorFreeSlotB);
+ Actor_Set_Goal_Number(kActorFreeSlotB, 400);
+ return true;
+ }
+ }
+ return false;
+ }
+ Actor_Set_Goal_Number(kActorFreeSlotB, 406);
+ Actor_Set_Targetable(kActorFreeSlotB, 1);
+ return true;
+ }
+}
+
+void AIScriptFreeSlotB::TimerExpired(int timer) {
+ //return false;
+}
+
+void AIScriptFreeSlotB::CompletedMovementTrack() {
+ switch (Actor_Query_Goal_Number(kActorFreeSlotB)) {
+ case 300:
+ Actor_Set_Goal_Number(kActorFreeSlotB, 301);
+ break;
+
+ case 301:
+ Actor_Set_Goal_Number(kActorFreeSlotB, 300);
+ break;
+
+ case 400:
+ Actor_Set_Goal_Number(kActorFreeSlotB, 405);
+ break;
+
+ case 406:
+ Non_Player_Actor_Combat_Mode_On(kActorFreeSlotB, 0, 0, 0, 8, 4, 7, 8, 0, 0, 100, 5, 300, 0);
+ break;
+
+ default:
+ return; //false;
+ }
+
+ return; //true;
+}
+
+void AIScriptFreeSlotB::ReceivedClue(int clueId, int fromActorId) {
+ //return false;
+}
+
+void AIScriptFreeSlotB::ClickedByPlayer() {
+ if (Actor_Query_Goal_Number(kActorFreeSlotB) != 599)
+ return; //false;
+
+ Actor_Face_Actor(kActorMcCoy, kActorFreeSlotB, 1);
+ if (Random_Query(1, 2) == 1) {
+ Actor_Says(kActorMcCoy, 8655, 16);
+ } else {
+ Actor_Says(kActorMcCoy, 8665, 16);
+ }
+}
+
+void AIScriptFreeSlotB::EnteredScene(int sceneId) {
+ // return false;
+}
+
+void AIScriptFreeSlotB::OtherAgentEnteredThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptFreeSlotB::OtherAgentExitedThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptFreeSlotB::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+ // return false;
+}
+
+void AIScriptFreeSlotB::ShotAtAndMissed() {
+ // return false;
+}
+
+bool AIScriptFreeSlotB::ShotAtAndHit() {
+ return false;
+}
+
+void AIScriptFreeSlotB::Retired(int byActorId) {
+ Actor_Set_Goal_Number(kActorFreeSlotB, 599);
+}
+
+int AIScriptFreeSlotB::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+ return 0;
+}
+
+bool AIScriptFreeSlotB::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+ switch (newGoalNumber) {
+ case 300:
+ AI_Movement_Track_Flush(kActorFreeSlotB);
+ AI_Movement_Track_Append(kActorFreeSlotB, 39, 2);
+ AI_Movement_Track_Repeat(kActorFreeSlotB);
+ break;
+
+ case 301:
+ AI_Movement_Track_Flush(kActorFreeSlotB);
+ processGoal301();
+ AI_Movement_Track_Repeat(kActorFreeSlotB);
+ break;
+
+ case 302:
+ Actor_Set_Targetable(kActorFreeSlotB, 1);
+ Non_Player_Actor_Combat_Mode_On(kActorFreeSlotB, 0, 0, 0, 8, 4, 7, 8, 25, 0, 75, 5, 300, 0);
+ break;
+
+ case 400:
+ AI_Movement_Track_Append(kActorFreeSlotB, 39, 0);
+ AI_Movement_Track_Repeat(kActorFreeSlotB);
+ break;
+
+ case 406:
+ AI_Movement_Track_Flush(kActorFreeSlotB);
+ AI_Movement_Track_Append(kActorFreeSlotB, 527, 0);
+ AI_Movement_Track_Repeat(kActorFreeSlotB);
+ break;
+
+ case 599:
+ Actor_Set_Health(kActorFreeSlotB, 20, 20);
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool AIScriptFreeSlotB::UpdateAnimation(int *animation, int *frame) {
+ switch (_animationState) {
+ case 0:
+ *animation = 861;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(861)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 1:
+ *animation = 862;
+ if (_var1) {
+ _var1--;
+ } else {
+ _animationFrame += _var2;
+ if (_animationFrame < 8) {
+ _var2 = 1;
+ } else {
+ if (_animationFrame > 8) {
+ _var2 = -1;
+ } else if (Random_Query(0, 4)) {
+ _var2 = -_var2;
+ }
+ }
+ if (_animationFrame >= 7 && _animationFrame <= 9) {
+ _var1 = Random_Query(0, 1);
+ }
+ }
+ break;
+
+ case 2:
+ *animation = 862;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(862) - 1) {
+ *animation = 861;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 3:
+ *animation = 858;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(858)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 4:
+ *animation = 857;
+ _animationFrame++;
+ if (_animationFrame == 3) {
+ int snd;
+ if (Random_Query(1, 2) == 1) {
+ snd = 9010;
+ } else {
+ snd = 9015;
+ }
+ Sound_Play_Speech_Line(kActorFreeSlotB, snd, 75, 0, 99);
+ }
+ if (_animationFrame == 3) {
+ Actor_Combat_AI_Hit_Attempt(kActorFreeSlotB);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+ *animation = 861;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 5:
+ *animation = 874;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(874) - 1) {
+ _animationState = 8;
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(874) - 1;
+ }
+ break;
+
+ case 6:
+ if (_animationFrame == 1) {
+ Ambient_Sounds_Play_Sound(437, 99, 0, 0, 20);
+ }
+ *animation = 860;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(860)) {
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorFreeSlotB, 0);
+ }
+ break;
+
+ case 7:
+ *animation = 859;
+ _animationFrame++;
+ if (_animationFrame == 1) {
+ Ambient_Sounds_Play_Sound(439, 99, 0, 0, 25);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(859)) {
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(859);
+ }
+ _animationState = 8;
+ break;
+
+ case 8:
+ *animation = 859;
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(859) - 1;
+ break;
+
+ default:
+ break;
+ }
+ *frame = _animationFrame;
+ return true;
+}
+
+bool AIScriptFreeSlotB::ChangeAnimationMode(int mode) {
+ switch (mode) {
+ case 0:
+ if ((unsigned int)(_animationState - 1) > 1) {
+ _animationState = 0;
+ _animationFrame = 0;
+ } else if (_animationState == 1) {
+ _animationState = 2;
+ }
+ break;
+
+ case 1:
+ _animationState = 3;
+ _animationFrame = 0;
+ break;
+
+ case 4:
+ if ((unsigned int)(_animationState - 1) > 1) {
+ _animationState = 0;
+ _animationFrame = 0;
+ } else if (_animationState == 1) {
+ _animationState = 2;
+ }
+ break;
+
+ case 6:
+ _animationState = 4;
+ _animationFrame = 0;
+ break;
+
+ case 7:
+ _animationState = 3;
+ _animationFrame = 0;
+ break;
+
+ case 8:
+ _animationState = 3;
+ _animationFrame = 0;
+ break;
+
+ case 21:
+ _animationState = 6;
+ _animationFrame = 0;
+ break;
+
+ case 43:
+ _animationState = 1;
+ _animationFrame = 0;
+ break;
+
+ case 48:
+ _animationState = 7;
+ _animationFrame = 0;
+ break;
+ }
+
+ return true;
+}
+
+void AIScriptFreeSlotB::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ *animationState = _animationState;
+ *animationFrame = _animationFrame;
+ *animationStateNext = _animationStateNext;
+ *animationNext = _animationNext;
+}
+
+void AIScriptFreeSlotB::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ _animationState = animationState;
+ _animationFrame = animationFrame;
+ _animationStateNext = animationStateNext;
+ _animationNext = animationNext;
+}
+
+bool AIScriptFreeSlotB::ReachedMovementTrackWaypoint(int waypointId) {
+ return true;
+}
+
+void AIScriptFreeSlotB::FledCombat() {
+ // return false;
+}
+
+void AIScriptFreeSlotB::processGoal301() {
+ switch (Random_Query(1, 14)) {
+ case 1:
+ AI_Movement_Track_Append(kActorFreeSlotB, 450, 1);
+ AI_Movement_Track_Append(kActorFreeSlotB, 451, 5);
+ AI_Movement_Track_Append(kActorFreeSlotB, 450, 0);
+ break;
+
+ case 2:
+ World_Waypoint_Set(466, 74, 144.98f, -50.13f, -175.75f);
+ World_Waypoint_Set(547, 74, 105.6f, -50.13f, -578.46f);
+ World_Waypoint_Set(548, 74, 62.0f, -50.13f, -574.0f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 1);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 1);
+ AI_Movement_Track_Append(kActorFreeSlotB, 548, 5);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 5);
+ break;
+
+ case 3:
+ AI_Movement_Track_Append(kActorFreeSlotB, 446, 15);
+ AI_Movement_Track_Append(kActorFreeSlotB, 447, 1);
+ AI_Movement_Track_Append(kActorFreeSlotB, 449, 1);
+ AI_Movement_Track_Append(kActorFreeSlotB, 448, 2);
+ AI_Movement_Track_Append(kActorFreeSlotB, 449, 0);
+ break;
+
+ case 4:
+ World_Waypoint_Set(466, 77, -22.70f, 6.39f, 33.12f);
+ World_Waypoint_Set(547, 77, -6.70f, -1.74f, -362.88f);
+ World_Waypoint_Set(548, 77, 164.0f, 11.87f, -1013.0f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 2);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 0);
+ AI_Movement_Track_Append(kActorFreeSlotB, 548, 0);
+ break;
+
+ case 5:
+ AI_Movement_Track_Append(kActorFreeSlotB, 457, 15);
+ AI_Movement_Track_Append(kActorFreeSlotB, 458, 0);
+ AI_Movement_Track_Append(kActorFreeSlotB, 459, 15);
+ break;
+
+ case 6:
+ AI_Movement_Track_Append(kActorFreeSlotB, 460, 15);
+ AI_Movement_Track_Append(kActorFreeSlotB, 461, 5);
+ AI_Movement_Track_Append(kActorFreeSlotB, 460, 15);
+ break;
+
+ case 7:
+ if (Actor_Query_In_Set(kActorClovis, kSetUG07)) {
+ AI_Movement_Track_Append(kActorFreeSlotB, 39, 10);
+ } else {
+ World_Waypoint_Set(466, 80, -88.78f, -12.21f, -184.08f);
+ World_Waypoint_Set(547, 80, 250.0f, -12.21f, -342.0f);
+ World_Waypoint_Set(548, 80, -164.78f, -12.21f, -832.08f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 5);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 1);
+ }
+ break;
+
+ case 8:
+ World_Waypoint_Set(466, 80, -88.78f, -12.21f, -184.08f);
+ World_Waypoint_Set(547, 80, 250.0f, -12.21f, -342.0f);
+ World_Waypoint_Set(548, 80, -164.78f, -12.21f, -832.08f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 5);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 1);
+ break;
+
+ case 9:
+ World_Waypoint_Set(466, 80, -88.78f, -12.21f, -184.08f);
+ World_Waypoint_Set(547, 80, 250.0f, -12.21f, -342.0f);
+ World_Waypoint_Set(548, 80, -164.78f, -12.21f, -832.08f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 5);
+ AI_Movement_Track_Append(kActorFreeSlotB, 548, 1);
+ break;
+
+ case 10:
+ World_Waypoint_Set(466, 80, -88.78f, -12.21f, -184.08f);
+ World_Waypoint_Set(547, 80, 250.0f, -12.21f, -342.0f);
+ World_Waypoint_Set(548, 80, -164.78f, -12.21f, -832.08f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 548, 5);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 1);
+ break;
+
+ case 11:
+ World_Waypoint_Set(466, 82, 91.0f, 156.94f, -498.0f);
+ World_Waypoint_Set(547, 82, -149.0f, 156.94f, -498.0f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 5);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 1);
+ break;
+
+ case 12:
+ World_Waypoint_Set(466, 82, 91.0f, 156.94f, -498.0f);
+ World_Waypoint_Set(547, 82, -149.0f, 156.94f, -498.0f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 5);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 1);
+ break;
+
+ case 13:
+ World_Waypoint_Set(466, 82, -152.51f, 277.31f, 311.98f);
+ World_Waypoint_Set(547, 82, -124.51f, 275.08f, 319.98f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 1);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 8);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 1);
+ break;
+
+ case 14:
+ World_Waypoint_Set(466, 84, -360.67f, 21.39f, 517.55f);
+ World_Waypoint_Set(547, 84, -250.67f, 21.39f, 477.55f);
+ World_Waypoint_Set(548, 84, -248.67f, 21.39f, -1454.45f);
+ AI_Movement_Track_Append(kActorFreeSlotB, 466, 1);
+ AI_Movement_Track_Append(kActorFreeSlotB, 547, 8);
+ AI_Movement_Track_Append(kActorFreeSlotB, 548, 1);
+ break;
+
+ default:
+ AI_Movement_Track_Append(kActorFreeSlotB, 39, Random_Query(1, 10));
+ break;
+ }
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/gaff.cpp b/engines/bladerunner/script/ai/gaff.cpp
index c26f0d907f..c5e629cab0 100644
--- a/engines/bladerunner/script/ai/gaff.cpp
+++ b/engines/bladerunner/script/ai/gaff.cpp
@@ -287,7 +287,7 @@ bool AIScriptGaff::GoalChanged(int currentGoalNumber, int newGoalNumber) {
return true;
case 303:
Actor_Face_Actor(kActorGaff, kActorMcCoy, 1);
- Actor_Change_Animation_Mode(kActorGaff, kAnimationModeCombatShoot);
+ Actor_Change_Animation_Mode(kActorGaff, kAnimationModeCombatAttack);
Sound_Play(27, 100, 0, 0, 50);
Actor_Change_Animation_Mode(kActorMcCoy, 48);
Actor_Retired_Here(kActorMcCoy, 12, 12, 1, -1);
diff --git a/engines/bladerunner/script/ai/generic_walker_a.cpp b/engines/bladerunner/script/ai/generic_walker_a.cpp
index 7acea89c25..0ba48811ed 100644
--- a/engines/bladerunner/script/ai/generic_walker_a.cpp
+++ b/engines/bladerunner/script/ai/generic_walker_a.cpp
@@ -354,8 +354,7 @@ bool AIScriptGenericWalkerA::prepareWalker() {
} else {
model = Random_Query(0, 5);
}
- }
- while (model == Global_Variable_Query(kVariableGenericWalkerBModel) || model == Global_Variable_Query(kVariableGenericWalkerCModel));
+ } while (model == Global_Variable_Query(kVariableGenericWalkerBModel) || model == Global_Variable_Query(kVariableGenericWalkerCModel));
Global_Variable_Set(kVariableGenericWalkerAModel, model);
Game_Flag_Set(kFlagGenericWalkerWaiting);
@@ -459,7 +458,7 @@ bool AIScriptGenericWalkerA::preparePath() {
int waypointEnd = 0;
do {
waypointStart = Random_Query(167, 171);
- } while (waypointEnd == 168 || waypointEnd == 169);
+ } while (waypointStart == 168 || waypointStart == 169);
do {
waypointEnd = Random_Query(167, 171);
} while (waypointEnd == waypointStart || waypointEnd == 168 || waypointEnd == 169);
diff --git a/engines/bladerunner/script/ai/generic_walker_b.cpp b/engines/bladerunner/script/ai/generic_walker_b.cpp
index a2ff58113f..2a6c3a1732 100644
--- a/engines/bladerunner/script/ai/generic_walker_b.cpp
+++ b/engines/bladerunner/script/ai/generic_walker_b.cpp
@@ -330,8 +330,7 @@ bool AIScriptGenericWalkerB::prepareWalker() {
} else {
model = Random_Query(0, 5);
}
- }
- while (model == Global_Variable_Query(kVariableGenericWalkerAModel) || model == Global_Variable_Query(kVariableGenericWalkerCModel));
+ } while (model == Global_Variable_Query(kVariableGenericWalkerAModel) || model == Global_Variable_Query(kVariableGenericWalkerCModel));
Global_Variable_Set(kVariableGenericWalkerBModel, model);
Game_Flag_Set(kFlagGenericWalkerWaiting);
@@ -435,7 +434,7 @@ bool AIScriptGenericWalkerB::preparePath() {
int waypointEnd = 0;
do {
waypointStart = Random_Query(167, 171);
- } while (waypointEnd == 168 || waypointEnd == 169);
+ } while (waypointStart == 168 || waypointStart == 169);
do {
waypointEnd = Random_Query(167, 171);
} while (waypointEnd == waypointStart || waypointEnd == 168 || waypointEnd == 169);
diff --git a/engines/bladerunner/script/ai/generic_walker_c.cpp b/engines/bladerunner/script/ai/generic_walker_c.cpp
index f317d5ad49..5c0478c645 100644
--- a/engines/bladerunner/script/ai/generic_walker_c.cpp
+++ b/engines/bladerunner/script/ai/generic_walker_c.cpp
@@ -331,9 +331,8 @@ bool AIScriptGenericWalkerC::prepareWalker() {
} else {
model = Random_Query(0, 5);
}
- }
// Here is probably bug in original code, because it not using kVariableGenericWalkerBModel but kVariableGenericWalkerCModel
- while (model == Global_Variable_Query(kVariableGenericWalkerAModel) || model == Global_Variable_Query(kVariableGenericWalkerBModel));
+ } while (model == Global_Variable_Query(kVariableGenericWalkerAModel) || model == Global_Variable_Query(kVariableGenericWalkerBModel));
Global_Variable_Set(kVariableGenericWalkerCModel, model);
@@ -438,7 +437,7 @@ bool AIScriptGenericWalkerC::preparePath() {
int waypointEnd = 0;
do {
waypointStart = Random_Query(167, 171);
- } while (waypointEnd == 168 || waypointEnd == 169);
+ } while (waypointStart == 168 || waypointStart == 169);
do {
waypointEnd = Random_Query(167, 171);
} while (waypointEnd == waypointStart || waypointEnd == 168 || waypointEnd == 169);
diff --git a/engines/bladerunner/script/ai/gordo.cpp b/engines/bladerunner/script/ai/gordo.cpp
index fd64112897..c44497176a 100644
--- a/engines/bladerunner/script/ai/gordo.cpp
+++ b/engines/bladerunner/script/ai/gordo.cpp
@@ -1157,7 +1157,7 @@ bool AIScriptGordo::ChangeAnimationMode(int mode) {
break;
}
break;
- case kAnimationModeCombatShoot:
+ case kAnimationModeCombatAttack:
_animationState = 18;
_animationFrame = 0;
break;
diff --git a/engines/bladerunner/script/ai/guzza.cpp b/engines/bladerunner/script/ai/guzza.cpp
index 0f99fa8a46..5a4459535e 100644
--- a/engines/bladerunner/script/ai/guzza.cpp
+++ b/engines/bladerunner/script/ai/guzza.cpp
@@ -728,7 +728,7 @@ bool AIScriptGuzza::ChangeAnimationMode(int mode) {
_animationFrame = 0;
}
break;
- case kAnimationModeCombatShoot:
+ case kAnimationModeCombatAttack:
_animationState = 31;
_animationFrame = 0;
break;
diff --git a/engines/bladerunner/script/ai/hanoi.cpp b/engines/bladerunner/script/ai/hanoi.cpp
new file mode 100644
index 0000000000..4b88be7c5f
--- /dev/null
+++ b/engines/bladerunner/script/ai/hanoi.cpp
@@ -0,0 +1,740 @@
+/* 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 "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptHanoi::AIScriptHanoi(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+ _var1 = 0;
+ _var2 = 0;
+ _var3 = 0;
+ _var4 = 1;
+}
+
+void AIScriptHanoi::Initialize() {
+ _animationFrame = 0;
+ _animationState = 0;
+ _animationStateNext = 0;
+ _animationNext = 0;
+
+ _var1 = 0;
+ _var2 = 0;
+ _var3 = 0;
+ _var4 = 1;
+
+ Actor_Set_Goal_Number(kActorHanoi, 0);
+}
+
+bool AIScriptHanoi::Update() {
+ if (Actor_Query_Goal_Number(kActorHolloway) == 240) {
+ AI_Countdown_Timer_Reset(kActorHanoi, 0);
+ }
+ if (Global_Variable_Query(kVariableChapter) == 3 && Actor_Query_Goal_Number(kActorHanoi) < 200) {
+ Actor_Set_Goal_Number(kActorHanoi, 210);
+ }
+ if (Player_Query_Current_Scene() != 56 && Actor_Query_Goal_Number(kActorHanoi) == 236) {
+ Actor_Set_Goal_Number(kActorHanoi, 210);
+ }
+ if (Player_Query_Current_Scene() == 56
+ && Actor_Query_Goal_Number(kActorHanoi) != 215
+ && Actor_Query_Goal_Number(kActorHanoi) != 230
+ && Actor_Query_Goal_Number(kActorHanoi) != 235
+ && Actor_Query_Goal_Number(kActorHanoi) != 236) {
+ if (Actor_Query_Inch_Distance_From_Waypoint(kActorMcCoy, 364) < 420) {
+ if (Actor_Query_Goal_Number(kActorHanoi) == 210) {
+ Actor_Set_Goal_Number(kActorHanoi, 211);
+ }
+ } else if (Actor_Query_Goal_Number(kActorHanoi) == 211) {
+ Actor_Set_Goal_Number(kActorHanoi, 210);
+ }
+ if (Actor_Query_Inch_Distance_From_Waypoint(kActorMcCoy, 361) < 240) {
+ if (Actor_Query_Goal_Number(kActorHanoi) == 210) {
+ Actor_Set_Goal_Number(kActorHanoi, 212);
+ }
+ } else if (Actor_Query_Goal_Number(kActorHanoi) == 212) {
+ Actor_Set_Goal_Number(kActorHanoi, 210);
+ }
+ if (Actor_Query_Inch_Distance_From_Actor(kActorMcCoy, kActorHysteriaPatron1) < 120
+ && Actor_Query_Which_Set_In(kActorHanoi) == 55
+ && Actor_Query_Goal_Number(kActorHanoi) != 213) {
+ Actor_Set_Goal_Number(kActorHanoi, 213);
+ }
+ }
+
+ return false;
+}
+
+void AIScriptHanoi::TimerExpired(int timer) {
+ if (timer == 0) {
+ if (Actor_Query_Goal_Number(kActorHanoi) == 215) {
+ Actor_Set_Goal_Number(kActorHanoi, 210);
+ return; //true;
+ }
+
+ if (Actor_Query_Goal_Number(kActorHanoi) == 220)
+ return; //false;
+
+ Actor_Set_Goal_Number(kActorHanoi, 202);
+ return; //true;
+ }
+ return; //false;
+}
+
+void AIScriptHanoi::CompletedMovementTrack() {
+ switch (Actor_Query_Goal_Number(kActorHanoi)) {
+ case 235:
+ Actor_Set_Goal_Number(kActorHanoi, 236);
+ break;
+
+ case 240:
+ Actor_Set_Goal_Number(kActorHanoi, 241);
+ break;
+
+ case 202:
+ Actor_Says(kActorHanoi, 130, 3);
+ Actor_Says(kActorDektora, 540, 30);
+ Actor_Set_Goal_Number(kActorHanoi, 203);
+ break;
+
+ case 203:
+ Actor_Face_Actor(kActorHanoi, kActorMcCoy, 1);
+ Actor_Face_Actor(kActorMcCoy, kActorHanoi, 1);
+ Actor_Change_Animation_Mode(kActorHanoi, 23);
+ Actor_Set_Invisible(kActorMcCoy, 1);
+ Actor_Says(kActorMcCoy, 3595, 3);
+ Actor_Says(kActorHanoi, 140, 3);
+ Actor_Set_Goal_Number(kActorHanoi, 220);
+ break;
+
+ case 213:
+ Actor_Set_Goal_Number(kActorHanoi, 210);
+ break;
+
+ default:
+ return; //false;
+ }
+
+ return; //true;
+}
+
+void AIScriptHanoi::ReceivedClue(int clueId, int fromActorId) {
+ //return false;
+}
+
+void AIScriptHanoi::ClickedByPlayer() {
+ if (Actor_Query_Goal_Number(kActorHanoi) == 230 || Actor_Query_Goal_Number(kActorHanoi) == 235) {
+ Actor_Face_Actor(kActorMcCoy, kActorHanoi, 1);
+ Actor_Says(kActorMcCoy, 8915, 11);
+
+ if (Actor_Query_Goal_Number(kActorHanoi) == 230) {
+ Actor_Says(kActorHanoi, 210, 3);
+ }
+ }
+}
+
+void AIScriptHanoi::EnteredScene(int sceneId) {
+ // return false;
+}
+
+void AIScriptHanoi::OtherAgentEnteredThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptHanoi::OtherAgentExitedThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptHanoi::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+ if (Player_Query_Current_Scene() != 56 || otherActorId || combatMode != 1) {
+ return; //false;
+ }
+ Player_Set_Combat_Mode(0);
+ Player_Loses_Control();
+ Actor_Set_Goal_Number(kActorHanoi, 220);
+
+ return; //true;
+}
+
+void AIScriptHanoi::ShotAtAndMissed() {
+ // return false;
+}
+
+bool AIScriptHanoi::ShotAtAndHit() {
+ return false;
+}
+
+void AIScriptHanoi::Retired(int byActorId) {
+ // return false;
+}
+
+int AIScriptHanoi::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+ return 0;
+}
+
+bool AIScriptHanoi::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+ if (!newGoalNumber) {
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append(kActorHanoi, 39, 0);
+ AI_Movement_Track_Repeat(kActorHanoi);
+
+ return true;
+ }
+
+ switch (newGoalNumber) {
+ case 200:
+ AI_Countdown_Timer_Start(kActorHanoi, 0, 45);
+ break;
+
+ case 201:
+ AI_Countdown_Timer_Reset(kActorHanoi, 0);
+ break;
+
+ case 202:
+ if (Actor_Query_Which_Set_In(kActorMcCoy) == kSetNR07 && Actor_Query_In_Set(kActorDektora, kSetNR07)) {
+ Player_Loses_Control();
+ Actor_Put_In_Set(kActorHanoi, kSetNR07);
+ Actor_Set_At_XYZ(kActorHanoi, -102.0f, -73.5f, -233.0f, 0);
+ Async_Actor_Walk_To_Waypoint(kActorMcCoy, 338, 0, 0);
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append(kActorHanoi, 336, 1);
+ AI_Movement_Track_Repeat(kActorHanoi);
+ } else {
+ Actor_Set_Goal_Number(kActorHanoi, 0);
+ }
+ break;
+
+ case 203:
+ if (Actor_Query_Which_Set_In(kActorMcCoy) != kSetNR07) {
+ return false;
+ }
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append(kActorHanoi, 337, 0);
+ AI_Movement_Track_Repeat(kActorHanoi);
+ break;
+
+ case 204:
+ Actor_Says(kActorHanoi, 210, 3);
+ Actor_Change_Animation_Mode(kActorHanoi, 23);
+ break;
+
+ case 210:
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append_With_Facing(kActorHanoi, 362, 0, 300);
+ AI_Movement_Track_Repeat(kActorHanoi);
+ break;
+
+ case 211:
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append_With_Facing(kActorHanoi, 363, 0, 500);
+ AI_Movement_Track_Repeat(kActorHanoi);
+ break;
+
+ case 212:
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append_With_Facing(kActorHanoi, 361, 0, 457);
+ AI_Movement_Track_Repeat(kActorHanoi);
+ break;
+
+ case 213:
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append_With_Facing(kActorHanoi, 365, Random_Query(15, 20), 600);
+ AI_Movement_Track_Repeat(kActorHanoi);
+ break;
+
+ case 215:
+ Actor_Put_In_Set(kActorHanoi, kSetNR03);
+ Actor_Set_At_Waypoint(kActorHanoi, 362, 300);
+ AI_Countdown_Timer_Reset(kActorHanoi, 0);
+ AI_Countdown_Timer_Start(kActorHanoi, 0, 6);
+ break;
+
+ case 220:
+ Game_Flag_Set(604);
+ AI_Countdown_Timer_Reset(kActorHanoi, 0);
+ Player_Loses_Control();
+ Player_Set_Combat_Mode(0);
+ Actor_Force_Stop_Walking(kActorMcCoy);
+ Actor_Change_Animation_Mode(kActorMcCoy, 48);
+ Actor_Set_Invisible(kActorMcCoy, 1);
+ AI_Movement_Track_Flush(kActorHanoi);
+ Actor_Put_In_Set(kActorHanoi, kSetNR01);
+ Actor_Set_At_XYZ(kActorHanoi, -444.0f, 24.0f, -845.0f, 512);
+ Actor_Change_Animation_Mode(kActorHanoi, 78);
+ Set_Enter(kSetNR01, kSetNR01);
+ break;
+
+ case 230:
+ AI_Movement_Track_Flush(kActorHanoi);
+ Actor_Put_In_Set(kActorHanoi, kSetNR05_NR08);
+ Actor_Set_At_XYZ(kActorHanoi, -1387.51f, 0.32f, 288.16f, 292);
+ break;
+
+ case 235:
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append(kActorHanoi, 439, 0);
+ AI_Movement_Track_Append(kActorHanoi, 39, 45);
+ AI_Movement_Track_Repeat(kActorHanoi);
+ break;
+
+ case 236:
+ break;
+
+ case 240:
+ Actor_Put_In_Set(kActorHanoi, kSetNR04);
+ Actor_Set_At_XYZ(kActorHanoi, -47.0f, 0.0f, 334.0f, 535);
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append(kActorHanoi, 549, 0);
+ AI_Movement_Track_Repeat(kActorHanoi);
+ break;
+
+ case 241:
+ Actor_Face_Actor(kActorHanoi, kActorMcCoy, 1);
+ Actor_Change_Animation_Mode(kActorHanoi, 6);
+ Actor_Retired_Here(kActorMcCoy, 12, 12, 1, -1);
+ break;
+
+ case 9999:
+ AI_Movement_Track_Flush(kActorHanoi);
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool AIScriptHanoi::UpdateAnimation(int *animation, int *frame) {
+ switch (_animationState) {
+ case 0:
+ if (_var2 == 1) {
+ *animation = 649;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(649)) {
+ *animation = 648;
+ _animationFrame = 0;
+ _var2 = 0;
+ }
+ } else if (_var2 == 0) {
+ *animation = 648;
+ if (_var3) {
+ _var3--;
+ if (!Random_Query(0, 6)) {
+ _var4 = -_var4;
+ }
+ } else {
+ _animationFrame += _var4;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(648)) {
+ _animationFrame = 0;
+ }
+ if (_animationFrame < 0) {
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(648) - 1;
+ }
+ if (_animationFrame == 5 || _animationFrame == 15 || _animationFrame == 11 || !_animationFrame) {
+ _var3 = Random_Query(5, 12);
+ }
+ if (_animationFrame >= 10 && _animationFrame <= 13) {
+ _var3 = Random_Query(0, 1);
+ }
+ if (!_animationFrame) {
+ if (!Random_Query(0, 4)) {
+ _var2 = 1;
+ }
+ }
+ }
+ }
+ break;
+
+ case 1:
+ if (_var2) {
+ *animation = 649;
+ if ( Slice_Animation_Query_Number_Of_Frames(649) < Slice_Animation_Query_Number_Of_Frames(649)) {
+ _animationFrame += 2;
+ } else {
+ _animationFrame -= 2;
+ }
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(649) - 1
+ || _animationFrame <= 0) {
+ _animationFrame = 0;
+ _animationState = _animationStateNext;
+ *animation = _animationNext;
+ }
+ } else {
+ _animationFrame = 0;
+ _animationState = _animationStateNext;
+ *animation = _animationNext;
+ }
+ break;
+
+ case 2:
+ *animation = 657;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(657)) {
+ _animationFrame = 0;
+ _animationState = 3;
+ *animation = 658;
+ }
+ break;
+
+ case 3:
+ *animation = 658;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(658)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 4:
+ *animation = 659;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(659)) {
+ _animationFrame = 0;
+ _animationState = 3;
+ *animation = 658;
+ }
+ break;
+
+ case 5:
+ *animation = 657;
+ _animationFrame--;
+ if (_animationFrame == 0) {
+ _animationState = 0;
+ _animationFrame = 0;
+ *animation = 648;
+ Actor_Face_Actor(kActorMcCoy, kActorHanoi, 1);
+ Actor_Set_Invisible(kActorMcCoy, 0);
+
+ if (Actor_Query_In_Set(kActorHanoi, kSetNR01) == 1) {
+ AI_Movement_Track_Flush(kActorHanoi);
+ AI_Movement_Track_Append(kActorHanoi, 350, 0);
+ AI_Movement_Track_Append(kActorHanoi, 39, 0);
+ AI_Movement_Track_Repeat(kActorHanoi);
+ }
+ }
+ break;
+
+ case 6:
+ *animation = 345;
+ _animationFrame++;
+ if (_animationFrame > 26) {
+ Actor_Change_Animation_Mode(kActorHanoi, 0);
+ _animationState = 0;
+ _animationFrame = 0;
+ *animation = 648;
+ Actor_Set_Goal_Number(kActorMcCoy, 210);
+ Actor_Set_Goal_Number(kActorHanoi, 210);
+ }
+ break;
+
+ case 7:
+ *animation = 645;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(645)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 8:
+ *animation = 642;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(642) - 1) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 9:
+ *animation = 643;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(643) - 1) {
+ Actor_Change_Animation_Mode(kActorHanoi, 4);
+ _animationState = 8;
+ _animationFrame = 0;
+ *animation = 642;
+ Actor_Set_Goal_Number(kActorHanoi, 241);
+ }
+ break;
+
+ case 10:
+ *animation = 644;
+ _animationFrame++;
+ if (_animationFrame == 4) {
+ Ambient_Sounds_Play_Sound(492, 77, 0, 0, 20);
+ }
+ if (_animationFrame == 6) {
+ Ambient_Sounds_Play_Sound(493, 97, 0, 0, 20);
+ }
+ if (_animationFrame == 5) {
+ Actor_Force_Stop_Walking(kActorMcCoy);
+ Actor_Change_Animation_Mode(kActorMcCoy, 48);
+ }
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(*animation) - 1) {
+ Actor_Change_Animation_Mode(kActorHanoi, 4);
+ _animationFrame = 0;
+ _animationState = 8;
+ *animation = 642;
+ }
+ break;
+
+ case 11:
+ *animation = 660;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(660)) {
+ *animation = 648;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 12:
+ *animation = 646;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(646)) {
+ *animation = 642;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 13:
+ *animation = 647;
+ if (_animationFrame < Slice_Animation_Query_Number_Of_Frames(647) - 1) {
+ _animationFrame++;
+ }
+ break;
+
+ case 14:
+ *animation = 650;
+ if (!_animationFrame && _var1) {
+ _animationState = 0;
+ } else {
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(650)) {
+ _animationFrame = 0;
+ }
+ }
+ break;
+
+ case 15:
+ *animation = 651;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(651)) {
+ _animationFrame = 0;
+ _animationState = 14;
+ *animation = 650;
+ }
+ break;
+
+ case 16:
+ *animation = 652;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(652)) {
+ _animationFrame = 0;
+ _animationState = 14;
+ *animation = 650;
+ }
+ break;
+
+ case 17:
+ *animation = 653;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(653)) {
+ _animationFrame = 0;
+ _animationState = 14;
+ *animation = 650;
+ }
+ break;
+
+ case 18:
+ *animation = 654;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(654)) {
+ _animationFrame = 0;
+ _animationState = 14;
+ *animation = 650;
+ }
+ break;
+
+ case 19:
+ *animation = 655;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(655)) {
+ _animationFrame = 0;
+ _animationState = 14;
+ *animation = 650;
+ }
+ break;
+
+ case 20:
+ *animation = 656;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(656)) {
+ _animationFrame = 0;
+ _animationState = 14;
+ *animation = 650;
+ }
+ break;
+
+ default:
+ break;
+ }
+ *frame = _animationFrame;
+
+ return true;
+}
+
+bool AIScriptHanoi::ChangeAnimationMode(int mode) {
+ switch (mode) {
+ case kAnimationModeIdle:
+ if ((unsigned int)(_animationState - 2) > 1) {
+ _animationState = 0;
+ } else {
+ _animationState = 3;
+ }
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeWalk:
+ _animationState = 7;
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeTalk:
+ if (_animationState == 3) {
+ _animationState = 4;
+ _animationFrame = 0;
+ } else {
+ _animationStateNext = 14;
+ _animationNext = 650;
+ _animationState = 1;
+ }
+ break;
+
+ case kAnimationModeCombatIdle:
+ _animationState = 8;
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeCombatAttack:
+ _animationState = 10;
+ _animationFrame = 0;
+ break;
+
+ case 12:
+ _animationStateNext = 15;
+ _animationNext = 651;
+ _animationState = 1;
+ break;
+
+ case 13:
+ _animationStateNext = 16;
+ _animationNext = 652;
+ _animationState = 1;
+ break;
+
+ case 14:
+ _animationStateNext = 17;
+ _animationNext = 653;
+ _animationState = 1;
+ break;
+
+ case 15:
+ _animationStateNext = 18;
+ _animationNext = 654;
+ _animationState = 1;
+ break;
+
+ case 16:
+ _animationStateNext = 18;
+ _animationNext = 654;
+ _animationState = 1;
+ break;
+
+ case 17:
+ _animationStateNext = 20;
+ _animationNext = 656;
+ _animationState = 1;
+ break;
+
+ case kAnimationModeHit:
+ case kAnimationModeCombatHit:
+ _animationState = 12;
+ _animationFrame = 0;
+ break;
+
+ case 23:
+ if (_animationState != 3 && _animationState != 4) {
+ Actor_Set_Invisible(kActorMcCoy, true);
+ _animationState = 2;
+ _animationFrame = 0;
+ } else {
+ _animationState = 5;
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(657) - 1;
+ }
+ break;
+
+ case kAnimationModeDie:
+ _animationState = 13;
+ _animationFrame = 0;
+ break;
+
+ case 71:
+ _animationState = 9;
+ _animationFrame = 0;
+ break;
+
+ case 78:
+ _animationState = 6;
+ _animationFrame = 16;
+ break;
+ }
+
+ return true;
+}
+
+void AIScriptHanoi::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ *animationState = _animationState;
+ *animationFrame = _animationFrame;
+ *animationStateNext = _animationStateNext;
+ *animationNext = _animationNext;
+}
+
+void AIScriptHanoi::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ _animationState = animationState;
+ _animationFrame = animationFrame;
+ _animationStateNext = animationStateNext;
+ _animationNext = animationNext;
+}
+
+bool AIScriptHanoi::ReachedMovementTrackWaypoint(int waypointId) {
+ if (waypointId == 365) {
+ Actor_Face_Actor(kActorHanoi, kActorHysteriaPatron1, true);
+ }
+
+ return true;
+}
+
+void AIScriptHanoi::FledCombat() {
+ // return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/hasan.cpp b/engines/bladerunner/script/ai/hasan.cpp
new file mode 100644
index 0000000000..ed2ebc717f
--- /dev/null
+++ b/engines/bladerunner/script/ai/hasan.cpp
@@ -0,0 +1,315 @@
+/* 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 "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptHasan::AIScriptHasan(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+ _var1 = 6;
+ _var2 = 1;
+ _var3 = 0;
+ _var4 = 0;
+ _var5 = 0;
+ _var6 = 0;
+}
+
+void AIScriptHasan::Initialize() {
+ _animationFrame = 0;
+ _animationState = 0;
+ _animationStateNext = 0;
+ _animationNext = 0;
+
+ _var1 = 6;
+ _var2 = 1;
+ _var3 = 0;
+ _var4 = 0;
+ _var5 = 0;
+ _var6 = 0;
+
+ Actor_Put_In_Set(kActorHasan, 0);
+ Actor_Set_At_XYZ(kActorHasan, -214.0f, 0.0f, -1379.0f, 371);
+ Actor_Set_Goal_Number(kActorHasan, 0);
+}
+
+bool AIScriptHasan::Update() {
+ if (Global_Variable_Query(kVariableChapter) != 3 || Actor_Query_Goal_Number(kActorHasan) >= 300)
+ return false;
+
+ Actor_Set_Goal_Number(kActorHasan, 300);
+ return true;
+}
+
+void AIScriptHasan::TimerExpired(int timer) {
+ //return false;
+}
+
+void AIScriptHasan::CompletedMovementTrack() {
+ //return false;
+}
+
+void AIScriptHasan::ReceivedClue(int clueId, int fromActorId) {
+ //return false;
+}
+
+void AIScriptHasan::ClickedByPlayer() {
+ //return false;
+}
+
+void AIScriptHasan::EnteredScene(int sceneId) {
+ // return false;
+}
+
+void AIScriptHasan::OtherAgentEnteredThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptHasan::OtherAgentExitedThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptHasan::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+ // return false;
+}
+
+void AIScriptHasan::ShotAtAndMissed() {
+ // return false;
+}
+
+bool AIScriptHasan::ShotAtAndHit() {
+ return false;
+}
+
+void AIScriptHasan::Retired(int byActorId) {
+ // return false;
+}
+
+int AIScriptHasan::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+ return 0;
+}
+
+bool AIScriptHasan::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+ if (newGoalNumber == 300) {
+ Actor_Put_In_Set(kActorHasan, kSetFreeSlotH);
+ Actor_Set_At_Waypoint(kActorHasan, 40, 0);
+ }
+ return false;
+}
+
+bool AIScriptHasan::UpdateAnimation(int *animation, int *frame) {
+ if (_var4) {
+ _var4--;
+ }
+ if (_var5) {
+ _var5--;
+ }
+
+ switch (_animationState) {
+ case 0:
+ if (_var6 == 1) {
+ *animation = 922;
+ if (_var3) {
+ _var3--;
+ } else {
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(922)) {
+ _animationFrame = 0;
+ _var6 = 0;
+ *animation = 921;
+ _var1 = Random_Query(6, 14);
+ _var2 = 2 * Random_Query(0, 1) - 1;
+ _var4 = Random_Query(40, 60);
+ }
+ if (_animationFrame >= 10 && _animationFrame <= 14) {
+ _var3 = Random_Query(0, 1);
+ }
+ }
+ } else if (_var6 == 2) {
+ *animation = 923;
+ if (_var3) {
+ _var3--;
+ } else {
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(923)) {
+ _animationFrame = 0;
+ _var6 = 0;
+ *animation = 921;
+ _var1 = Random_Query(6, 14);
+ _var2 = 2 * Random_Query(0, 1) - 1;
+ _var5 = Random_Query(40, 60);
+ }
+ if (_animationFrame == 14) {
+ _var3 = Random_Query(3, 10);
+ }
+ if (_animationFrame == 23) {
+ _var3 = Random_Query(0, 4);
+ }
+ }
+ } else if (_var6 == 0) {
+ *animation = 921;
+ if (_var3) {
+ _var3--;
+ } else {
+ _animationFrame += _var2;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(921)) {
+ _animationFrame = 0;
+ }
+ if (_animationFrame < 0) {
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(921) - 1;
+ }
+ if (!--_var1) {
+ _var2 = 2 * Random_Query(0, 1) - 1;
+ _var1 = Random_Query(6, 14);
+ _var3 = Random_Query(0, 4);
+ }
+ if (!_animationFrame) {
+ _var6 = Random_Query(0, 2);
+ }
+ if (_var6 == 1 && _var4) {
+ _var6 = 0;
+ }
+ if (_var6 == 2 && _var5) {
+ _var6 = 0;
+ }
+ }
+ }
+ break;
+
+ case 1:
+ *animation = 925;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(925)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 2:
+ *animation = 926;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(926)) {
+ _animationFrame = 0;
+ _animationState = 1;
+ *animation = 925;
+ }
+ break;
+
+ case 3:
+ *animation = 927;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(927)) {
+ _animationFrame = 0;
+ _animationState = 1;
+ *animation = 925;
+ }
+ break;
+
+ case 4:
+ *animation = 928;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(928)) {
+ _animationFrame = 0;
+ _animationState = 1;
+ *animation = 925;
+ }
+ break;
+
+ case 5:
+ *animation = 929;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(929)) {
+ _animationFrame = 0;
+ _animationState = 1;
+ *animation = 925;
+ }
+ break;
+
+ case 6:
+ *animation = 930;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(930)) {
+ _animationFrame = 0;
+ _animationState = 1;
+ *animation = 925;
+ }
+ break;
+
+ default:
+ break;
+ }
+ *frame = _animationFrame;
+
+ return true;
+}
+
+bool AIScriptHasan::ChangeAnimationMode(int mode) {
+ switch (mode) {
+ case 0:
+ _animationState = 0;
+ _var6 = 0;
+ _animationFrame = 0;
+ break;
+
+ case 3:
+ _animationState = 1;
+ _var6 = 0;
+ _animationFrame = 0;
+ break;
+
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ _animationState = 6;
+ _var6 = 0;
+ _animationFrame = 0;
+ break;
+
+ default:
+ break;
+ }
+ return true;
+}
+
+void AIScriptHasan::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ *animationState = _animationState;
+ *animationFrame = _animationFrame;
+ *animationStateNext = _animationStateNext;
+ *animationNext = _animationNext;
+}
+
+void AIScriptHasan::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ _animationState = animationState;
+ _animationFrame = animationFrame;
+ _animationStateNext = animationStateNext;
+ _animationNext = animationNext;
+}
+
+bool AIScriptHasan::ReachedMovementTrackWaypoint(int waypointId) {
+ return true;
+}
+
+void AIScriptHasan::FledCombat() {
+ // return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/hysteria_patron1.cpp b/engines/bladerunner/script/ai/hysteria_patron1.cpp
index 44278ac5e9..6eadd74976 100644
--- a/engines/bladerunner/script/ai/hysteria_patron1.cpp
+++ b/engines/bladerunner/script/ai/hysteria_patron1.cpp
@@ -34,7 +34,7 @@ void AIScriptHysteriaPatron1::Initialize() {
_animationNext = 0;
Actor_Put_In_Set(kActorHysteriaPatron1, kSetNR03);
- Actor_Set_At_XYZ(kActorHysteriaPatron1, 50.0f, -6.5900002f, -1030.0f, 524);
+ Actor_Set_At_XYZ(kActorHysteriaPatron1, 50.0f, -6.59f, -1030.0f, 524);
}
bool AIScriptHysteriaPatron1::Update() {
diff --git a/engines/bladerunner/script/ai/leon.cpp b/engines/bladerunner/script/ai/leon.cpp
index fad9da3cfb..fdcb538f0a 100644
--- a/engines/bladerunner/script/ai/leon.cpp
+++ b/engines/bladerunner/script/ai/leon.cpp
@@ -386,7 +386,7 @@ bool AIScriptLeon::ChangeAnimationMode(int mode) {
_animationFrame = 0;
var_45EDAC = 0;
break;
- case kAnimationModeCombatShoot:
+ case kAnimationModeCombatAttack:
_animationState = 10;
_animationFrame = 0;
break;
diff --git a/engines/bladerunner/script/ai/lucy.cpp b/engines/bladerunner/script/ai/lucy.cpp
index aebeac7322..464f228179 100644
--- a/engines/bladerunner/script/ai/lucy.cpp
+++ b/engines/bladerunner/script/ai/lucy.cpp
@@ -227,7 +227,7 @@ void AIScriptLucy::Retired(int byActorId) {
if ((byActorId == kActorSteele || byActorId == kActorMcCoy)
&& Actor_Query_In_Set(kActorSteele, kSetHF06)
&& Actor_Query_In_Set(kActorMcCoy, kSetHF06)) {
- Non_Player_Actor_Combat_Mode_On(kActorSteele, 3, 1, 0, 15, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorSteele, kActorCombatStateUncover, true, kActorMcCoy, 15, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 25, 300, false);
}
if (Query_Difficulty_Level() && byActorId == kActorMcCoy && Game_Flag_Query(46)) {
Global_Variable_Increment(2, 200);
@@ -861,10 +861,10 @@ void AIScriptLucy::checkCombat() {
&& Global_Variable_Query(kVariableChapter) == 5
&& Actor_Query_Goal_Number(kActorLucy) != 450) {
if (Global_Variable_Query(kVariableAffectionTowards) == 3) {
- Global_Variable_Set(45, 0);
+ Global_Variable_Set(kVariableAffectionTowards, 0);
}
Actor_Set_Goal_Number(kActorLucy, 450);
- Non_Player_Actor_Combat_Mode_On(kActorLucy, 0, 0, 0, 4, 0, 1, 2, -1, 0, 0, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorLucy, kActorCombatStateIdle, false, kActorMcCoy, 4, kAnimationModeIdle, kAnimationModeWalk, kAnimationModeRun, -1, 0, 0, 10, 300, false);
}
}
diff --git a/engines/bladerunner/script/ai/luther.cpp b/engines/bladerunner/script/ai/luther.cpp
new file mode 100644
index 0000000000..21df880d64
--- /dev/null
+++ b/engines/bladerunner/script/ai/luther.cpp
@@ -0,0 +1,439 @@
+/* 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 "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptLuther::AIScriptLuther(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+ _flag = false;
+}
+
+void AIScriptLuther::Initialize() {
+ _animationFrame = 0;
+ _animationState = 0;
+ _animationStateNext = 0;
+ _animationNext = 0;
+
+ _flag = false;
+
+ Actor_Put_In_Set(kActorLuther, kSetUG16);
+ Actor_Set_At_XYZ(kActorLuther, 176.91f, -40.67f, 225.92f, 486);
+ Actor_Set_Goal_Number(kActorLuther, 400);
+ Actor_Set_Targetable(kActorLuther, 1);
+}
+
+bool AIScriptLuther::Update() {
+ if (!Actor_Query_Is_In_Current_Set(kActorLuther)
+ || Player_Query_Combat_Mode() != 1
+ || Global_Variable_Query(29)
+ || Game_Flag_Query(596)
+ || Global_Variable_Query(kVariableChapter) != 4) {
+ if (Actor_Query_Goal_Number(kActorLuther) == 400 && Actor_Query_Goal_Number(kActorLuther) != 499) {
+ Actor_Set_Goal_Number(kActorLuther, 401);
+ } else if (Actor_Query_Goal_Number(kActorLuther) == 494) {
+ Actor_Set_Goal_Number(kActorLuther, 495);
+ ChangeAnimationMode(48);
+ } else if (Actor_Query_Goal_Number(kActorLuther) != 495 || Game_Flag_Query(587)) {
+ if (Actor_Query_Goal_Number(kActorLuther) != 497
+ || Global_Variable_Query(29) >= 2
+ || Game_Flag_Query(568)) {
+ if (Actor_Query_Goal_Number(kActorLuther) != 497
+ || Global_Variable_Query(29) <= 1
+ || Game_Flag_Query(568)) {
+ if (Actor_Query_Goal_Number(kActorLuther) == 498) {
+ Game_Flag_Set(595);
+ Actor_Set_Goal_Number(kActorLuther, 499);
+ Actor_Set_Targetable(kActorLuther, 0);
+ } else {
+ return false;
+ }
+ } else {
+ Actor_Set_Targetable(kActorLuther, 0);
+ Actor_Set_Goal_Number(kActorLuther, 498);
+ Actor_Set_Targetable(kActorLuther, 0);
+ }
+ } else {
+ Game_Flag_Set(568);
+ ChangeAnimationMode(50);
+ ChangeAnimationMode(48);
+ Actor_Set_Goal_Number(kActorLuther, 498);
+ Actor_Set_Targetable(kActorLuther, 0);
+ Scene_Loop_Set_Default(5);
+ Scene_Loop_Start_Special(2, 4, 1);
+ Ambient_Sounds_Play_Sound(559, 50, 0, 0, 99);
+ Ambient_Sounds_Remove_Looping_Sound(516, 1);
+ }
+ } else {
+ AI_Countdown_Timer_Reset(kActorLuther, 2);
+ AI_Countdown_Timer_Start(kActorLuther, 2, 5);
+ Actor_Set_Goal_Number(kActorLuther, 496);
+ Game_Flag_Set(587);
+ }
+ } else {
+ Actor_Says(kActorMcCoy, 5720, 12);
+ Actor_Says(kActorLuther, 80, 13);
+ Actor_Says(kActorLance, 40, 12);
+ Game_Flag_Set(596);
+ }
+
+ return false;
+}
+
+void AIScriptLuther::TimerExpired(int timer) {
+ if (timer != 2)
+ return; //false;
+
+ AI_Countdown_Timer_Reset(kActorLuther, 2);
+ Actor_Set_Goal_Number(kActorLuther, 497);
+
+ return; //true;
+}
+
+void AIScriptLuther::CompletedMovementTrack() {
+ if (Actor_Query_Goal_Number(kActorLuther) != 401)
+ return; //false;
+
+ Actor_Set_Goal_Number(kActorLuther, 402);
+
+ return; //true;
+}
+
+void AIScriptLuther::ReceivedClue(int clueId, int fromActorId) {
+ //return false;
+}
+
+void AIScriptLuther::ClickedByPlayer() {
+ //return false;
+}
+
+void AIScriptLuther::EnteredScene(int sceneId) {
+ // return false;
+}
+
+void AIScriptLuther::OtherAgentEnteredThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptLuther::OtherAgentExitedThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptLuther::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+ // return false;
+}
+
+void AIScriptLuther::ShotAtAndMissed() {
+ // return false;
+}
+
+bool AIScriptLuther::ShotAtAndHit() {
+ if (Actor_Query_Which_Set_In(kActorLuther) == 19) {
+ Actor_Set_Health(kActorLuther, 50, 50);
+ }
+ Global_Variable_Increment(29, 1);
+ Music_Stop(2);
+ if (Global_Variable_Query(29) <= 0) {
+ return false;
+ }
+ if (!Game_Flag_Query(560)) {
+ Game_Flag_Set(557);
+ }
+ Actor_Set_Goal_Number(kActorLuther, 494);
+
+ return true;
+}
+
+void AIScriptLuther::Retired(int byActorId) {
+ Actor_Set_Goal_Number(kActorLuther, 599);
+}
+
+int AIScriptLuther::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+ return 0;
+}
+
+bool AIScriptLuther::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+ switch (newGoalNumber) {
+ case 401:
+ AI_Movement_Track_Flush(kActorLuther);
+ AI_Movement_Track_Append(kActorLuther, 39, 20);
+ AI_Movement_Track_Append_With_Facing(kActorLuther, 368, 120, 486);
+ AI_Movement_Track_Append(kActorLuther, 40, 10);
+ AI_Movement_Track_Repeat(kActorLuther);
+ break;
+
+ case 402:
+ Actor_Set_Goal_Number(kActorLuther, 401);
+ break;
+
+ case 403:
+ AI_Movement_Track_Flush(kActorLuther);
+ break;
+
+ case 499:
+ Actor_Set_Goal_Number(kActorLuther, 599);
+ break;
+ }
+
+ return false;
+}
+
+bool AIScriptLuther::UpdateAnimation(int *animation, int *frame) {
+ switch (_animationState) {
+ case 0:
+ *animation = 346;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(346) - 1) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 1:
+ *animation = 348;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(348) - 1) {
+ *animation = 346;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorLuther, 0);
+ }
+ break;
+
+ case 2:
+ if (!_animationFrame && _flag) {
+ *animation = 346;
+ _animationState = 0;
+ } else {
+ *animation = 349;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(349) - 1) {
+ _animationFrame = 0;
+ }
+ }
+ break;
+
+ case 3:
+ *animation = 350;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(350) - 1) {
+ _animationFrame = 0;
+ _animationState = 2;
+ *animation = 349;
+ }
+ break;
+
+ case 4:
+ *animation = 351;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(351) - 1) {
+ _animationFrame = 0;
+ _animationState = 2;
+ *animation = 349;
+ }
+ break;
+
+ case 5:
+ *animation = 352;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(352) - 1) {
+ _animationFrame = 0;
+ _animationState = 2;
+ *animation = 349;
+ }
+ break;
+
+ case 6:
+ *animation = 353;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(353) - 1) {
+ _animationFrame = 0;
+ _animationState = 2;
+ *animation = 349;
+ }
+ break;
+
+ case 7:
+ *animation = 354;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(354) - 1) {
+ _animationFrame = 0;
+ _animationState = 2;
+ *animation = 349;
+ }
+ break;
+
+ case 8:
+ *animation = 355;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(355) - 1) {
+ _animationFrame = 0;
+ _animationState = 2;
+ *animation = 349;
+ }
+ break;
+
+ case 9:
+ *animation = 356;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(356) - 1) {
+ *animation = 346;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorLuther, 0);
+ }
+ break;
+
+ case 10:
+ *animation = 357;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(357) - 1) {
+ Actor_Change_Animation_Mode(kActorLuther, 50);
+ *animation = 358;
+ _animationFrame = 0;
+ }
+ break;
+
+ case 11:
+ *animation = 358;
+ if (_animationFrame < Slice_Animation_Query_Number_Of_Frames(358) - 1) {
+ _animationFrame++;
+ }
+ break;
+
+ case 12:
+ *animation = 359;
+ if (_animationFrame == 12) {
+ Ambient_Sounds_Play_Sound(557, 59, 0, 0, 20);
+ }
+ if (_animationFrame < Slice_Animation_Query_Number_Of_Frames(*animation) - 1) {
+ _animationFrame++;
+ }
+ break;
+
+ default:
+ break;
+ }
+ *frame = _animationFrame;
+
+ return true;
+}
+
+bool AIScriptLuther::ChangeAnimationMode(int mode) {
+ switch (mode) {
+ case 0:
+ if ((unsigned int)(_animationState - 2) > 6) {
+ _animationState = 0;
+ _animationFrame = 0;
+ } else {
+ _flag = 1;
+ }
+ break;
+
+ case 3:
+ _animationState = 2;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 6:
+ _animationState = 9;
+ _animationFrame = 0;
+ break;
+
+ case 12:
+ _animationState = 3;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 13:
+ _animationState = 4;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 14:
+ _animationState = 5;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 15:
+ _animationState = 6;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 16:
+ _animationState = 7;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 17:
+ _animationState = 8;
+ _animationFrame = 0;
+ _flag = 0;
+ break;
+
+ case 23:
+ _animationState = 1;
+ _animationFrame = 0;
+ break;
+
+ case 48:
+ _animationState = 12;
+ _animationFrame = 0;
+ break;
+
+ case 50:
+ _animationState = 11;
+ _animationFrame = 0;
+ break;
+ }
+
+ return true;
+}
+
+void AIScriptLuther::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ *animationState = _animationState;
+ *animationFrame = _animationFrame;
+ *animationStateNext = _animationStateNext;
+ *animationNext = _animationNext;
+}
+
+void AIScriptLuther::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ _animationState = animationState;
+ _animationFrame = animationFrame;
+ _animationStateNext = animationStateNext;
+ _animationNext = animationNext;
+}
+
+bool AIScriptLuther::ReachedMovementTrackWaypoint(int waypointId) {
+ return true;
+}
+
+void AIScriptLuther::FledCombat() {
+ // return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/mccoy.cpp b/engines/bladerunner/script/ai/mccoy.cpp
index 554de0cd80..1e3dff8c1b 100644
--- a/engines/bladerunner/script/ai/mccoy.cpp
+++ b/engines/bladerunner/script/ai/mccoy.cpp
@@ -242,22 +242,22 @@ bool AIScriptMcCoy::ShotAtAndHit() {
void AIScriptMcCoy::Retired(int byActorId) {
if (byActorId == kActorSteele && Actor_Query_In_Set(kActorSteele, kSetHF06)) {
if (Actor_Query_In_Set(kActorDektora, kSetHF06) && Actor_Query_Goal_Number(kActorDektora) != 599) {
- Non_Player_Actor_Combat_Mode_On(kActorSteele, 3, 1, kActorDektora, 15, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorSteele, kActorCombatStateUncover, true, kActorDektora, 15, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 25, 300, false);
} else if (Actor_Query_In_Set(kActorLucy, kSetHF06) && Actor_Query_Goal_Number(kActorLucy) != 599) {
- Non_Player_Actor_Combat_Mode_On(kActorSteele, 3, 1, kActorLucy, 15, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorSteele, kActorCombatStateUncover, true, kActorLucy, 15, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 25, 300, false);
}
}
if (Actor_Query_In_Set(kActorMcCoy, kSetHF05) && Actor_Query_In_Set(kActorOfficerLeary, kSetHF05) && Actor_Query_In_Set(kActorDektora, kSetHF05) && Actor_Query_Goal_Number(kActorDektora) != 599) {
- Non_Player_Actor_Combat_Mode_On(kActorOfficerLeary, 3, 1, kActorDektora, 4, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerLeary, kActorCombatStateUncover, true, kActorDektora, 4, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 25, 300, false);
}
if (Actor_Query_In_Set(kActorMcCoy, kSetHF05) && Actor_Query_In_Set(kActorOfficerGrayford, kSetHF05) && Actor_Query_In_Set(kActorDektora, kSetHF05) && Actor_Query_Goal_Number(kActorDektora) != 599) {
- Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, 3, 1, kActorDektora, 4, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateUncover, true, kActorDektora, 4, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 25, 300, false);
}
if (Actor_Query_In_Set(kActorMcCoy, kSetHF05) && Actor_Query_In_Set(kActorOfficerLeary, kSetHF05) && Actor_Query_In_Set(kActorLucy, kSetHF05) && Actor_Query_Goal_Number(kActorLucy) != 599) {
- Non_Player_Actor_Combat_Mode_On(kActorOfficerLeary, 3, 1, kActorLucy, 4, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerLeary, kActorCombatStateUncover, true, kActorLucy, 4, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 25, 300, false);
}
if (Actor_Query_In_Set(kActorMcCoy, kSetHF05) && Actor_Query_In_Set(kActorOfficerGrayford, kSetHF05) && Actor_Query_In_Set(kActorLucy, kSetHF05) && Actor_Query_Goal_Number(kActorLucy) != 599) {
- Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, 3, 1, kActorLucy, 4, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateUncover, true, kActorLucy, 4, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 25, 300, false);
}
}
@@ -307,7 +307,7 @@ bool AIScriptMcCoy::GoalChanged(int currentGoalNumber, int newGoalNumber) {
return true;
case 230:
dword_45A0FC = Actor_Query_Goal_Number(kActorSteele) == 215;
- Actor_Change_Animation_Mode(kActorMcCoy, kAnimationModeCombatShoot);
+ Actor_Change_Animation_Mode(kActorMcCoy, kAnimationModeCombatAttack);
return true;
case 220:
Actor_Change_Animation_Mode(kActorMcCoy, 75);
@@ -412,7 +412,7 @@ bool AIScriptMcCoy::GoalChanged(int currentGoalNumber, int newGoalNumber) {
case 400:
Actor_Set_Health(kActorMcCoy, 50, 50);
Game_Flag_Set(373);
- v5 = Global_Variable_Query(45);
+ v5 = Global_Variable_Query(kVariableAffectionTowards);
if (v5 == 1) {
Actor_Modify_Friendliness_To_Other(kActorSteele, kActorMcCoy, 3);
} else if (v5 == 2) {
@@ -428,14 +428,14 @@ bool AIScriptMcCoy::GoalChanged(int currentGoalNumber, int newGoalNumber) {
if (Actor_Query_Friendliness_To_Other(kActorSteele, kActorMcCoy) < Actor_Query_Friendliness_To_Other(kActorClovis, kActorMcCoy)) {
Game_Flag_Set(653);
}
- v7 = Global_Variable_Query(45);
+ v7 = Global_Variable_Query(kVariableAffectionTowards);
if (v7 == 1) {
if (Game_Flag_Query(653)) {
- Global_Variable_Set(45, 0);
+ Global_Variable_Set(kVariableAffectionTowards, 0);
}
} else if (v7 == 2 || v7 == 3) {
if (!Game_Flag_Query(653)) {
- Global_Variable_Set(45, 0);
+ Global_Variable_Set(kVariableAffectionTowards, 0);
}
}
if (!Game_Flag_Query(653)) {
@@ -1382,7 +1382,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
break;
}
break;
- case kAnimationModeCombatShoot:
+ case kAnimationModeCombatAttack:
_animationState = 21;
_animationFrame = 0;
break;
@@ -1503,7 +1503,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
}
}
break;
- case 21:
+ case kAnimationModeHit:
switch (_animationState) {
case 14:
case 15:
@@ -1520,7 +1520,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
}
_animationFrame = 0;
break;
- case 16:
+ default:
if (Random_Query(0, 1) == 1) {
_animationState = 26;
} else {
@@ -1530,7 +1530,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
break;
}
break;
- case 22:
+ case kAnimationModeCombatHit:
if (Random_Query(0, 1) == 1) {
_animationState = 23;
} else {
@@ -1587,7 +1587,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
_animationState = 41;
_animationFrame = 0;
break;
- case 48:
+ case kAnimationModeDie:
switch (_animationState) {
case 14:
case 15:
@@ -1610,7 +1610,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
break;
}
break;
- case 49:
+ case kAnimationModeCombatDie:
_animationState = 28;
_animationFrame = 0;
break;
@@ -1622,7 +1622,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
_animationState = 55;
_animationFrame = 0;
break;
- case 53:
+ case kAnimationModeSit:
if (_animationState != 60 && (Player_Query_Current_Set() == kSetNR03 || Player_Query_Current_Set() == kSetNR05_NR08)) {
_animationState = 60;
_animationFrame = 0;
diff --git a/engines/bladerunner/script/ai/mutant1.cpp b/engines/bladerunner/script/ai/mutant1.cpp
index 9ecaf9d80e..eb1c0562af 100644
--- a/engines/bladerunner/script/ai/mutant1.cpp
+++ b/engines/bladerunner/script/ai/mutant1.cpp
@@ -83,7 +83,7 @@ bool AIScriptMutant1::Update() {
case 410:
if (Actor_Query_Which_Set_In(kActorMutant1) != Player_Query_Current_Set()) {
- Non_Player_Actor_Combat_Mode_Off(70);
+ Non_Player_Actor_Combat_Mode_Off(kActorMutant1);
Actor_Set_Goal_Number(kActorMutant1, 403);
}
break;
@@ -326,28 +326,23 @@ bool AIScriptMutant1::GoalChanged(int currentGoalNumber, int newGoalNumber) {
case 410:
switch (Actor_Query_Which_Set_In(kActorMutant1)) {
case kSetUG01:
- Non_Player_Actor_Combat_Mode_On(kActorMutant1, 0, 0, 0, 11, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant1, kActorCombatStateIdle, false, kActorMcCoy, 11, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
case kSetUG04:
case kSetUG05:
case kSetUG06:
- Non_Player_Actor_Combat_Mode_On(kActorMutant1, 0, 0, 0, 10, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant1, kActorCombatStateIdle, false, kActorMcCoy, 10, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
case kSetUG07:
- Non_Player_Actor_Combat_Mode_On(kActorMutant1, 0, 0, 0, 12, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant1, kActorCombatStateIdle, false, kActorMcCoy, 12, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
case kSetUG10:
- Non_Player_Actor_Combat_Mode_On(kActorMutant1, 0, 0, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0);
- break;
-
case kSetUG12:
- Non_Player_Actor_Combat_Mode_On(kActorMutant1, 0, 0, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0);
- break;
case kSetUG14:
- Non_Player_Actor_Combat_Mode_On(kActorMutant1, 0, 0, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant1, kActorCombatStateIdle, false, kActorMcCoy, 14, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
}
return true;
diff --git a/engines/bladerunner/script/ai/mutant2.cpp b/engines/bladerunner/script/ai/mutant2.cpp
index 6a51c710dd..6317311088 100644
--- a/engines/bladerunner/script/ai/mutant2.cpp
+++ b/engines/bladerunner/script/ai/mutant2.cpp
@@ -305,25 +305,19 @@ bool AIScriptMutant2::GoalChanged(int currentGoalNumber, int newGoalNumber) {
case 410:
switch (Actor_Query_Which_Set_In(kActorMutant2)) {
case kSetUG01:
- Non_Player_Actor_Combat_Mode_On(kActorMutant2, 0, 0, 0, 11, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant2, kActorCombatStateIdle, false, kActorMcCoy, 11, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
case kSetUG04:
case kSetUG05:
case kSetUG06:
- Non_Player_Actor_Combat_Mode_On(kActorMutant2, 0, 0, 0, 10, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant2, kActorCombatStateIdle, false, kActorMcCoy, 10, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
case kSetUG10:
- Non_Player_Actor_Combat_Mode_On(kActorMutant2, 0, 0, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0);
- break;
-
case kSetUG12:
- Non_Player_Actor_Combat_Mode_On(kActorMutant2, 0, 0, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0);
- break;
-
case kSetUG14:
- Non_Player_Actor_Combat_Mode_On(kActorMutant2, 0, 0, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant2, kActorCombatStateIdle, false, kActorMcCoy, 14, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
}
return true;
diff --git a/engines/bladerunner/script/ai/mutant3.cpp b/engines/bladerunner/script/ai/mutant3.cpp
index 76a9a0edff..db161d8d5a 100644
--- a/engines/bladerunner/script/ai/mutant3.cpp
+++ b/engines/bladerunner/script/ai/mutant3.cpp
@@ -316,24 +316,19 @@ bool AIScriptMutant3::GoalChanged(int currentGoalNumber, int newGoalNumber) {
case 410:
switch (Actor_Query_Which_Set_In(kActorMutant3)) {
case kSetUG01:
- Non_Player_Actor_Combat_Mode_On(kActorMutant3, 0, 1, 0, 11, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant3, kActorCombatStateIdle, false, kActorMcCoy, 11, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
case kSetUG04:
case kSetUG05:
case kSetUG06:
- Non_Player_Actor_Combat_Mode_On(kActorMutant3, 0, 1, 0, 10, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant3, kActorCombatStateIdle, false, kActorMcCoy, 10, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
case kSetUG10:
- Non_Player_Actor_Combat_Mode_On(kActorMutant3, 0, 1, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0);
- break;
case kSetUG12:
- Non_Player_Actor_Combat_Mode_On(kActorMutant3, 0, 1, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0);
- break;
-
case kSetUG14:
- Non_Player_Actor_Combat_Mode_On(kActorMutant3, 0, 1, 0, 14, 4, 7, 8, -1, -1, -1, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorMutant3, kActorCombatStateIdle, false, kActorMcCoy, 14, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
break;
}
break;
@@ -342,6 +337,7 @@ bool AIScriptMutant3::GoalChanged(int currentGoalNumber, int newGoalNumber) {
AI_Movement_Track_Flush(kActorMutant3);
AI_Movement_Track_Append(kActorMutant3, 39, 100);
AI_Movement_Track_Repeat(kActorMutant3);
+ break;
case 599:
AI_Movement_Track_Flush(kActorMutant3);
diff --git a/engines/bladerunner/script/ai/officer_grayford.cpp b/engines/bladerunner/script/ai/officer_grayford.cpp
new file mode 100644
index 0000000000..a1f9b11f9b
--- /dev/null
+++ b/engines/bladerunner/script/ai/officer_grayford.cpp
@@ -0,0 +1,1422 @@
+/* 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 "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptOfficerGrayford::AIScriptOfficerGrayford(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+ _var1 = 0;
+ _var2 = 0;
+ _var3 = 0;
+}
+
+void AIScriptOfficerGrayford::Initialize() {
+ _animationFrame = 0;
+ _animationState = 0;
+ _animationStateNext = 0;
+ _animationNext = 0;
+
+ _var1 = 0;
+ _var2 = 0;
+ _var3 = 0;
+
+ Actor_Put_In_Set(kActorOfficerGrayford, kSetFreeSlotG);
+ Actor_Set_At_Waypoint(kActorOfficerGrayford, 39, 0);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 0);
+}
+
+bool AIScriptOfficerGrayford::Update() {
+ if (Global_Variable_Query(kVariableChapter) == 4 && Actor_Query_Goal_Number(kActorOfficerGrayford) < 300) {
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 300);
+ } else if (Global_Variable_Query(kVariableChapter) == 5 && Actor_Query_Goal_Number(kActorOfficerGrayford) < 400) {
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 400);
+ } else if (!Game_Flag_Query(177)
+ && Actor_Query_Goal_Number(kActorOfficerGrayford) > 102
+ && Actor_Query_Goal_Number(kActorOfficerGrayford) < 110) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 110);
+ } else if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 0) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 1);
+ } else if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 10) {
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 0);
+ } else if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 102) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 103);
+ } else if (Game_Flag_Query(629)) {
+ AI_Movement_Track_Unpause(kActorGenwalkerA);
+ AI_Movement_Track_Unpause(kActorGenwalkerB);
+ AI_Movement_Track_Unpause(kActorGenwalkerC);
+ } else if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 310
+ && Actor_Query_Which_Set_In(kActorOfficerGrayford) != Player_Query_Current_Set()) {
+ Non_Player_Actor_Combat_Mode_Off(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ } else if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 599
+ && Actor_Query_Which_Set_In(kActorOfficerGrayford) != Player_Query_Current_Set()) {
+ Actor_Set_Health(kActorOfficerGrayford, 50, 50);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ } else if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 305) {
+ switch (Actor_Query_Which_Set_In(kActorOfficerGrayford)) {
+ case kSetRC03:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 18, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetUG01:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 11, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetUG04:
+ case kSetUG05:
+ case kSetUG06:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 10, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetUG08:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 13, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetUG10:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 14, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetUG12:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 16, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetUG14:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 17, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetMA07:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 7, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetNR01:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 3, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetDR01_DR02_DR04:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 0, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetBB01:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 1, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ case kSetCT11:
+ if (Actor_Query_Which_Set_In(kActorOfficerGrayford) == Player_Query_Current_Set()) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 310);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 5, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 10, 300, false);
+ }
+ break;
+
+ }
+ }
+ return false;
+}
+
+void AIScriptOfficerGrayford::TimerExpired(int timer) {
+ if (timer == 2) {
+ AI_Countdown_Timer_Reset(kActorOfficerGrayford, 2);
+ if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 104) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 105);
+ } else if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 105) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 104);
+ }
+ }
+}
+
+void AIScriptOfficerGrayford::CompletedMovementTrack() {
+ switch (Actor_Query_Goal_Number(kActorOfficerGrayford)) {
+ case 1:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 2);
+ break;
+
+ case 2:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 3);
+ break;
+
+ case 3:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 4);
+ break;
+
+ case 4:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 5);
+ break;
+
+ case 5:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 6);
+ break;
+
+ case 6:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 7);
+ break;
+
+ case 7:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 8);
+ break;
+
+ case 8:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 9);
+ break;
+
+ case 9:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 10);
+ break;
+
+ case 104:
+ case 105:
+ if (Random_Query(0, 2)) {
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, 43);
+ } else {
+ AI_Countdown_Timer_Reset(kActorOfficerGrayford, 2);
+ AI_Countdown_Timer_Start(kActorOfficerGrayford, 2, Random_Query(6, 12));
+ }
+ Actor_Face_Waypoint(kActorOfficerGrayford, 97, true);
+ // return false;
+ break;
+
+ case 305:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 306);
+ break;
+
+ case 307:
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateIdle, true, kActorMcCoy, 12, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, -1, -1, 15, 300, false);
+ break;
+
+ case 308:
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, kAnimationModeCombatIdle);
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, true);
+ break;
+
+ }
+
+ // return true;
+}
+
+void AIScriptOfficerGrayford::ReceivedClue(int clueId, int fromActorId) {
+ //return false;
+}
+
+void AIScriptOfficerGrayford::ClickedByPlayer() {
+ switch (Actor_Query_Goal_Number(kActorOfficerGrayford)) {
+ case 1:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 99);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, true);
+ if (Random_Query(1, 2) == 1) {
+ Actor_Says(kActorMcCoy, 5075, 14);
+ } else {
+ Actor_Says(kActorMcCoy, 4515, 13);
+ Actor_Says(kActorOfficerGrayford, 230, 13);
+ }
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 1);
+ break;
+
+ case 2:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 99);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, true);
+ if (Random_Query(1, 2) == 1) {
+ Actor_Says(kActorMcCoy, 5075, 14);
+ } else {
+ Actor_Says(kActorMcCoy, 4515, 13);
+ Actor_Says(kActorOfficerGrayford, 330, 13);
+ }
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 2);
+ break;
+
+ case 3:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 99);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, true);
+ if (Random_Query(1, 2) == 1) {
+ Actor_Says(kActorMcCoy, 5075, 14);
+ } else {
+ Actor_Says(kActorMcCoy, 5075, 14); // bug in the original? Matches the above statement
+ }
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 3);
+ break;
+
+ case 4:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 99);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, true);
+ if (Random_Query(1, 2) == 1) {
+ Actor_Says(kActorMcCoy, 5075, 14);
+ Actor_Says(kActorOfficerGrayford, 160, 13);
+ } else {
+ Actor_Says(kActorMcCoy, 4515, 13);
+ Actor_Says(kActorOfficerGrayford, 330, 13);
+ }
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 4);
+ break;
+
+ case 7:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 99);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Actor_Says(kActorMcCoy, 4515, 14);
+ Actor_Says(kActorOfficerGrayford, 330, 13);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 7);
+ break;
+
+ case 8:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 99);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, true);
+ Actor_Says(kActorMcCoy, 5075, 13);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 8);
+ break;
+
+ case 104:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 199);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Actor_Says(kActorMcCoy, 1005, kAnimationModeTalk);
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Countdown_Timer_Reset(kActorOfficerGrayford, 2);
+ if (_animationState == 35 || _animationState == 34) {
+ _animationState = 37;
+ _animationFrame = 0;
+ }
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, true);
+ Actor_Says(kActorOfficerGrayford, 190, 19);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 104);
+ break;
+
+ case 105:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 199);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Actor_Says(kActorMcCoy, 1005, kAnimationModeTalk);
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Countdown_Timer_Reset(kActorOfficerGrayford, 2);
+ if (_animationState == 35 || _animationState == 34) {
+ _animationState = 37;
+ _animationFrame = 0;
+ }
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, 1);
+ Actor_Says(kActorOfficerGrayford, 190, 19);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 105);
+ break;
+
+ default:
+ return; //false;
+ break;
+ }
+
+ return; //true;
+}
+
+void AIScriptOfficerGrayford::EnteredScene(int sceneId) {
+ // return false;
+}
+
+void AIScriptOfficerGrayford::OtherAgentEnteredThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptOfficerGrayford::OtherAgentExitedThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptOfficerGrayford::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+ // return false;
+}
+
+void AIScriptOfficerGrayford::ShotAtAndMissed() {
+ // return false;
+}
+
+bool AIScriptOfficerGrayford::ShotAtAndHit() {
+ if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 307)
+ Actor_Set_Health(kActorOfficerGrayford, 50, 50);
+
+ return false;
+}
+
+void AIScriptOfficerGrayford::Retired(int byActorId) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 599);
+ Game_Flag_Set(607);
+}
+
+int AIScriptOfficerGrayford::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+ return 0;
+}
+
+bool AIScriptOfficerGrayford::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+ switch (newGoalNumber) {
+ case 1:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 82, Random_Query(5, 20));
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 2:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 76, Random_Query(10, 20));
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 3:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 77, Random_Query(5, 15));
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 4:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 78, Random_Query(5, 15));
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 5:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 6:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 79, Random_Query(5, 15));
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 7:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 80, 1);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 8:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 81, Random_Query(5, 15));
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 9:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 82, Random_Query(5, 15));
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 101:
+ Player_Loses_Control();
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Put_In_Set(kActorOfficerGrayford, kSetDR01_DR02_DR04);
+ Actor_Set_At_Waypoint(kActorOfficerGrayford, 110, 0);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Loop_Actor_Walk_To_Waypoint(kActorOfficerGrayford, 111, 0, false, true);
+
+ _animationState = 23;
+ _animationFrame = kActorMcCoy;
+
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, true);
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+
+ if (Game_Flag_Query(713)) {
+ Actor_Set_Goal_Number(kActorMcCoy, 500);
+ } else {
+ Actor_Says(kActorMcCoy, 960, 15);
+ Actor_Says(kActorMcCoy, 965, 18);
+ _animationState = 24;
+ }
+ return true;
+
+ case 102:
+ return true;
+
+ case 103:
+ Actor_Says(kActorOfficerGrayford, 120, 19);
+ Actor_Says_With_Pause(kActorMcCoy, 970, 0.2f, 13);
+ Actor_Says(kActorMcCoy, 975, 12);
+
+ if (Actor_Clue_Query(kActorMcCoy, kClueMorajiInterview) == 1) {
+ Actor_Says(kActorMcCoy, 980, 16);
+ Actor_Says_With_Pause(kActorOfficerGrayford, 130, 0.1f, 13);
+ Actor_Says(kActorMcCoy, 985, 14);
+ Actor_Says_With_Pause(kActorMcCoy, 990, 0.0f, 17);
+ Actor_Says_With_Pause(kActorOfficerGrayford, 140, 1.0f, 16);
+ Actor_Says_With_Pause(kActorOfficerGrayford, 150, 0.0f, 17);
+ Actor_Says(kActorOfficerGrayford, 160, 15);
+ Actor_Says_With_Pause(kActorMcCoy, 995, 0.3f, 14);
+ }
+
+ Player_Gains_Control();
+
+ if (Actor_Query_Goal_Number(kActorMoraji) == 23) {
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMoraji, 1);
+ } else {
+ Actor_Face_Waypoint(kActorOfficerGrayford, 97, 1);
+ }
+
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, 43);
+
+ if (Player_Query_Current_Scene() == 28) {
+ Actor_Says(kActorOfficerGrayford, 170, kAnimationModeTalk);
+ }
+ return true;
+
+ case 104:
+ AI_Countdown_Timer_Reset(kActorOfficerGrayford, 2);
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 112, 0);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 105:
+ AI_Countdown_Timer_Reset(kActorOfficerGrayford, 2);
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 113, 0);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 106:
+ Actor_Face_Actor(kActorMcCoy, kActorOfficerGrayford, true);
+ Actor_Says(kActorMcCoy, 1000, 14);
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Countdown_Timer_Reset(kActorOfficerGrayford, 2);
+
+ if (_animationState == 35 || _animationState == 34) {
+ _animationState = 37;
+ _animationFrame = 0;
+ }
+
+ Actor_Face_Actor(kActorOfficerGrayford, kActorMcCoy, true);
+ Actor_Says(kActorOfficerGrayford, 180, 18);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, currentGoalNumber);
+ break;
+
+ case 110:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 0);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ AI_Movement_Track_Flush(kActorMoraji);
+ AI_Movement_Track_Append(kActorMoraji, 41, 0);
+ AI_Movement_Track_Repeat(kActorMoraji);
+ return true;
+
+ case 300:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ return true;
+
+ case 305:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ switch (Random_Query(1, 10)) {
+ case 1:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 398, 15);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 399, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 400, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 401, 0);
+ AI_Movement_Track_Append_With_Facing(kActorOfficerGrayford, 402, 3, 276);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 403, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 404, 15);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ return true;
+
+ case 2:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 385, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 242, 2);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 386, 2);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 387, 15);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ return true;
+
+ case 3:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 390, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 391, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 392, 5);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 345, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 393, 15);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ return true;
+
+ case 4:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 381, 15);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 382, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 383, 15);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 382, 3);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 384, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ return true;
+
+ case 5:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 388, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 389, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ return true;
+
+ case 6:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 385, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 242, 2);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 386, 2);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 387, 15);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ return true;
+
+ case 7:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 394, 15);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 395, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 396, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 397, 15);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 396, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 395, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 430, 15);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ return true;
+
+ case 8:
+ switch (Random_Query(1, 7)) {
+ case 1:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 302, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 407, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 408, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ break; // and go to case 9 below
+
+ case 2:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 536, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 537, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 538, 5);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 537, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 536, 0);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ break; // and go to case 9 below
+
+ case 3:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 296, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 409, 2);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 296, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ break; // and go to case 9 below
+
+ case 4:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 411, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 412, 5);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 411, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ break; // and go to case 9 below
+
+ case 5:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 413, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 414, 0);
+ AI_Movement_Track_Append_With_Facing(kActorOfficerGrayford, 431, 0, 1017);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 432, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ break; // and go to case 9 below
+
+ case 6:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 415, 0);
+ AI_Movement_Track_Append_With_Facing(kActorOfficerGrayford, 416, 0, 620);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 417, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 418, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ break; // and go to case 9 below
+
+ case 7:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 405, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 406, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return false;
+
+ }
+ // fall through
+ // TODO bug in the game? there should be nothing track related after AI_Movement_Track_Repeat
+
+ case 9:
+ if (Random_Query(0, 1)) {
+ AI_Movement_Track_Append(kActorOfficerGrayford, 433, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 434, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 435, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ } else {
+ AI_Movement_Track_Append(kActorOfficerGrayford, 420, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 422, 2);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 421, 1);
+ AI_Movement_Track_Append_With_Facing(kActorOfficerGrayford, 422, 4, 182);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 420, 10);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ // TODO bug in the game? Same code bellow looks like a case 10 and are from set 84 whereas upper one are from set 81
+ AI_Movement_Track_Append(kActorOfficerGrayford, 310, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 307, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 309, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 310, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ }
+ return false;
+
+ case 10:
+ AI_Movement_Track_Append(kActorOfficerGrayford, 310, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 307, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 309, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 310, 0);
+ AI_Movement_Track_Append(kActorOfficerGrayford, 35, 30);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return false;
+
+ }
+ return false;
+
+ case 306:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 305);
+ return true;
+
+ case 307:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append_With_Facing(kActorOfficerGrayford, 419, 0, 512);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 308:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ AI_Movement_Track_Append_Run(kActorOfficerGrayford, 440, 0);
+ AI_Movement_Track_Append_Run(kActorOfficerGrayford, 441, 0);
+ AI_Movement_Track_Repeat(kActorOfficerGrayford);
+ return true;
+
+ case 399:
+ AI_Movement_Track_Flush(kActorOfficerGrayford);
+ Actor_Put_In_Set(kActorOfficerGrayford, kSetTB02_TB03);
+ Actor_Set_At_XYZ(kActorOfficerGrayford, -173.89f, 0.0f, 2084.22f, 859);
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, kAnimationModeCombatIdle);
+ return true;
+
+ case 599:
+ _animationState = 32;
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(624) - 1;
+ return true;
+
+ }
+ return false;
+}
+
+bool AIScriptOfficerGrayford::UpdateAnimation(int *animation, int *frame) {
+ switch (_animationState) {
+ case 0:
+ if (!_var1) {
+ *animation = 625;
+ }
+ if (_var1 == 1) {
+ *animation = 626;
+ }
+ if (_var1 == 2) {
+ *animation = 627;
+ }
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+ _animationFrame = 0;
+ _var1 = 0;
+ if (!Random_Query(0, 1)) {
+ _var1 = Random_Query(1, 2);
+ }
+ }
+ break;
+
+ case 1:
+ *animation = 618;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(618)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 2:
+ *animation = 619;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(619)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 5:
+ *animation = 611;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(611)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 6:
+ *animation = 610;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(610)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 9:
+ if (!_animationFrame && _var2) {
+ *animation = 625;
+ _animationState = 0;
+ _var1 = 0;
+ _var2 = 0;
+ } else {
+ *animation = 629;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(629)) {
+ _animationFrame = 0;
+ _animationState = Random_Query(9, 11);
+ }
+ }
+ break;
+
+ case 10:
+ *animation = 630;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(630)) {
+ _animationFrame = 0;
+ _animationState = 9;
+ *animation = 629;
+ }
+ break;
+
+ case 11:
+ *animation = 631;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(631)) {
+ _animationFrame = 0;
+ _animationState = 9;
+ *animation = 629;
+ }
+ break;
+
+ case 12:
+ *animation = 632;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(632)) {
+ _animationFrame = 0;
+ _animationState = 9;
+ *animation = 629;
+ }
+ break;
+
+ case 13:
+ *animation = 633;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(633)) {
+ _animationFrame = 0;
+ _animationState = 9;
+ *animation = 629;
+ }
+ break;
+
+ case 14:
+ *animation = 634;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(634)) {
+ _animationFrame = 0;
+ _animationState = 9;
+ *animation = 629;
+ }
+ break;
+
+ case 15:
+ *animation = 635;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(635)) {
+ _animationFrame = 0;
+ _animationState = 9;
+ *animation = 629;
+ }
+ break;
+
+ case 16:
+ *animation = 636;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(636)) {
+ _animationFrame = 0;
+ _animationState = 9;
+ *animation = 629;
+ }
+ break;
+
+ case 17:
+ *animation = 637;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(637)) {
+ _animationFrame = 0;
+ _animationState = 9;
+ *animation = 629;
+ }
+ break;
+
+ case 18:
+ case 19:
+ *animation = 605;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(605)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 20:
+ *animation = 615;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(615)) {
+ _animationFrame = 0;
+ _animationState = 19;
+ }
+ break;
+
+ case 21:
+ *animation = 616;
+ _animationFrame++;
+ if (_animationFrame == 11) {
+ Ambient_Sounds_Play_Sound(556, 25, 0, 0, 25);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+ *animation = 625;
+ _animationFrame = 0;
+ _animationState = 0;
+ _var1 = 0;
+ if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 101) {
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 102);
+ }
+ }
+ break;
+
+ case 22:
+ *animation = 617;
+ _animationFrame++;
+ if (_animationFrame == 3) {
+ int snd;
+ if (Random_Query(1, 2) == 1) {
+ snd = 9010;
+ } else {
+ snd = 9015;
+ }
+ Sound_Play_Speech_Line(kActorOfficerGrayford, snd, 75, 0, 99);
+ }
+ if (_animationFrame == 5) {
+ Actor_Combat_AI_Hit_Attempt(kActorOfficerGrayford);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(617)) {
+ _animationState = 19;
+ _animationFrame = 0;
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, 4);
+ }
+ break;
+
+ case 23:
+ *animation = 617;
+ if (_animationFrame < 2) {
+ _animationFrame++;
+ }
+ break;
+
+ case 24:
+ *animation = 617;
+ _animationFrame--;
+ if (_animationFrame < 0) {
+ _animationFrame = 0;
+ _animationState = 21;
+ *animation = 616;
+ }
+ break;
+
+ case 27:
+ *animation = 608;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(608) - 1) {
+ _animationFrame = 0;
+ _animationState = 19;
+ *animation = 625;
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, 4);
+ }
+ break;
+
+ case 28:
+ *animation = 609;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(609) - 1) {
+ _animationFrame = 0;
+ _animationState = 19;
+ *animation = 625;
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, 4);
+ }
+ break;
+
+ case 29:
+ *animation = 622;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(622) - 1) {
+ *animation = 605;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, 0);
+ }
+ break;
+
+ case 30:
+ *animation = 623;
+ _animationFrame++;
+ if (_animationFrame > Slice_Animation_Query_Number_Of_Frames(623) - 1) {
+ *animation = 605;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, 0);
+ }
+ break;
+
+ case 31:
+ *animation = 612;
+ if (_animationFrame < Slice_Animation_Query_Number_Of_Frames(612) - 1) {
+ _animationFrame++;
+ }
+ break;
+
+ case 32:
+ *animation = 624;
+ if (_animationFrame < Slice_Animation_Query_Number_Of_Frames(624) - 1) {
+ _animationFrame++;
+ }
+ break;
+
+ case 34:
+ *animation = 639;
+ if (_var3) {
+ _var3--;
+ } else {
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(639)) {
+ if (Random_Query(0, 1)) {
+ *animation = 641;
+ _animationState = 37;
+ } else {
+ *animation = 638;
+ _animationState = 35;
+ }
+ _animationFrame = 0;
+ } else {
+ if (_animationFrame == 12) {
+ _var3 = Random_Query(5, 18);
+ }
+ }
+ }
+ break;
+
+ case 35:
+ *animation = 638;
+ if (_var3) {
+ _var3--;
+ } else {
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(638)) {
+ if (Random_Query(0, 1)) {
+ *animation = 641;
+ _animationState = 37;
+ } else {
+ *animation = 639;
+ _animationState = 34;
+ }
+ _animationFrame = 0;
+ } else {
+ if (_animationFrame == 10) {
+ _var3 = Random_Query(5, 18);
+ }
+ }
+ }
+ break;
+
+ case 36:
+ *animation = 640;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(640)) {
+ _animationFrame = 0;
+ _animationState = 34;
+ *animation = 639;
+ }
+ break;
+
+ case 37:
+ *animation = 641;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(641)) {
+ *animation = 625;
+ _animationState = 0;
+ _animationFrame = 0;
+
+ switch (Actor_Query_Goal_Number(kActorOfficerGrayford)) {
+ case 103:
+ case 104:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 105);
+ break;
+
+ case 105:
+ Actor_Set_Goal_Number(kActorOfficerGrayford, 104);
+ break;
+ }
+ }
+ break;
+
+ default:
+ *animation = 399;
+ break;
+ }
+ *frame = _animationFrame;
+
+ return true;
+}
+
+bool AIScriptOfficerGrayford::ChangeAnimationMode(int mode) {
+ switch (mode) {
+ case kAnimationModeIdle:
+ switch (_animationState) {
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ _var2 = 1;
+ break;
+
+ case 18:
+ {
+ int tmp = _animationFrame;
+ Actor_Change_Animation_Mode(kActorOfficerGrayford, 4);
+ _animationFrame = tmp;
+ _animationState = 19;
+ break;
+ }
+
+ case 19:
+ _animationState = 21;
+ _animationFrame = 0;
+ break;
+
+ case 20:
+ case 21:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ return true;
+
+ default:
+ _animationState = 0;
+ _animationFrame = 0;
+ break;
+ }
+ break;
+
+ case kAnimationModeWalk:
+ if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 101) {
+ _animationState = 6;
+ _animationFrame = 0;
+ } else if (_animationState != 1) {
+ _animationState = 1;
+ _animationFrame = 0;
+ }
+ break;
+
+ case kAnimationModeRun:
+ if (Actor_Query_Goal_Number(kActorOfficerGrayford) == 101) {
+ _animationState = 5;
+ _animationFrame = 0;
+ } else if (_animationState != 2) {
+ _animationState = 2;
+ _animationFrame = 0;
+ }
+ break;
+
+ case kAnimationModeTalk:
+ if (_animationState != 36 && _animationState != 34) {
+ _animationState = 9;
+ _animationFrame = 0;
+ _var2 = 0;
+ }
+ break;
+
+ case kAnimationModeCombatIdle:
+ switch (_animationState) {
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ _animationState = 19;
+ _animationFrame = 0;
+ break;
+
+ case 19:
+ case 20:
+ case 22:
+ case 24:
+ return true;
+
+ case 23:
+ _animationState = 24;
+ _animationFrame = 0;
+ break;
+
+ default:
+ _animationState = 20;
+ _animationFrame = 0;
+ }
+ break;
+
+ case kAnimationModeCombatAim:
+ _animationState = 23;
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeCombatAttack:
+ _animationFrame = 0;
+ _animationState = 22;
+ break;
+
+ case kAnimationModeCombatWalk:
+ _animationState = 6;
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeCombatRun:
+ _animationState = 5;
+ _animationFrame = 0;
+ break;
+
+ case 12:
+ _animationState = 10;
+ _animationFrame = 0;
+ _var2 = 0;
+ break;
+
+ case 13:
+ _animationState = 11;
+ _animationFrame = 0;
+ _var2 = 0;
+ break;
+
+ case 14:
+ _animationState = 12;
+ _animationFrame = 0;
+ _var2 = 0;
+ break;
+
+ case 15:
+ _animationState = 13;
+ _animationFrame = 0;
+ _var2 = 0;
+ break;
+
+ case 16:
+ _animationState = 14;
+ _animationFrame = 0;
+ _var2 = 0;
+ break;
+
+ case 17:
+ _animationState = 15;
+ _animationFrame = 0;
+ _var2 = 0;
+ break;
+
+ case 18:
+ _animationState = 16;
+ _animationFrame = 0;
+ _var2 = 0;
+ break;
+
+ case 19:
+ _animationState = 17;
+ _animationFrame = 0;
+ _var2 = 0;
+ break;
+
+ case kAnimationModeHit:
+ switch (_animationState) {
+ case 19:
+ case 20:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ if (Random_Query(0, 1)) {
+ _animationState = 27;
+ } else {
+ _animationState = 28;
+ }
+ _animationFrame = 0;
+ break;
+
+ case 21:
+ if (Random_Query(0, 1)) {
+ _animationState = 29;
+ } else {
+ _animationState = 30;
+ }
+ _animationFrame = 0;
+ break;
+ }
+ break;
+
+ case kAnimationModeCombatHit:
+ if (Random_Query(0, 1)) {
+ _animationState = 27;
+ } else {
+ _animationState = 28;
+ }
+ _animationFrame = 0;
+ break;
+
+ case 43:
+ _animationState = 36;
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeWalkUp:
+ _animationState = 3;
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeWalkDown:
+ _animationState = 4;
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeCombatWalkUp:
+ _animationState = 7;
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeCombatWalkDown:
+ _animationState = 7;
+ _animationFrame = 0;
+ break;
+
+ case kAnimationModeDie:
+ switch (_animationState) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 7:
+ _animationState = 20;
+ _animationFrame = 0;
+ break;
+
+ case 5:
+ case 6:
+ return true;
+
+ default:
+ _animationState = 32;
+ _animationFrame = 0;
+ break;
+ }
+ break;
+
+ case 58:
+ _animationState = 18;
+ _animationFrame = 0;
+ break;
+
+ }
+
+ return true;
+}
+
+void AIScriptOfficerGrayford::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ *animationState = _animationState;
+ *animationFrame = _animationFrame;
+ *animationStateNext = _animationStateNext;
+ *animationNext = _animationNext;
+}
+
+void AIScriptOfficerGrayford::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ _animationState = animationState;
+ _animationFrame = animationFrame;
+ _animationStateNext = animationStateNext;
+ _animationNext = animationNext;
+}
+
+bool AIScriptOfficerGrayford::ReachedMovementTrackWaypoint(int waypointId) {
+ return true;
+}
+
+void AIScriptOfficerGrayford::FledCombat() {
+ // return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/officer_leary.cpp b/engines/bladerunner/script/ai/officer_leary.cpp
index b18ba0869f..0adbe7c1c0 100644
--- a/engines/bladerunner/script/ai/officer_leary.cpp
+++ b/engines/bladerunner/script/ai/officer_leary.cpp
@@ -979,7 +979,7 @@ bool AIScriptOfficerLeary::ChangeAnimationMode(int mode) {
break;
}
break;
- case kAnimationModeCombatShoot:
+ case kAnimationModeCombatAttack:
_animationState = 24;
_animationFrame = 0;
break;
diff --git a/engines/bladerunner/script/ai/rajif.cpp b/engines/bladerunner/script/ai/rajif.cpp
index 2ac6a5bed5..26cf41282f 100644
--- a/engines/bladerunner/script/ai/rajif.cpp
+++ b/engines/bladerunner/script/ai/rajif.cpp
@@ -115,7 +115,7 @@ bool AIScriptRajif::UpdateAnimation(int *animation, int *frame) {
if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(751)) {
_animationFrame = 0;
}
- } else {
+ } else { // bug in original. Both branches are equal
*animation = 751;
_animationFrame++;
if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(751)) {
diff --git a/engines/bladerunner/script/ai/sadik.cpp b/engines/bladerunner/script/ai/sadik.cpp
new file mode 100644
index 0000000000..9fdb889b6c
--- /dev/null
+++ b/engines/bladerunner/script/ai/sadik.cpp
@@ -0,0 +1,1039 @@
+/* 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 "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptSadik::AIScriptSadik(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+ _flag = 0;
+ _var1 = 0;
+ _var2 = 0;
+ _var3 = 0;
+ _var4 = 1;
+}
+
+void AIScriptSadik::Initialize() {
+ _animationFrame = 0;
+ _animationState = 0;
+ _animationStateNext = 0;
+ _animationNext = 0;
+
+ _flag = 0;
+ _var1 = 0;
+ _var2 = 0;
+ _var3 = 0;
+ _var4 = 1;
+
+ Actor_Put_In_Set(kActorSadik, kSetFreeSlotA);
+ Actor_Set_At_Waypoint(kActorSadik, 33, 0);
+ Actor_Set_Goal_Number(kActorSadik, 100);
+}
+
+bool AIScriptSadik::Update() {
+ if (Global_Variable_Query(kVariableChapter) != 2 || Player_Query_Current_Scene() != 10 || Game_Flag_Query(391)) {
+ if (_var1) {
+ Sound_Play(_var1, 100, 0, 0, 50);
+ _var1 = 0;
+ }
+ if (Global_Variable_Query(kVariableChapter) == 3 && Actor_Query_Goal_Number(kActorSadik) < 200) {
+ Actor_Set_Goal_Number(kActorSadik, 200);
+ }
+ if (Global_Variable_Query(kVariableChapter) == 5 && Actor_Query_Goal_Number(kActorSadik) < 400) {
+ Actor_Set_Goal_Number(kActorSadik, 400);
+ }
+ if (Actor_Query_Goal_Number(kActorSadik) == 411) {
+ if (Game_Flag_Query(657)) {
+ Actor_Set_Goal_Number(kActorSadik, 412);
+ }
+ }
+ return false;
+ } else {
+ Actor_Set_Goal_Number(kActorSadik, 101);
+ Actor_Set_Targetable(kActorSadik, 1);
+ Game_Flag_Set(391);
+ Game_Flag_Set(406);
+ return true;
+ }
+}
+
+void AIScriptSadik::TimerExpired(int timer) {
+ if (!timer) {
+ AI_Countdown_Timer_Reset(kActorSadik, 0);
+
+ switch (Actor_Query_Goal_Number(kActorSadik)) {
+ case 302:
+ Actor_Set_Goal_Number(kActorSadik, 305);
+ break;
+
+ case 303:
+ Actor_Set_Goal_Number(kActorSadik, 305);
+ break;
+
+ case 307:
+ Actor_Set_Goal_Number(kActorSadik, 308);
+ break;
+ }
+ }
+}
+
+void AIScriptSadik::CompletedMovementTrack() {
+ switch (Actor_Query_Goal_Number(kActorSadik)) {
+ case 301:
+ Actor_Set_Goal_Number(kActorSadik, 302);
+ break;
+
+ case 101:
+ Actor_Set_Goal_Number(kActorSadik, 102);
+ break;
+
+ case 104:
+ Actor_Set_Goal_Number(kActorSadik, 105);
+ break;
+
+ case 105:
+ Actor_Set_Goal_Number(kActorSadik, 106);
+ break;
+
+ default:
+ return; //false;
+ }
+
+ return; //true;
+}
+
+void AIScriptSadik::ReceivedClue(int clueId, int fromActorId) {
+ //return false;
+}
+
+void AIScriptSadik::ClickedByPlayer() {
+ if (Actor_Query_Goal_Number(kActorSadik) == 599) {
+ Actor_Face_Actor(kActorMcCoy, kActorSadik, 1);
+ Actor_Says(kActorMcCoy, 8580, 16);
+ }
+}
+
+void AIScriptSadik::EnteredScene(int sceneId) {
+ // return false;
+}
+
+void AIScriptSadik::OtherAgentEnteredThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptSadik::OtherAgentExitedThisScene(int otherActorId) {
+ // return false;
+}
+
+void AIScriptSadik::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+ // return false;
+}
+
+void AIScriptSadik::ShotAtAndMissed() {
+ if (Actor_Query_Goal_Number(kActorSadik) == 414 || Actor_Query_Goal_Number(kActorSadik) == 416) {
+ Game_Flag_Set(714);
+ if (Actor_Query_Which_Set_In(kActorSadik) != 48) {
+ Actor_Set_Goal_Number(kActorSadik, 418);
+ Scene_Exits_Disable();
+ }
+ }
+}
+
+bool AIScriptSadik::ShotAtAndHit() {
+ if (Actor_Query_Goal_Number(kActorSadik) == 301) {
+ if (Game_Flag_Query(48)) {
+ Actor_Set_Health(kActorSadik, 60, 60);
+ } else {
+ Actor_Set_Health(kActorSadik, 40, 40);
+ }
+ return true;
+ } else {
+ if (Actor_Query_Goal_Number(kActorSadik) == 414 || Actor_Query_Goal_Number(kActorSadik) == 416) {
+ Game_Flag_Set(714);
+ if (Actor_Query_Which_Set_In(kActorSadik) != 48) {
+ Actor_Set_Goal_Number(kActorSadik, 418);
+ Scene_Exits_Disable();
+ }
+ }
+ return false;
+ }
+}
+
+void AIScriptSadik::Retired(int byActorId) {
+ if ((Actor_Query_Goal_Number(kActorSadik) == 418 || Actor_Query_Goal_Number(kActorSadik) == 450)
+ && Actor_Query_Which_Set_In(kActorSadik) != 48) {
+ Scene_Exits_Enable();
+ }
+ if (Actor_Query_In_Set(kActorSadik, kSetKP07)) {
+ Global_Variable_Decrement(51, 1);
+ Actor_Set_Goal_Number(kActorSadik, 599);
+
+ if (!Global_Variable_Query(51)) {
+ Player_Loses_Control();
+ Delay(2000);
+ Player_Set_Combat_Mode(0);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, -12.0f, -41.58f, 72.0f, 0, 1, 0, 0);
+ Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+ Ambient_Sounds_Remove_All_Looping_Sounds(1);
+ Game_Flag_Set(579);
+ Game_Flag_Reset(653);
+ Set_Enter(kSetKP05_KP06, kSetKP03);
+ return; //true;
+ }
+ }
+
+ Actor_Set_Goal_Number(kActorSadik, 599);
+
+ return; //false;
+}
+
+int AIScriptSadik::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+ return 0;
+}
+
+bool AIScriptSadik::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+ switch (newGoalNumber) {
+ case 100:
+ AI_Movement_Track_Flush(kActorSadik);
+ AI_Movement_Track_Append(kActorSadik, 33, 0);
+ AI_Movement_Track_Repeat(kActorSadik);
+ return true;
+
+ case 101:
+ AI_Movement_Track_Flush(kActorSadik);
+ AI_Movement_Track_Append_Run(kActorSadik, 131, 0);
+ AI_Movement_Track_Append_Run(kActorSadik, 132, 0);
+ AI_Movement_Track_Append_Run(kActorSadik, 133, 0);
+ AI_Movement_Track_Repeat(kActorSadik);
+ return true;
+
+ case 102:
+ AI_Movement_Track_Flush(kActorSadik);
+ AI_Movement_Track_Append(kActorSadik, 313, 0);
+ AI_Movement_Track_Repeat(kActorSadik);
+ Game_Flag_Set(509);
+ return true;
+
+ case 103:
+ Actor_Set_Immunity_To_Obstacles(kActorSadik, 1);
+ Actor_Face_Heading(kActorSadik, kActorMcCoy, kActorMcCoy);
+ _animationState = 32;
+ _animationFrame = -1;
+ Actor_Change_Animation_Mode(kActorMcCoy, 48);
+ return true;
+
+ case 104:
+ Actor_Set_Goal_Number(kActorMcCoy, 100);
+ AI_Movement_Track_Flush(kActorSadik);
+ AI_Movement_Track_Append(kActorSadik, 314, 0);
+ AI_Movement_Track_Append_Run(kActorSadik, 317, 0);
+ AI_Movement_Track_Repeat(kActorSadik);
+ return true;
+
+ case 105:
+ Actor_Change_Animation_Mode(kActorSadik, 62);
+ return true;
+
+ case 106:
+ Actor_Face_Heading(kActorSadik, 100, 0);
+ Actor_Change_Animation_Mode(kActorSadik, 63);
+ Actor_Set_Goal_Number(kActorClovis, 101);
+ Actor_Set_Immunity_To_Obstacles(kActorSadik, 0);
+ return true;
+
+ case 107:
+ _var1 = 0;
+ return false;
+
+ case 200:
+ Actor_Put_In_Set(kActorSadik, kSetFreeSlotA);
+ Actor_Set_At_Waypoint(kActorSadik, 33, 0);
+ Actor_Set_Goal_Number(kActorMcCoy, 199);
+ return true;
+
+ case 300:
+ Actor_Put_In_Set(kActorSadik, kSetUG18);
+ Actor_Set_At_XYZ(kActorSadik, 111.89f, 0.0f, 408.42f, 0);
+ Actor_Change_Animation_Mode(kActorSadik, 4);
+ return true;
+
+ case 301:
+ Actor_Set_Targetable(kActorSadik, 1);
+ World_Waypoint_Set(436, 89, -356.11f, 0.0f, 652.42f);
+ AI_Movement_Track_Flush(kActorSadik);
+ AI_Movement_Track_Append_Run(kActorSadik, 436, 0);
+ AI_Movement_Track_Repeat(kActorSadik);
+ return true;
+
+ case 302:
+ Actor_Set_Targetable(kActorSadik, 0);
+ return true;
+
+ case 303:
+ AI_Countdown_Timer_Reset(kActorSadik, 0);
+ AI_Countdown_Timer_Start(kActorSadik, 0, 5);
+ return true;
+
+ case 304:
+ Actor_Set_Targetable(kActorSadik, 0);
+ AI_Countdown_Timer_Reset(kActorSadik, 0);
+ return true;
+
+ case 305:
+ case 306:
+ case 310:
+ return true;
+
+ case 307:
+ Sound_Play(12, 100, 0, 0, 50);
+ AI_Countdown_Timer_Start(kActorSadik, 0, 2);
+ return true;
+
+ case 308:
+ if (Player_Query_Current_Scene() == 102) {
+ Actor_Force_Stop_Walking(kActorMcCoy);
+ Actor_Change_Animation_Mode(kActorSadik, 6);
+ Sound_Play(12, 100, 0, 0, 50);
+ Actor_Change_Animation_Mode(kActorMcCoy, 48);
+ Actor_Retired_Here(kActorMcCoy, 6, 6, 1, -1);
+ }
+ return true;
+
+ case 309:
+ AI_Countdown_Timer_Reset(kActorSadik, 0);
+ return true;
+
+ case 400:
+ Actor_Set_Goal_Number(kActorSadik, 410);
+ return true;
+
+ case 410:
+ if (Game_Flag_Query(653) == 1) {
+ Actor_Set_Goal_Number(kActorSadik, 414);
+ } else {
+ Actor_Set_Goal_Number(kActorSadik, 411);
+ }
+ return true;
+
+ case 411:
+ Actor_Put_In_Set(kActorSadik, kSetKP05_KP06);
+ Actor_Set_At_XYZ(kActorSadik, -1134.0f, 0.0f, 73.45f, 398);
+ Actor_Set_Goal_Number(kActorClovis, 513);
+ Actor_Set_Goal_Number(kActorMaggie, 411);
+ return true;
+
+ case 412:
+ Actor_Says(kActorSadik, 60, 3);
+ Actor_Says(kActorMcCoy, 2240, 3);
+ Actor_Says(kActorSadik, 70, 3);
+ Actor_Says(kActorSadik, 80, 3);
+ Actor_Says(kActorMcCoy, 2245, 3);
+ Actor_Says(kActorSadik, 90, 3);
+ Actor_Says(kActorSadik, 100, 3);
+ Actor_Says(kActorMcCoy, 2250, 3);
+ Actor_Set_Goal_Number(kActorSadik, 413);
+ return true;
+
+ case 413:
+ Loop_Actor_Walk_To_XYZ(kActorSadik, -1062.0f, 0.0f, 219.0f, 0, 0, 1, 0);
+ Actor_Set_Targetable(kActorSadik, 1);
+ Non_Player_Actor_Combat_Mode_On(kActorSadik, kActorCombatStateIdle, true, kActorMcCoy, 9, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, -1, -1, 15, 300, false);
+ Actor_Set_Goal_Number(kActorSadik, 450);
+ return true;
+
+ case 414:
+ Actor_Put_In_Set(kActorSadik, kSetKP05_KP06);
+ Actor_Set_At_XYZ(kActorSadik, -961.0f, 0.0f, -778.0f, 150);
+ Actor_Set_Targetable(kActorSadik, 1);
+ return true;
+
+ case 415:
+ Actor_Says(kActorSadik, 110, 3);
+ Actor_Says(kActorMcCoy, 2290, 3);
+ Actor_Says(kActorSadik, 310, 3);
+ Actor_Says(kActorMcCoy, 2300, 3);
+ if (Game_Flag_Query(48)) {
+ Actor_Says(kActorSadik, 180, 3);
+ Actor_Says(kActorSadik, 190, 3);
+ Actor_Says(kActorMcCoy, 2310, 3);
+ Actor_Says(kActorSadik, 200, 3);
+ } else {
+ Actor_Says(kActorSadik, 140, 3);
+ Actor_Says(kActorSadik, 150, 3);
+ Actor_Says(kActorMcCoy, 2305, 3);
+ Actor_Says(kActorSadik, 160, 3);
+ Actor_Says(kActorSadik, 170, 3);
+ }
+ Actor_Says(kActorMcCoy, 2315, 3);
+ Actor_Says(kActorSadik, 210, 3);
+ Actor_Says(kActorSadik, 220, 3);
+ Actor_Says(kActorSadik, 230, 3);
+ Actor_Says(kActorSadik, 240, 3);
+ Actor_Says(kActorSadik, 250, 3);
+ Actor_Says(kActorSadik, 260, 3);
+ Actor_Set_Goal_Number(kActorSadik, 416);
+ return true;
+
+ case 416:
+ Loop_Actor_Walk_To_XYZ(kActorSadik, -961.0f, 0.0f, -778.0f, 0, 0, 0, 0);
+ Actor_Face_Heading(kActorSadik, 150, 0);
+ return true;
+
+ case 417:
+ Actor_Face_Actor(kActorSadik, kActorMcCoy, 1);
+ Actor_Says(kActorSadik, 320, 3);
+ Loop_Actor_Walk_To_XYZ(kActorSadik, -857.0f, 0.0f, -703.0f, 0, 0, 1, 0);
+ Actor_Says(kActorMcCoy, 2330, 3);
+ Actor_Says(kActorSadik, 330, 3);
+ Actor_Says(kActorMcCoy, 2335, 3);
+ Actor_Says(kActorSadik, 340, 3);
+ Actor_Set_Goal_Number(kActorSadik, 416);
+ return true;
+
+ case 418:
+ Game_Flag_Reset(653);
+ Actor_Set_Goal_Number(kActorClovis, 518);
+ Non_Player_Actor_Combat_Mode_On(kActorSadik, kActorCombatStateIdle, true, kActorMcCoy, 9, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, -1, -1, 15, 300, false);
+ return true;
+
+ case 419:
+ Actor_Put_In_Set(kActorSadik, kSetKP07);
+ Actor_Set_At_XYZ(kActorSadik, -12.0f, -41.58f, 72.0f, 0);
+ return true;
+
+ case 420:
+ case 450:
+ return true;
+ }
+ return false;
+}
+
+bool AIScriptSadik::UpdateAnimation(int *animation, int *frame) {
+ switch (_animationState) {
+ case 0:
+ if (_var2 == 1) {
+ *animation = 329;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(329)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _var2 = 0;
+ }
+ } else if (_var2 == 0) {
+ *animation = 328;
+ if (_var3) {
+ _var3--;
+ if (!Random_Query(0, 6)) {
+ _var4 = -_var4;
+ }
+ } else {
+ _animationFrame += _var4;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(328)) {
+ _animationFrame = 0;
+ }
+ if (_animationFrame < 0) {
+ _animationFrame = Slice_Animation_Query_Number_Of_Frames(328) - 1;
+ }
+ if (!Random_Query(0, 4)) {
+ _var3 = 1;
+ }
+ if (!_animationFrame || _animationFrame == 8) {
+ _var3 = Random_Query(2, 8);
+ }
+ if (!Random_Query(0, 2)) {
+ if (!_animationFrame) {
+ _var2 = 1;
+ _var3 = 0;
+ *animation = 329;
+ }
+ }
+ }
+ }
+ break;
+
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ switch (_animationState) {
+ case 1:
+ *animation = 323;
+ break;
+ case 2:
+ *animation = 324;
+ break;
+ case 3:
+ *animation = 317;
+ break;
+ case 4:
+ *animation = 318;
+ break;
+ case 6:
+ *animation = 340;
+ break;
+ case 5:
+ *animation = 339;
+ break;
+ }
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 7:
+ *animation = 312;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(312)) {
+ _animationFrame = 0;
+ }
+ break;
+
+ case 8:
+ *animation = 313;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(313)) {
+ _animationFrame = 0;
+ _animationState = 7;
+ *animation = 312;
+ Actor_Change_Animation_Mode(kActorSadik, 4);
+ }
+ break;
+
+ case 9:
+ *animation = 314;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(314)) {
+ _animationFrame = 0;
+ _animationState = 7;
+ *animation = 312;
+ Actor_Change_Animation_Mode(kActorSadik, 4);
+ }
+ break;
+
+ case 10:
+ *animation = 325;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(325)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorSadik, 0);
+ }
+ break;
+
+ case 11:
+ *animation = 326;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(326)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorSadik, 0);
+ }
+ break;
+
+ case 12:
+ *animation = 315;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(315)) {
+ _animationFrame = 0;
+ _animationState = 7;
+ *animation = 312;
+ Actor_Change_Animation_Mode(kActorSadik, 4);
+ }
+ break;
+
+ case 13:
+ *animation = 316;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(316)) {
+ _animationFrame = 0;
+ _animationState = 7;
+ *animation = 312;
+ Actor_Change_Animation_Mode(kActorSadik, 4);
+ }
+ break;
+
+ case 14:
+ *animation = 327;
+ if (_animationFrame < Slice_Animation_Query_Number_Of_Frames(327) - 1) {
+ _animationFrame++;
+ }
+ break;
+
+ case 15:
+ *animation = 327;
+ if (_animationFrame < Slice_Animation_Query_Number_Of_Frames(327) - 1) {
+ _animationFrame++;
+ }
+ break;
+
+ case 16:
+ *animation = 320;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(320)) {
+ _animationFrame = 0;
+ _animationState = 7;
+ *animation = 312;
+ }
+ break;
+
+ case 17:
+ *animation = 321;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(321)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 18:
+ *animation = 322;
+ _animationFrame++;
+ if (_animationFrame == 5) {
+ int snd;
+ if (Random_Query(1, 2) == 1) {
+ snd = 9010;
+ } else {
+ snd = 9015;
+ }
+ Sound_Play_Speech_Line(8, snd, 75, 0, 99);
+ }
+ if (_animationFrame == 7) {
+ Actor_Combat_AI_Hit_Attempt(kActorSadik);
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(322)) {
+ _animationFrame = 0;
+ _animationState = 7;
+ *animation = 312;
+ Actor_Change_Animation_Mode(kActorSadik, 4);
+ }
+ break;
+
+ case 19:
+ *animation = 331;
+ if (!_animationFrame && _flag) {
+ *animation = 328;
+ _animationState = 0;
+ _flag = 0;
+ } else {
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(331)) {
+ _animationFrame = 0;
+ }
+ }
+ break;
+
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ switch (_animationState) {
+ case 20:
+ *animation = 332;
+ break;
+ case 21:
+ *animation = 333;
+ break;
+ case 22:
+ *animation = 334;
+ break;
+ case 23:
+ *animation = 335;
+ break;
+ case 24:
+ *animation = 336;
+ break;
+ case 25:
+ *animation = 337;
+ break;
+ default:
+ *animation = 338;
+ break;
+ }
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+ _animationFrame = 0;
+ _animationState = 19;
+ *animation = 331;
+ }
+ break;
+
+ case 27:
+ *animation = 330;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(330)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorSadik, 0);
+ }
+ break;
+
+ case 28:
+ *animation = 341;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(341)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 29:
+ *animation = 342;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(342)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+ }
+ break;
+
+ case 30:
+ *animation = 343;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(343)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorSadik, 0);
+ }
+ break;
+
+ case 31:
+ *animation = 344;
+ _animationFrame++;
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(344)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorSadik, 0);
+ }
+ break;
+
+ case 32:
+ *animation = 345;
+ _animationFrame++;
+ if (_animationFrame == 23) {
+ _var1 = 201;
+ }
+ if (_animationFrame >= 25) {
+ _animationFrame = 0;
+ _animationState = 0;
+ *animation = 328;
+ Actor_Set_Goal_Number(kActorSadik, 104);
+ }
+ break;
+
+ case 33:
+ *animation = 344;
+ _animationFrame++;
+ if (Actor_Query_Goal_Number(kActorSadik) == 105) {
+ if (_animationFrame == 4) {
+ _var1 = 221;
+ }
+ if (_animationFrame == 6) {
+ Actor_Change_Animation_Mode(0, 21);
+ }
+ }
+ if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+
+ Actor_Change_Animation_Mode(kActorSadik, 0);
+ if (Actor_Query_Goal_Number(kActorSadik) == 105) {
+ Actor_Change_Animation_Mode(kActorSadik, 63);
+ }
+ }
+ break;
+
+ case 34:
+ *animation = 343;
+ _animationFrame++;
+ if (_animationFrame == 4) {
+ if (Actor_Query_Goal_Number(kActorSadik) == 105) {
+ Actor_Change_Animation_Mode(0, 48);
+ _var1 = 222;
+ } else {
+ Actor_Change_Animation_Mode(0, 68);
+ _var1 = 223;
+ }
+ }
+
+ if (_animationFrame >= 15) {
+ *animation = 328;
+ _animationFrame = 0;
+ _animationState = 0;
+ Actor_Change_Animation_Mode(kActorSadik, 0);
+ if (Actor_Query_Goal_Number(kActorSadik) == 105) {
+ AI_Movement_Track_Flush(kActorSadik);
+ AI_Movement_Track_Append(kActorSadik, 318, 0);
+ AI_Movement_Track_Repeat(kActorSadik);
+ } else {
+ if (Actor_Query_Goal_Number(kActorSadik) == 106) {
+ Actor_Change_Animation_Mode(kActorSadik, 63);
+ }
+ }
+ }
+ break;
+
+ default:
+ *animation = 406;
+ _animationFrame = 0;
+ break;
+ }
+
+ *frame = _animationFrame;
+
+ return true;
+}
+
+bool AIScriptSadik::ChangeAnimationMode(int mode) {
+ Actor_Set_Frame_Rate_FPS(kActorSadik, -2);
+
+ switch (mode) {
+ case 0:
+ switch (_animationState) {
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ _flag = 1;
+ break;
+ case 30:
+ case 31:
+ return 1;
+ default:
+ _animationState = 0;
+ _animationFrame = 0;
+ _var3 = 0;
+ break;
+ }
+ break;
+
+ case 1:
+ _animationFrame = 0;
+ _animationState = 1;
+ break;
+
+ case 2:
+ _animationFrame = 0;
+ _animationState = 2;
+ break;
+
+ case 3:
+ _animationState = 20;
+ _animationFrame = 0;
+ break;
+
+ case 4:
+ switch (_animationState) {
+ case 0:
+ _animationFrame = 0;
+ _animationState = 16;
+ break;
+ case 3:
+ case 4:
+ _animationState = 7;
+ _animationFrame = 0;
+ break;
+ case 7:
+ case 16:
+ case 18:
+ return true;
+ case 17:
+ _animationFrame = 0;
+ _animationState = 7;
+ break;
+ default:
+ _animationFrame = 0;
+ _animationState = 16;
+ break;
+ }
+ break;
+
+ case 5:
+ case 9:
+ case 10:
+ case 11:
+ case 19:
+ case 20:
+ return true;
+
+ case 6:
+ _animationFrame = 0;
+ _animationState = 18;
+ break;
+
+ case 7:
+ _animationFrame = 0;
+ _animationState = 3;
+ break;
+
+ case 8:
+ _animationFrame = 0;
+ _animationState = 4;
+ break;
+
+ case 12:
+ _animationState = 20;
+ _animationFrame = 0;
+ break;
+
+ case 13:
+ _animationState = 21;
+ _animationFrame = 0;
+ break;
+
+ case 14:
+ _animationState = 22;
+ _animationFrame = 0;
+ break;
+
+ case 15:
+ _animationState = 23;
+ _animationFrame = 0;
+ break;
+
+ case 16:
+ _animationState = 24;
+ _animationFrame = 0;
+ break;
+
+ case 17:
+ _animationState = 25;
+ _animationFrame = 0;
+ break;
+
+ case 18:
+ _animationState = 26;
+ _animationFrame = 0;
+ break;
+
+ case 21:
+ switch (_animationState) {
+ case 7:
+ case 8:
+ case 9:
+ case 16:
+ case 17:
+ case 18:
+ if (Random_Query(0, 1)) {
+ _animationState = 13;
+ } else {
+ _animationState = 12;
+ }
+ break;
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ if (Random_Query(0, 1)) {
+ _animationState = 11;
+ } else {
+ _animationState = 10;
+ }
+ break;
+ }
+ _animationFrame = 0;
+ break;
+
+ case 22:
+ if (Random_Query(0, 1)) {
+ _animationState = 12;
+ } else {
+ _animationState = 13;
+ }
+ _animationFrame = 0;
+ break;
+
+ case 23:
+ _animationState = 27;
+ _animationFrame = 0;
+ break;
+
+ case 48:
+ _animationState = 14;
+ _animationFrame = 0;
+ break;
+
+ case 62:
+ if (Actor_Query_Goal_Number(kActorSadik) != 105 && Actor_Query_Goal_Number(kActorSadik) != 106) {
+ _animationState = 31;
+ _animationFrame = 0;
+ } else {
+ _animationState = 33;
+ _animationFrame = 0;
+ }
+ break;
+
+ case 63:
+ if (Actor_Query_Goal_Number(kActorSadik) != 105 && Actor_Query_Goal_Number(kActorSadik) != 106) {
+ _animationState = 30;
+ _animationFrame = 2;
+ } else {
+ _animationState = 34;
+ _animationFrame = 2;
+ }
+ break;
+ }
+ return true;
+}
+
+void AIScriptSadik::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ *animationState = _animationState;
+ *animationFrame = _animationFrame;
+ *animationStateNext = _animationStateNext;
+ *animationNext = _animationNext;
+}
+
+void AIScriptSadik::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ _animationState = animationState;
+ _animationFrame = animationFrame;
+ _animationStateNext = animationStateNext;
+ _animationNext = animationNext;
+}
+
+bool AIScriptSadik::ReachedMovementTrackWaypoint(int waypointId) {
+ return true;
+}
+
+void AIScriptSadik::FledCombat() {
+ // return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/steele.cpp b/engines/bladerunner/script/ai/steele.cpp
index e51a14a8ca..ff2afa1ec3 100644
--- a/engines/bladerunner/script/ai/steele.cpp
+++ b/engines/bladerunner/script/ai/steele.cpp
@@ -419,7 +419,7 @@ bool AIScriptSteele::ShotAtAndHit() {
Actor_Set_Goal_Number(kActorSteele, 271);
if (/* !a1 && */ Actor_Query_In_Set(kActorSteele, kSetHF06))
- Non_Player_Actor_Combat_Mode_On(1, 3, 1, 0, 15, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorSteele, kActorCombatStateUncover, true, kActorMcCoy, 15, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 25, 300, false);
return false;
}
diff --git a/engines/bladerunner/script/ai/taffy_patron.cpp b/engines/bladerunner/script/ai/taffy_patron.cpp
index c7fa3a7165..0bf6861d12 100644
--- a/engines/bladerunner/script/ai/taffy_patron.cpp
+++ b/engines/bladerunner/script/ai/taffy_patron.cpp
@@ -95,13 +95,13 @@ bool AIScriptTaffyPatron::GoalChanged(int currentGoalNumber, int newGoalNumber)
case 250:
Actor_Put_In_Set(kActorTaffyPatron, kSetNR01);
- Actor_Set_At_XYZ(kActorTaffyPatron, -170.39999, 23.68, -850.0, 324);
- Async_Actor_Walk_To_XYZ(kActorTaffyPatron, -390.0, 31.549999, -429.0, 24, 1);
+ Actor_Set_At_XYZ(kActorTaffyPatron, -170.4f, 23.68f, -850.0f, 324);
+ Async_Actor_Walk_To_XYZ(kActorTaffyPatron, -390.0f, 31.55f, -429.0f, 24, 1);
return true;
case 255:
Actor_Put_In_Set(kActorTaffyPatron, kSetNR01);
- Actor_Set_At_XYZ(kActorTaffyPatron, -170.39999, 23.68, -850.0, 324);
+ Actor_Set_At_XYZ(kActorTaffyPatron, -170.4f, 23.68f, -850.0f, 324);
Actor_Change_Animation_Mode(kActorTaffyPatron, 48);
return true;
diff --git a/engines/bladerunner/script/ai/zuben.cpp b/engines/bladerunner/script/ai/zuben.cpp
index 9fe6aa2f10..58cea9d39d 100644
--- a/engines/bladerunner/script/ai/zuben.cpp
+++ b/engines/bladerunner/script/ai/zuben.cpp
@@ -152,7 +152,7 @@ void AIScriptZuben::CompletedMovementTrack() {
Set_Enter(kSetCT06, kSceneCT06);
}
if (Actor_Query_Goal_Number(kActorZuben) == 21) {
- Non_Player_Actor_Combat_Mode_On(kActorZuben, 0, 0, kActorMcCoy, 6, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 15, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorZuben, kActorCombatStateIdle, false, kActorMcCoy, 6, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 15, 300, false);
}
int goal = Actor_Query_Goal_Number(kActorZuben);
if (goal == 200) {
@@ -977,7 +977,7 @@ bool AIScriptZuben::ChangeAnimationMode(int mode) {
break;
}
break;
- case kAnimationModeCombatShoot:
+ case kAnimationModeCombatAttack:
_animationState = 8;
_animationFrame = 0;
break;
diff --git a/engines/bladerunner/script/ai_script.cpp b/engines/bladerunner/script/ai_script.cpp
index 7b28e2db3d..b328824de1 100644
--- a/engines/bladerunner/script/ai_script.cpp
+++ b/engines/bladerunner/script/ai_script.cpp
@@ -22,9 +22,8 @@
#include "bladerunner/script/ai_script.h"
-#include "bladerunner/bladerunner.h"
-
#include "bladerunner/actor.h"
+#include "bladerunner/bladerunner.h"
namespace BladeRunner {
@@ -47,17 +46,24 @@ AIScripts::AIScripts(BladeRunnerEngine *vm, int actorCount) {
_AIScripts[kActorClovis] = new AIScriptClovis(_vm); // 5
_AIScripts[kActorLucy] = new AIScriptLucy(_vm); // 6
_AIScripts[kActorIzo] = new AIScriptIzo(_vm); // 7
+ _AIScripts[kActorSadik] = new AIScriptSadik(_vm); // 8
_AIScripts[kActorCrazylegs] = new AIScriptCrazylegs(_vm); // 9
+ _AIScripts[kActorLuther] = new AIScriptLuther(_vm); // 10
_AIScripts[kActorGrigorian] = new AIScriptGrigorian(_vm); // 11
_AIScripts[kActorTransient] = new AIScriptTransient(_vm); // 12
_AIScripts[kActorLance] = new AIScriptLance(_vm); // 13
+ _AIScripts[kActorBulletBob] = new AIScriptBulletBob(_vm); // 14
_AIScripts[kActorRunciter] = new AIScriptRunciter(_vm); // 15
_AIScripts[kActorInsectDealer] = new AIScriptInsectDealer(_vm); // 16
_AIScripts[kActorTyrellGuard] = new AIScriptTyrellGuard(_vm); // 17
+ _AIScripts[kActorEarlyQ] = new AIScriptEarlyQ(_vm); // 18
_AIScripts[kActorZuben] = new AIScriptZuben(_vm); // 19
+ _AIScripts[kActorHasan] = new AIScriptHasan(_vm); // 20
_AIScripts[kActorMarcus] = new AIScriptMarcus(_vm); // 21
_AIScripts[kActorMia] = new AIScriptMia(_vm); // 22
_AIScripts[kActorOfficerLeary] = new AIScriptOfficerLeary(_vm); // 23
+ _AIScripts[kActorOfficerGrayford] = new AIScriptOfficerGrayford(_vm); // 24
+ _AIScripts[kActorHanoi] = new AIScriptHanoi(_vm); // 25
_AIScripts[kActorBaker] = new AIScriptBaker(_vm); // 26
_AIScripts[kActorDeskClerk] = new AIScriptDeskClerk(_vm); // 27
_AIScripts[kActorHowieLee] = new AIScriptHowieLee(_vm); // 28
@@ -96,6 +102,8 @@ AIScripts::AIScripts(BladeRunnerEngine *vm, int actorCount) {
_AIScripts[kActorNewscaster] = new AIScriptNewscaster(_vm); // 61
_AIScripts[kActorLeon] = new AIScriptLeon(_vm); // 62
_AIScripts[kActorMaleAnnouncer] = new AIScriptMaleAnnouncer(_vm); // 63
+ _AIScripts[kActorFreeSlotA] = new AIScriptFreeSlotA(_vm); // 64
+ _AIScripts[kActorFreeSlotB] = new AIScriptFreeSlotB(_vm); // 65
_AIScripts[kActorMaggie] = new AIScriptMaggie(_vm); // 66
_AIScripts[kActorGenwalkerA] = new AIScriptGenericWalkerA(_vm); // 67
_AIScripts[kActorGenwalkerB] = new AIScriptGenericWalkerB(_vm); // 68
@@ -324,4 +332,43 @@ void AIScripts::changeAnimationMode(int actor, int mode) {
_inScriptCounter--;
}
+void AIScripts::fledCombat(int actor) {
+ if (actor >= _actorCount) {
+ return;
+ }
+
+ _inScriptCounter++;
+ if (_AIScripts[actor]) {
+ _AIScripts[actor]->FledCombat();
+ }
+ _inScriptCounter--;
+}
+
+void AIScripts::setAnimationState(int actor, int animationState, int animationFrame, int animationStateNext, int animationNext) {
+ if (actor >= _actorCount) {
+ return;
+ }
+
+ _inScriptCounter++;
+ if (_AIScripts[actor]) {
+ _AIScripts[actor]->SetAnimationState(animationState, animationFrame, animationStateNext, animationNext);
+ }
+ _inScriptCounter--;
+}
+
+
+void AIScripts::queryAnimationState(int actor, int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+ if (actor >= _actorCount) {
+ return;
+ }
+
+ _inScriptCounter++;
+ if (_AIScripts[actor]) {
+ _AIScripts[actor]->FledCombat();
+ _AIScripts[actor]->QueryAnimationState(animationState, animationFrame, animationStateNext, animationNext);
+ }
+ _inScriptCounter--;
+}
+
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai_script.h b/engines/bladerunner/script/ai_script.h
index 32bbce092f..9cafa28039 100644
--- a/engines/bladerunner/script/ai_script.h
+++ b/engines/bladerunner/script/ai_script.h
@@ -61,7 +61,7 @@ public:
virtual bool GoalChanged(int currentGoalNumber, int newGoalNumber) = 0;
virtual bool UpdateAnimation(int *animation, int *frame) = 0;
virtual bool ChangeAnimationMode(int mode) = 0;
- virtual void QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *nextAnimation) = 0;
+ virtual void QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) = 0;
virtual void SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) = 0;
virtual bool ReachedMovementTrackWaypoint(int waypointId) = 0;
virtual void FledCombat() = 0;
@@ -189,10 +189,22 @@ DECLARE_SCRIPT(Izo)
void modifyWaypoints();
END_SCRIPT
+DECLARE_SCRIPT(Sadik)
+ int _var1;
+ int _var2;
+ int _var3;
+ int _var4;
+ bool _flag;
+END_SCRIPT
+
DECLARE_SCRIPT(Crazylegs)
bool _flag;
END_SCRIPT
+DECLARE_SCRIPT(Luther)
+ bool _flag;
+END_SCRIPT
+
DECLARE_SCRIPT(Grigorian)
int var_45CA10;
int var_45CA14;
@@ -204,6 +216,13 @@ END_SCRIPT
DECLARE_SCRIPT(Lance)
END_SCRIPT
+DECLARE_SCRIPT(BulletBob)
+ int _var1;
+ int _var2;
+ int _var3;
+ int _var4;
+END_SCRIPT
+
DECLARE_SCRIPT(Runciter)
int var_45CD78;
int var_45CD7C;
@@ -225,6 +244,13 @@ DECLARE_SCRIPT(TyrellGuard)
bool _flag1;
END_SCRIPT
+DECLARE_SCRIPT(EarlyQ)
+ int _var1;
+ int _var2;
+ int _var3;
+ bool _flag;
+END_SCRIPT
+
DECLARE_SCRIPT(Zuben)
int _var_45D258;
int _var_45D25C;
@@ -235,6 +261,15 @@ DECLARE_SCRIPT(Zuben)
void dialogue();
END_SCRIPT
+DECLARE_SCRIPT(Hasan)
+ int _var1;
+ int _var2;
+ int _var3;
+ int _var4;
+ int _var5;
+ int _var6;
+END_SCRIPT
+
DECLARE_SCRIPT(Marcus)
END_SCRIPT
@@ -250,6 +285,19 @@ DECLARE_SCRIPT(OfficerLeary)
bool sub_431420();
END_SCRIPT
+DECLARE_SCRIPT(OfficerGrayford)
+ int _var1;
+ int _var2;
+ int _var3;
+END_SCRIPT
+
+DECLARE_SCRIPT(Hanoi)
+ int _var1;
+ int _var2;
+ int _var3;
+ int _var4;
+END_SCRIPT
+
DECLARE_SCRIPT(Baker)
END_SCRIPT
@@ -411,6 +459,24 @@ END_SCRIPT
DECLARE_SCRIPT(MaleAnnouncer)
END_SCRIPT
+DECLARE_SCRIPT(FreeSlotA)
+ int _var1;
+ int _var2;
+ float _var3;
+ float _var4;
+ float _var5;
+
+ void calcHit();
+ void processGoal306();
+END_SCRIPT
+
+DECLARE_SCRIPT(FreeSlotB)
+ int _var1;
+ int _var2;
+
+ void processGoal301();
+END_SCRIPT
+
DECLARE_SCRIPT(Maggie)
int var_45F3F8;
int var_45F3FC;
@@ -500,8 +566,16 @@ public:
bool reachedMovementTrackWaypoint(int actor, int waypointId);
void updateAnimation(int actor, int *animation, int *frame);
void changeAnimationMode(int actor, int mode);
+ void queryAnimationState(int actor, int *animationState, int *animationFrame, int *animationStateNext, int *animationNext);
+ void setAnimationState(int actor, int animationState, int animationFrame, int animationStateNext, int animationNext);
+ void fledCombat(int actor);
bool isInsideScript() const { return _inScriptCounter > 0; }
+
+ void callChangeAnimationMode(int actor, int mode) { _AIScripts[actor]->ChangeAnimationMode(mode); }
+ int callGetFriendlinessModifierIfGetsClue(int actor, int otherActorId, int clueId) {
+ return _AIScripts[actor]->GetFriendlinessModifierIfGetsClue(otherActorId, clueId);
+ }
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/police_maze.cpp b/engines/bladerunner/script/police_maze.cpp
new file mode 100644
index 0000000000..a85fa07451
--- /dev/null
+++ b/engines/bladerunner/script/police_maze.cpp
@@ -0,0 +1,603 @@
+/* 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 "bladerunner/bladerunner.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/items.h"
+#include "bladerunner/mouse.h"
+#include "bladerunner/savefile.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/scene_objects.h"
+#include "bladerunner/script/police_maze.h"
+#include "bladerunner/script/scene_script.h"
+
+namespace BladeRunner {
+
+PoliceMaze::PoliceMaze(BladeRunnerEngine *vm) : ScriptBase(vm) {
+ reset();
+
+ for (int i = 0; i < kNumMazeTracks; i++) {
+ _tracks[i] = new PoliceMazeTargetTrack(vm);
+ }
+}
+
+PoliceMaze::~PoliceMaze() {
+ for (int i = 0; i < kNumMazeTracks; i++) {
+ delete _tracks[i];
+ }
+
+ reset();
+}
+
+void PoliceMaze::reset() {
+ _isPaused = false;
+ _isActive = false;
+ _isEnding = false;
+
+ for (int i = 0; i < kNumMazeTracks; i++) {
+ _tracks[i] = 0;
+ }
+
+ _pm_var1 = 0;
+ _pm_var2 = 0;
+}
+
+void PoliceMaze::clear(bool isLoadingGame) {
+ for (int i = 0; i < kNumMazeTracks; i++) {
+ if (_tracks[i]->isPresent()) {
+ _tracks[i]->clear(isLoadingGame);
+ }
+ }
+}
+
+void PoliceMaze::activate() {
+ _isActive = true;
+ _isEnding = false;
+}
+
+void PoliceMaze::setPauseState(bool state) {
+ warning("PAUSE: %d", state);
+ _isPaused = state;
+
+ uint32 t = _vm->getTotalPlayTime();
+
+ for (int i = 0; i < kNumMazeTracks; i++) {
+ _tracks[i]->setTime(t);
+ }
+}
+
+void PoliceMaze::tick() {
+ if (_isPaused) {
+ return;
+ }
+
+ if (_vm->_scene->getSetId() != kSetPS10_PS11_PS12_PS13) {
+ return;
+ }
+
+ if (_isEnding) {
+ _isActive = false;
+ return;
+ }
+
+ for (int i = 0; i < kNumMazeTracks; i++) {
+ _tracks[i]->tick();
+ }
+
+ bool notFound = true;
+ for (int i = 0; i < kNumMazeTracks; i++) {
+ if (!_tracks[i]->isPaused()) {
+ notFound = false;
+ break;
+ }
+ }
+
+ if (notFound && _isActive && !_isEnding) {
+ _isActive = false;
+ _isEnding = true;
+
+ if (_vm->_scene->getSceneId() == kScenePS13) {
+ Actor_Voice_Over(320, kActorAnsweringMachine);
+ } else {
+ Actor_Voice_Over(310, kActorAnsweringMachine);
+ }
+ }
+}
+
+void PoliceMaze::save(SaveFileWriteStream &f) {
+ f.writeBool(_isPaused);
+ f.writeBool(_isActive);
+ f.writeBool(_isEnding);
+ for (int i = 0; i < kNumMazeTracks; ++i) {
+ _tracks[i]->save(f);
+ }
+}
+
+void PoliceMaze::load(SaveFileReadStream &f) {
+ _isPaused = f.readBool();
+ _isActive = f.readBool();
+ _isEnding = f.readBool();
+ for (int i = 0; i < kNumMazeTracks; ++i) {
+ _tracks[i]->load(f);
+ }
+}
+
+PoliceMazeTargetTrack::PoliceMazeTargetTrack(BladeRunnerEngine *vm) : ScriptBase(vm) {
+ reset();
+}
+
+PoliceMazeTargetTrack::~PoliceMazeTargetTrack() {
+ reset();
+}
+
+void PoliceMazeTargetTrack::reset() {
+ _isPresent = false;
+ _itemId = -1;
+ _pointCount = 0;
+ _data = nullptr;
+ _dataIndex = 0;
+ _timeLeftUpdate = 0;
+ _timeLeftWait = 0;
+ _time = 0;
+ _isWaiting = false;
+ _isMoving = false;
+ _pointIndex = 0;
+ _pointTarget = 0;
+ _isRotating = false;
+ _angleTarget = 0;
+ _angleDelta = 0;
+ _isPaused = true;
+}
+
+void PoliceMazeTargetTrack::clear(bool isLoadingGame) {
+ reset();
+}
+
+void PoliceMazeTargetTrack::add(int trackId, float startX, float startY, float startZ, float endX, float endY, float endZ, int steps, const int *instructions, bool isActive) {
+ _data = (const int *)instructions;
+
+ if (true /* !GameIsLoading */) { // TODO: FIXME
+ _itemId = trackId;
+ _pointCount = steps;
+ _dataIndex = 0;
+
+ double coef = 1.0f / (long double)steps;
+
+ double coefX = (endX - startX) * coef;
+ double coefY = (endY - startY) * coef;
+ double coefZ = (endZ - startZ) * coef;
+
+ for (int i = 0; i < steps - 1; i++) {
+ _points[i].x = i * coefX + startX;
+ _points[i].y = i * coefY + startY;
+ _points[i].z = i * coefZ + startZ;
+ }
+
+ _points[steps - 1].x = endX;
+ _points[steps - 1].y = endY;
+ _points[steps - 1].z = endZ;
+
+ _isPaused = !isActive;
+ }
+ _isPresent = true;
+}
+
+bool PoliceMazeTargetTrack::tick() {
+ if (!_isPresent) {
+ return false;
+ }
+
+ uint32 oldTime = _time;
+ _time = _vm->getTotalPlayTime();
+ int32 timeDiff = _time - oldTime;
+ _timeLeftUpdate -= timeDiff;
+
+ if (_timeLeftUpdate > 0) {
+ return false;
+ }
+
+ _timeLeftUpdate = 66;
+
+ if (_isPaused) {
+ return false;
+ }
+
+ if (_isWaiting) {
+ _timeLeftWait -= timeDiff;
+
+ if (_timeLeftWait > 0) {
+ return true;
+ }
+
+ _isWaiting = false;
+ _timeLeftWait = 0;
+ }
+
+ if (_vm->_items->isSpinning(_itemId)) {
+ return true;
+ }
+
+ if (_isRotating) {
+ float angle = _vm->_items->getFacing(_itemId) + _angleDelta;
+
+ if (_angleDelta > 0) {
+ if (angle >= _angleTarget) {
+ angle = _angleTarget;
+ _isRotating = false;
+ }
+ } else if (_angleDelta < 0) {
+ if (angle <= _angleTarget) {
+ angle = _angleTarget;
+ _isRotating = false;
+ }
+ } else {
+ _isRotating = false;
+ }
+
+ _vm->_items->setFacing(_itemId, angle);
+
+ if (_isRotating)
+ return false;
+ }
+
+ bool advancePoint = false;
+
+ if (_isMoving) {
+ if (_pointIndex < _pointTarget) {
+ _pointIndex++;
+ advancePoint = true;
+ } else if (_pointIndex > _pointTarget) {
+ _pointIndex--;
+ advancePoint = true;
+ } else {
+ _isMoving = 0;
+ }
+ }
+
+ if (advancePoint) {
+ _vm->_items->setXYZ(_itemId, _points[_pointIndex]);
+ readdObject(_itemId);
+
+ return true;
+ }
+
+ bool cont = true;
+
+ while (cont) {
+ _dataIndex++;
+
+ debug ("ItemId %3i, pos %3i, instruction %3i", _itemId, _dataIndex - 1, _data[_dataIndex - 1]);
+
+ switch (_data[_dataIndex - 1]) {
+ case kPMTIActivate:
+ {
+ int variableId = _data[_dataIndex++];
+ int maxValue = _data[_dataIndex++];
+
+ if (Global_Variable_Query(variableId) >= maxValue) {
+ setPaused();
+ cont = false;
+ } else {
+ cont = true;
+ }
+ break;
+ }
+
+ case kPMTILeave:
+ if (!_vm->_items->isPoliceMazeEnemy(_itemId) && _vm->_items->isTarget(_itemId)) {
+ Police_Maze_Increment_Score(1);
+ }
+ break;
+
+ case kPMTIShoot:
+ {
+ int soundId = _data[_dataIndex++];
+ _dataIndex++; // second argument is not used
+
+ if (_vm->_items->isTarget(_itemId)) {
+ Sound_Play(soundId, 90, 0, 0, 50);
+ Police_Maze_Decrement_Score(1);
+ Actor_Force_Stop_Walking(kActorMcCoy);
+
+ if (Player_Query_Combat_Mode()) {
+ Actor_Change_Animation_Mode(kActorMcCoy, kAnimationModeCombatHit);
+ } else {
+ Actor_Change_Animation_Mode(kActorMcCoy, kAnimationModeHit);
+ }
+
+ int snd;
+
+ if (Random_Query(1, 2) == 1) {
+ snd = 9900;
+ } else {
+ snd = 9905;
+ }
+ Sound_Play_Speech_Line(kActorMcCoy, snd, 75, 0, 99);
+
+ _vm->_mouse->setMouseJitterDown();
+ }
+
+ cont = false;
+ break;
+ }
+
+ case kPMTIEnemyReset:
+ {
+ int itemId = _data[_dataIndex++];
+ _vm->_items->setPoliceMazeEnemy(itemId, false);
+ break;
+ }
+
+ case kPMTIEnemySet:
+ {
+ int itemId = _data[_dataIndex++];
+ _vm->_items->setPoliceMazeEnemy(itemId, true);
+ break;
+ }
+
+ case kPMTIFlagReset:
+ {
+ int gameFlagId = _data[_dataIndex++];
+ Game_Flag_Reset(gameFlagId);
+ break;
+ }
+
+ case kPMTIFlagSet:
+ {
+ int gameFlagId = _data[_dataIndex++];
+ Game_Flag_Set(gameFlagId);
+ break;
+ }
+
+ case kPMTIVariableDec:
+ {
+ int variableId = _data[_dataIndex++];
+ Global_Variable_Decrement(variableId, 1);
+ break;
+ }
+
+ case kPMTIVariableInc:
+ {
+ int variableId = _data[_dataIndex++];
+ int maxValue = _data[_dataIndex++];
+ if (Global_Variable_Query(variableId) < maxValue) {
+ Global_Variable_Increment(variableId, 1);
+ }
+ break;
+ }
+
+ case kPMTIVariableReset:
+ {
+ int variableId = _data[_dataIndex++];
+ Global_Variable_Reset(variableId);
+ break;
+ }
+
+ case kPMTIVariableSet:
+ {
+ int variableId = _data[_dataIndex++];
+ int value = _data[_dataIndex++];
+ Global_Variable_Set(variableId, value);
+ break;
+ }
+
+ case kPMTITargetSet:
+ {
+ int itemId = _data[_dataIndex++];
+ int value = _data[_dataIndex++];
+ _vm->_items->setIsTarget(itemId, value);
+ break;
+ }
+
+ case kPMTI12:
+ {
+ int trackId1 = _data[_dataIndex++];
+ int trackId2 = _data[_dataIndex++];
+ int trackId3 = _data[_dataIndex++];
+
+ switch (Random_Query(1, 3)) {
+ case 1:
+ _vm->_policeMaze->_tracks[trackId1]->resetPaused();
+ break;
+
+ case 2:
+ _vm->_policeMaze->_tracks[trackId2]->resetPaused();
+ break;
+
+ case 3:
+ _vm->_policeMaze->_tracks[trackId3]->resetPaused();
+ break;
+ }
+
+ break;
+ }
+
+ case kPMTI13:
+ {
+ int trackId1 = _data[_dataIndex++];
+ int trackId2 = _data[_dataIndex++];
+
+ if (Random_Query(1, 2) == 1) {
+ _vm->_policeMaze->_tracks[trackId1]->resetPaused();
+ } else {
+ _vm->_policeMaze->_tracks[trackId2]->resetPaused();
+ }
+ break;
+ }
+
+ case kPMTIPausedSet:
+ {
+ int trackId = _data[_dataIndex++];
+ _vm->_policeMaze->_tracks[trackId]->setPaused();
+ break;
+ }
+
+ case kPMTIPausedReset:
+ {
+ int trackId = _data[_dataIndex++];
+ _vm->_policeMaze->_tracks[trackId]->resetPaused();
+ break;
+ }
+
+ case kPMTIPlaySound:
+ {
+ int soundId = _data[_dataIndex++];
+ int volume = _data[_dataIndex++];
+ Sound_Play(soundId, volume, 0, 0, 50);
+ break;
+ }
+
+ case kPMTIObstacleReset:
+ {
+ int itemId = _data[_dataIndex++];
+ _vm->_items->setIsObstacle(itemId, 0);
+ break;
+ }
+
+ case kPMTIObstacleSet:
+ {
+ int itemId = _data[_dataIndex++];
+ _vm->_items->setIsObstacle(itemId, 1);
+ break;
+ }
+
+ case kPMTIWaitRandom:
+ {
+ int randomMin = _data[_dataIndex++];
+ int randomMax = _data[_dataIndex++];
+ _timeLeftWait = Random_Query(randomMin, randomMax);
+ _isWaiting = true;
+
+ cont = false;
+ break;
+ }
+
+ case kPMTIRotate:
+ _angleTarget = _data[_dataIndex++];
+ _angleDelta = _data[_dataIndex++];
+ _isRotating = true;
+
+ cont = false;
+ break;
+
+ case kPMTIFacing:
+ {
+ int angle = _data[_dataIndex++];
+ _vm->_items->setFacing(_itemId, angle);
+ break;
+ }
+
+ case kPMTIRestart:
+ _dataIndex = 0;
+
+ cont = false;
+ break;
+
+ case kPMTIWait:
+ _timeLeftWait = _data[_dataIndex++];
+ _isWaiting = true;
+
+ cont = false;
+ break;
+
+ case kPMTIMove:
+ _pointTarget = _data[_dataIndex++];
+ _isMoving = true;
+
+ cont = false;
+ break;
+
+ case kPMTIPosition:
+ _pointIndex = _data[_dataIndex++];
+ _isMoving = false;
+ _vm->_items->setXYZ(_itemId, _points[_pointIndex]);
+ readdObject(_itemId);
+ break;
+
+ default:
+ return false;
+ }
+
+ if (_isPaused || _isWaiting) {
+ cont = false;
+ }
+ }
+
+ return true;
+}
+
+void PoliceMazeTargetTrack::readdObject(int itemId) {
+ if (_vm->_sceneObjects->remove(itemId + kSceneObjectOffsetItems)) {
+ const BoundingBox &boundingBox = _vm->_items->getBoundingBox(itemId);
+ const Common::Rect &screenRect = _vm->_items->getScreenRectangle(itemId);
+ bool targetable = _vm->_items->isTarget(itemId);
+ bool obstacle = _vm->_items->isVisible(itemId);
+
+ _vm->_sceneObjects->addItem(itemId + kSceneObjectOffsetItems, boundingBox, screenRect, targetable, obstacle);
+ }
+}
+
+void PoliceMazeTargetTrack::save(SaveFileWriteStream &f) {
+ f.writeBool(_isPresent);
+ f.writeInt(_itemId);
+ f.writeInt(_pointCount);
+ f.writeInt(_dataIndex);
+ f.writeBool(_isWaiting);
+ f.writeBool(_isMoving);
+ f.writeInt(_pointIndex);
+ f.writeInt(_pointTarget);
+ f.writeBool(_isRotating);
+ f.writeInt(_angleTarget);
+ f.writeInt(_angleDelta);
+ f.writeBool(_isPaused);
+
+ for (int i = 0; i < kNumTrackPoints; ++i) {
+ f.writeVector3(_points[i]);
+ }
+
+ f.writeInt(_timeLeftUpdate);
+ f.writeInt(_timeLeftWait);
+}
+
+void PoliceMazeTargetTrack::load(SaveFileReadStream &f) {
+ _isPresent = f.readBool();
+ _itemId = f.readInt();
+ _pointCount = f.readInt();
+ _dataIndex = f.readInt();
+ _isWaiting = f.readBool();
+ _isMoving = f.readBool();
+ _pointIndex = f.readInt();
+ _pointTarget = f.readInt();
+ _isRotating = f.readBool();
+ _angleTarget = f.readInt();
+ _angleDelta = f.readInt();
+ _isPaused = f.readBool();
+
+ for (int i = 0; i < kNumTrackPoints; ++i) {
+ _points[i] = f.readVector3();
+ }
+
+ _timeLeftUpdate = f.readInt();
+ _timeLeftWait = f.readInt();
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/police_maze.h b/engines/bladerunner/script/police_maze.h
new file mode 100644
index 0000000000..725fbd4319
--- /dev/null
+++ b/engines/bladerunner/script/police_maze.h
@@ -0,0 +1,106 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BLADERUNNER_SCRIPT_POLICE_MAZE_H
+#define BLADERUNNER_SCRIPT_POLICE_MAZE_H
+
+#include "bladerunner/script/script.h"
+#include "bladerunner/vector.h"
+
+namespace BladeRunner {
+
+enum {
+ kNumMazeTracks = 64,
+ kNumTrackPoints = 100
+};
+
+class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
+
+class PoliceMazeTargetTrack : ScriptBase {
+ uint32 _time;
+ bool _isPresent;
+ int _itemId;
+ int _pointCount;
+ Vector3 _points[kNumTrackPoints];
+ const int *_data;
+ int _dataIndex;
+ int32 _timeLeftUpdate;
+ int32 _timeLeftWait;
+ bool _isWaiting;
+ int _isMoving;
+ int _pointIndex;
+ int _pointTarget;
+ bool _isRotating;
+ int _angleTarget;
+ int _angleDelta;
+ bool _isPaused;
+
+public:
+ PoliceMazeTargetTrack(BladeRunnerEngine *vm);
+ ~PoliceMazeTargetTrack();
+
+ void reset();
+ void clear(bool isLoadingGame);
+ void add(int trackId, float startX, float startY, float startZ, float endX, float endY, float endZ, int steps, const int *instructions, bool isActive);
+
+ bool tick();
+ bool isPresent() const { return _isPresent; }
+ void setPaused() { _isPaused = true; }
+ void resetPaused() { _isPaused = false; }
+ bool isPaused() const { return _isPaused; }
+ void setTime(uint32 t) { _time = t; }
+
+ void readdObject(int itemId);
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+};
+
+class PoliceMaze : ScriptBase {
+ bool _isPaused;
+ bool _isActive;
+ bool _isEnding;
+ int _pm_var1;
+ int _pm_var2;
+
+public:
+ PoliceMazeTargetTrack *_tracks[kNumMazeTracks];
+
+public:
+ PoliceMaze(BladeRunnerEngine *vm);
+ ~PoliceMaze();
+
+ void tick();
+ void reset();
+ void clear(bool isLoadingGame);
+ void setPauseState(bool state);
+ void activate();
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/script/scene/ct07.cpp b/engines/bladerunner/script/scene/ct07.cpp
index 2eb7805c44..ebbe604b65 100644
--- a/engines/bladerunner/script/scene/ct07.cpp
+++ b/engines/bladerunner/script/scene/ct07.cpp
@@ -89,7 +89,7 @@ void SceneScriptCT07::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bo
void SceneScriptCT07::PlayerWalkedIn() {
Player_Gains_Control();
- Non_Player_Actor_Combat_Mode_On(kActorZuben, 0, 0, kActorMcCoy, 2, 4, 7, 8, 0, 0, 100, 15, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorZuben, kActorCombatStateIdle, false, kActorMcCoy, 2, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 15, 300, false);
Game_Flag_Set(516);
Actor_Face_Actor(kActorMcCoy, kActorZuben, true);
}
diff --git a/engines/bladerunner/script/scene/ct11.cpp b/engines/bladerunner/script/scene/ct11.cpp
index 63d114ebfb..49dd417ae1 100644
--- a/engines/bladerunner/script/scene/ct11.cpp
+++ b/engines/bladerunner/script/scene/ct11.cpp
@@ -54,7 +54,7 @@ void SceneScriptCT11::SceneLoaded() {
Unobstacle_Object("BOX SOUTH 1", true);
if (Global_Variable_Query(kVariableChapter) < 4) {
if (!Game_Flag_Query(645)) {
- Item_Add_To_World(115, 951, 33, 640.21002f, 30.0f, 470.0f, 512, 12, 12, false, true, false, true);
+ Item_Add_To_World(115, 951, 33, 640.21f, 30.0f, 470.0f, 512, 12, 12, false, true, false, true);
Scene_2D_Region_Add(0, 505, 316, 513, 321);
Game_Flag_Set(725);
}
@@ -99,15 +99,15 @@ bool SceneScriptCT11::ClickedOnItem(int itemId, bool a2) {
bool SceneScriptCT11::ClickedOnExit(int exitId) {
if (exitId == 0) {
- if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, 121.0f, 9.6800003f, -42.0f, 0, 1, false, 0)) {
+ if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, 121.0f, 9.68f, -42.0f, 0, 1, false, 0)) {
Game_Flag_Set(304);
Set_Enter(31, kSceneCT09);
}
return true;
}
if (exitId == 1) {
- if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, -300.0f, 9.6800003f, 66.0f, 0, 1, false, 0)) {
- Loop_Actor_Walk_To_XYZ(kActorMcCoy, -400.0f, 9.6800003f, -70.0f, 0, 1, false, 0);
+ if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, -300.0f, 9.68f, 66.0f, 0, 1, false, 0)) {
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, -400.0f, 9.68f, -70.0f, 0, 1, false, 0);
Game_Flag_Set(86);
Set_Enter(4, kSceneCT12);
}
diff --git a/engines/bladerunner/script/scene/ct12.cpp b/engines/bladerunner/script/scene/ct12.cpp
index 859b065b37..88bbd4645a 100644
--- a/engines/bladerunner/script/scene/ct12.cpp
+++ b/engines/bladerunner/script/scene/ct12.cpp
@@ -138,7 +138,7 @@ bool SceneScriptCT12::ClickedOnItem(int itemId, bool a2) {
bool SceneScriptCT12::ClickedOnExit(int exitId) {
if (exitId == 0) {
- if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, -419.14999f, -6.5f, 696.94f, 0, 1, false, 0)) {
+ if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, -419.15f, -6.5f, 696.94f, 0, 1, false, 0)) {
Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
Game_Flag_Set(88);
Set_Enter(4, kSceneCT01);
diff --git a/engines/bladerunner/script/scene/dr02.cpp b/engines/bladerunner/script/scene/dr02.cpp
index cbdb1ddcd7..c416fe2ff2 100644
--- a/engines/bladerunner/script/scene/dr02.cpp
+++ b/engines/bladerunner/script/scene/dr02.cpp
@@ -32,7 +32,7 @@ void SceneScriptDR02::InitializeScene() {
} else if (Game_Flag_Query(264)) {
Setup_Scene_Information(-1258.0f, 7.18f, -314.0f, 400);
} else {
- Setup_Scene_Information(168.78f, 0.16f, -775.71997f, 193);
+ Setup_Scene_Information(168.78f, 0.16f, -775.72f, 193);
}
Scene_Exit_Add_2D_Exit(0, 605, 0, 639, 479, 1);
Scene_Exit_Add_2D_Exit(1, 222, 176, 279, 314, 0);
diff --git a/engines/bladerunner/script/scene/dr04.cpp b/engines/bladerunner/script/scene/dr04.cpp
index 21933aaae7..fd7316536d 100644
--- a/engines/bladerunner/script/scene/dr04.cpp
+++ b/engines/bladerunner/script/scene/dr04.cpp
@@ -247,7 +247,7 @@ void SceneScriptDR04::PlayerWalkedIn() {
Loop_Actor_Walk_To_XYZ(kActorMcCoy, -851.0f, 71.64f, 647.0f, 0, 0, false, 0);
Actor_Face_Heading(kActorMcCoy, 0, false);
Loop_Actor_Travel_Stairs(kActorMcCoy, 7, 0, 0);
- Loop_Actor_Walk_To_XYZ(kActorMcCoy, -774.85f, 7.18f, 386.67001f, 0, 0, false, 0);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, -774.85f, 7.18f, 386.67f, 0, 0, false, 0);
Actor_Set_Immunity_To_Obstacles(kActorMcCoy, false);
Footstep_Sound_Override_Off();
}
diff --git a/engines/bladerunner/script/scene/dr06.cpp b/engines/bladerunner/script/scene/dr06.cpp
index ebc19bce41..393cdc3184 100644
--- a/engines/bladerunner/script/scene/dr06.cpp
+++ b/engines/bladerunner/script/scene/dr06.cpp
@@ -26,9 +26,9 @@ namespace BladeRunner {
void SceneScriptDR06::InitializeScene() {
if (Game_Flag_Query(230)) {
- Setup_Scene_Information(-733.57001f, 136.60001f, -968.64001f, 0);
+ Setup_Scene_Information(-733.57f, 136.6f, -968.64f, 0);
} else {
- Setup_Scene_Information(-707.57001f, 136.60001f, -1132.64f, 472);
+ Setup_Scene_Information(-707.57f, 136.6f, -1132.64f, 472);
}
Scene_Exit_Add_2D_Exit(0, 601, 11, 639, 479, 1);
if (Global_Variable_Query(kVariableChapter) > 3 && Game_Flag_Query(715)) {
diff --git a/engines/bladerunner/script/scene/hf01.cpp b/engines/bladerunner/script/scene/hf01.cpp
index ce36b91e31..d75c381f35 100644
--- a/engines/bladerunner/script/scene/hf01.cpp
+++ b/engines/bladerunner/script/scene/hf01.cpp
@@ -90,9 +90,9 @@ bool SceneScriptHF01::ClickedOn3DObject(const char *objectName, bool a2) {
bool SceneScriptHF01::ClickedOnActor(int actorId) {
int v1;
- if (Global_Variable_Query(45) == 2) {
+ if (Global_Variable_Query(kVariableAffectionTowards) == 2) {
v1 = kActorDektora;
- } else if (Global_Variable_Query(45) == 3) {
+ } else if (Global_Variable_Query(kVariableAffectionTowards) == 3) {
v1 = kActorLucy;
} else {
v1 = -1;
@@ -295,15 +295,15 @@ void SceneScriptHF01::PlayerWalkedIn() {
Actor_Set_At_XYZ(kActorOfficerLeary, 8.2f, 8.0f, -346.67f, 1021);
Actor_Put_In_Set(kActorOfficerGrayford, 37);
Actor_Set_At_XYZ(kActorOfficerGrayford, 51.21f, 8.0f, -540.78f, 796);
- Non_Player_Actor_Combat_Mode_On(kActorOfficerLeary, 3, 1, kActorMcCoy, 4, 4, 7, 8, 0, 0, 0, 100, 300, 0);
- Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, 3, 1, kActorMcCoy, 4, 4, 7, 8, 0, 0, 0, 100, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerLeary, kActorCombatStateUncover, true, kActorMcCoy, 4, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 0, 100, 300, false);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateUncover, true, kActorMcCoy, 4, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 0, 100, 300, false);
}
if (!Game_Flag_Query(165) && Actor_Query_Goal_Number(kActorCrazylegs) != 2) {
- if (Actor_Clue_Query(kActorMcCoy, kCluePhoneCallLucy1) && Global_Variable_Query(45) == 3 && Actor_Query_Goal_Number(kActorLucy) != 599) {
+ if (Actor_Clue_Query(kActorMcCoy, kCluePhoneCallLucy1) && Global_Variable_Query(kVariableAffectionTowards) == 3 && Actor_Query_Goal_Number(kActorLucy) != 599) {
Actor_Put_In_Set(kActorLucy, 37);
Actor_Set_At_XYZ(kActorLucy, -5.0f, 8.0f, -622.0f, 419);
Actor_Set_Targetable(kActorLucy, true);
- } else if (Actor_Clue_Query(kActorMcCoy, kCluePhoneCallDektora1) && Global_Variable_Query(45) == 2 && Actor_Query_Goal_Number(kActorDektora) != 599) {
+ } else if (Actor_Clue_Query(kActorMcCoy, kCluePhoneCallDektora1) && Global_Variable_Query(kVariableAffectionTowards) == 2 && Actor_Query_Goal_Number(kActorDektora) != 599) {
Actor_Put_In_Set(kActorDektora, 37);
Actor_Set_At_XYZ(kActorDektora, -5.0f, 8.0f, -622.0f, 419);
Actor_Set_Targetable(kActorDektora, true);
diff --git a/engines/bladerunner/script/scene/hf03.cpp b/engines/bladerunner/script/scene/hf03.cpp
index 09bf589bb7..e3b01df4f8 100644
--- a/engines/bladerunner/script/scene/hf03.cpp
+++ b/engines/bladerunner/script/scene/hf03.cpp
@@ -96,8 +96,8 @@ void SceneScriptHF03::sub_401C80() {
Actor_Says(kActorLucy, 210, 13);
Actor_Says(kActorMcCoy, 1655, 15);
Actor_Modify_Friendliness_To_Other(kActorLucy, kActorMcCoy, Random_Query(9, 10));
- if (Actor_Query_Friendliness_To_Other(kActorLucy, kActorMcCoy) > 59 && !Global_Variable_Query(45)) {
- Global_Variable_Set(45, 3);
+ if (Actor_Query_Friendliness_To_Other(kActorLucy, kActorMcCoy) > 59 && Global_Variable_Query(kVariableAffectionTowards) == 0) {
+ Global_Variable_Set(kVariableAffectionTowards, 3);
Actor_Says(kActorLucy, 940, 14);
Actor_Says(kActorMcCoy, 6780, 11);
Actor_Says(kActorLucy, 950, 12);
diff --git a/engines/bladerunner/script/scene/hf05.cpp b/engines/bladerunner/script/scene/hf05.cpp
index ff497ebbe8..c96f852973 100644
--- a/engines/bladerunner/script/scene/hf05.cpp
+++ b/engines/bladerunner/script/scene/hf05.cpp
@@ -114,7 +114,7 @@ bool SceneScriptHF05::ClickedOn3DObject(const char *objectName, bool a2) {
ADQ_Add(kActorVoiceOver, 940, -1);
Ambient_Sounds_Play_Sound(147, 50, 99, 0, 0);
Delay(1500);
- Loop_Actor_Walk_To_XYZ(kActorMcCoy, 181.53999f, 40.630001f, 388.09f, 0, 0, true, 0);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, 181.54f, 40.63f, 388.09f, 0, 0, true, 0);
Actor_Face_Heading(kActorMcCoy, 0, false);
Actor_Change_Animation_Mode(kActorMcCoy, 23);
Actor_Clue_Lose(kActorMcCoy, kClueBomb);
@@ -163,7 +163,7 @@ bool SceneScriptHF05::ClickedOnExit(int exitId) {
return true;
}
if (exitId == 2) {
- if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, 277.0f, 40.631f, 410.0f, 0, 1, false, 0) && !Game_Flag_Query(684)) {
+ if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, 277.0f, 40.63f, 410.0f, 0, 1, false, 0) && !Game_Flag_Query(684)) {
Game_Flag_Set(529);
Set_Enter(42, kSceneHF06);
}
@@ -483,10 +483,10 @@ void SceneScriptHF05::sub_403738() {
}
int SceneScriptHF05::sub_404858() {
- if (Global_Variable_Query(45) == 2 && Actor_Query_Goal_Number(kActorDektora) != 599) {
+ if (Global_Variable_Query(kVariableAffectionTowards) == 2 && Actor_Query_Goal_Number(kActorDektora) != 599) {
return kActorDektora;
}
- if (Global_Variable_Query(45) == 3 && Actor_Query_Goal_Number(kActorLucy) != 599) {
+ if (Global_Variable_Query(kVariableAffectionTowards) == 3 && Actor_Query_Goal_Number(kActorLucy) != 599) {
return kActorLucy;
}
return -1;
@@ -494,15 +494,15 @@ int SceneScriptHF05::sub_404858() {
void SceneScriptHF05::sub_4042E4() {
Actor_Force_Stop_Walking(kActorMcCoy);
- Actor_Put_In_Set(kActorOfficerLeary, 41);
- Actor_Set_At_XYZ(kActorOfficerLeary, 430.39999f, 40.630001f, -258.17999f, 300);
- Actor_Put_In_Set(kActorOfficerGrayford, 41);
- Actor_Set_At_XYZ(kActorOfficerGrayford, 526.40002f, 37.18f, -138.17999f, 300);
+ Actor_Put_In_Set(kActorOfficerLeary, kSetHF05);
+ Actor_Set_At_XYZ(kActorOfficerLeary, 430.4f, 40.63f, -258.18f, 300);
+ Actor_Put_In_Set(kActorOfficerGrayford, kSetHF05);
+ Actor_Set_At_XYZ(kActorOfficerGrayford, 526.4f, 37.18f, -138.18f, 300);
ADQ_Flush();
ADQ_Add(kActorOfficerGrayford, 260, -1);
Player_Loses_Control();
- Non_Player_Actor_Combat_Mode_On(kActorOfficerLeary, 3, 1, kActorMcCoy, 4, 4, 7, 8, 0, 0, 100, 100, 1200, 1);
- return Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, 3, 1, kActorMcCoy, 4, 4, 7, 8, 0, 0, 100, 100, 300, 1);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerLeary, kActorCombatStateUncover, true, kActorMcCoy, 4, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 100, 1200, true);
+ Non_Player_Actor_Combat_Mode_On(kActorOfficerGrayford, kActorCombatStateUncover, true, kActorMcCoy, 4, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 100, 300, true);
}
void SceneScriptHF05::sub_403F0C() {
diff --git a/engines/bladerunner/script/scene/hf06.cpp b/engines/bladerunner/script/scene/hf06.cpp
index 7a41c9eda2..49ea1d81d2 100644
--- a/engines/bladerunner/script/scene/hf06.cpp
+++ b/engines/bladerunner/script/scene/hf06.cpp
@@ -180,12 +180,13 @@ void SceneScriptHF06::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bo
void SceneScriptHF06::PlayerWalkedIn() {
if (Game_Flag_Query(662)) {
- int actorId;
- if (Global_Variable_Query(45) == 3 && Actor_Query_Goal_Number(kActorLucy) != 599) {
+ int actorId = -1;
+ if (Global_Variable_Query(kVariableAffectionTowards) == 3 && Actor_Query_Goal_Number(kActorLucy) != 599) {
actorId = kActorLucy;
- } else {
- actorId = Global_Variable_Query(45) == 2 && Actor_Query_Goal_Number(kActorDektora) != 599 ? kActorDektora : -1;
- }
+ } else if (Global_Variable_Query(kVariableAffectionTowards) == 2 && Actor_Query_Goal_Number(kActorDektora) != 599) {
+ actorId = kActorDektora;
+ }
+
if (actorId != -1) {
Actor_Put_In_Set(actorId, 42);
if (Game_Flag_Query(559)) {
@@ -267,7 +268,7 @@ void SceneScriptHF06::sub_401EF4() {
Sound_Play(562, 50, 0, 0, 50);
Game_Flag_Set(559);
Scene_Exits_Disable();
- Non_Player_Actor_Combat_Mode_On(kActorSteele, 3, 1, actorId, 15, 4, 7, 8, 0, 0, 100, 10, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorSteele, kActorCombatStateUncover, true, actorId, 15, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 10, 300, false);
}
void SceneScriptHF06::sub_4023E0() {
diff --git a/engines/bladerunner/script/scene/hf07.cpp b/engines/bladerunner/script/scene/hf07.cpp
index e9fe2f05fd..b653cfd08a 100644
--- a/engines/bladerunner/script/scene/hf07.cpp
+++ b/engines/bladerunner/script/scene/hf07.cpp
@@ -142,11 +142,11 @@ void SceneScriptHF07::DialogueQueueFlushed(int a1) {
}
int SceneScriptHF07::sub_401864() {
- if (Global_Variable_Query(45) == 2 && Actor_Query_Goal_Number(3) != 599) {
- return 3;
+ if (Global_Variable_Query(kVariableAffectionTowards) == 2 && Actor_Query_Goal_Number(3) != 599) {
+ return kActorDektora;
}
- if (Global_Variable_Query(45) == 3 && Actor_Query_Goal_Number(6) != 599) {
- return 6;
+ if (Global_Variable_Query(kVariableAffectionTowards) == 3 && Actor_Query_Goal_Number(6) != 599) {
+ return kActorLucy;
}
return -1;
}
diff --git a/engines/bladerunner/script/scene/kp05.cpp b/engines/bladerunner/script/scene/kp05.cpp
index 9b080aceb0..99fa6c33fa 100644
--- a/engines/bladerunner/script/scene/kp05.cpp
+++ b/engines/bladerunner/script/scene/kp05.cpp
@@ -158,7 +158,7 @@ void SceneScriptKP05::PlayerWalkedIn() {
Actor_Says(kActorMcCoy, 2220, 3);
Actor_Says(kActorSteele, 620, 15);
Actor_Says(kActorSteele, 630, 17);
- Non_Player_Actor_Combat_Mode_On(kActorSteele, 0, 1, kActorMcCoy, 9, 4, 7, 8, 0, -1, -1, 20, 240, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorSteele, kActorCombatStateIdle, true, kActorMcCoy, 9, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, -1, -1, 20, 240, false);
}
}
diff --git a/engines/bladerunner/script/scene/ma04.cpp b/engines/bladerunner/script/scene/ma04.cpp
index 5f1b41e998..ead9f1946d 100644
--- a/engines/bladerunner/script/scene/ma04.cpp
+++ b/engines/bladerunner/script/scene/ma04.cpp
@@ -176,9 +176,9 @@ bool SceneScriptMA04::ClickedOn2DRegion(int region) {
Overlay_Remove("MA04OVER");
Delay(500);
if (Game_Flag_Query(653)) {
- if (Global_Variable_Query(45) == 2) {
+ if (Global_Variable_Query(kVariableAffectionTowards) == 2) {
phoneCallWithDektora();
- } else if (Global_Variable_Query(45) == 3) {
+ } else if (Global_Variable_Query(kVariableAffectionTowards) == 3) {
phoneCallWithLucy();
} else {
phoneCallWithClovis();
diff --git a/engines/bladerunner/script/scene/nr01.cpp b/engines/bladerunner/script/scene/nr01.cpp
index 171cea52d8..fd7c9911d0 100644
--- a/engines/bladerunner/script/scene/nr01.cpp
+++ b/engines/bladerunner/script/scene/nr01.cpp
@@ -384,7 +384,7 @@ void SceneScriptNR01::PlayerWalkedIn() {
if (Actor_Query_Goal_Number(kActorGordo) == 230) {
Scene_Exits_Disable();
Actor_Set_Goal_Number(kActorGordo, 231);
- Non_Player_Actor_Combat_Mode_On(kActorGordo, 0, 1, kActorMcCoy, 3, 4, 7, 8, -1, -1, -1, 20, 300, 0);
+ Non_Player_Actor_Combat_Mode_On(kActorGordo, kActorCombatStateIdle, true, kActorMcCoy, 3, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, 20, 300, false);
}
} else if (Game_Flag_Query(545)) {
Game_Flag_Reset(545);
diff --git a/engines/bladerunner/script/scene/nr04.cpp b/engines/bladerunner/script/scene/nr04.cpp
index 18583f0d75..00aee0b4ad 100644
--- a/engines/bladerunner/script/scene/nr04.cpp
+++ b/engines/bladerunner/script/scene/nr04.cpp
@@ -187,7 +187,7 @@ void SceneScriptNR04::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bo
Delay(2500);
Actor_Says(kActorEarlyQ, 290, 3);
sub_401DB0();
- //return true;
+ //return true;
break;
case 213:
Actor_Clue_Acquire(kActorMcCoy, kClueDektorasDressingRoom, 0, kActorEarlyQ);
diff --git a/engines/bladerunner/script/scene/nr09.cpp b/engines/bladerunner/script/scene/nr09.cpp
index fd4faeccb0..7f786e17c8 100644
--- a/engines/bladerunner/script/scene/nr09.cpp
+++ b/engines/bladerunner/script/scene/nr09.cpp
@@ -107,7 +107,7 @@ void SceneScriptNR09::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bo
void SceneScriptNR09::PlayerWalkedIn() {
if (Game_Flag_Query(614)) {
- Loop_Actor_Walk_To_XYZ(kActorMcCoy, -704.07001f, 0.35f, 623.04f, 0, 0, false, 0);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, -704.07f, 0.35f, 623.04f, 0, 0, false, 0);
Game_Flag_Reset(614);
}
//return false;
diff --git a/engines/bladerunner/script/scene/nr11.cpp b/engines/bladerunner/script/scene/nr11.cpp
index 95ef4b7d84..5c4f4c141c 100644
--- a/engines/bladerunner/script/scene/nr11.cpp
+++ b/engines/bladerunner/script/scene/nr11.cpp
@@ -140,7 +140,7 @@ bool SceneScriptNR11::ClickedOn3DObject(const char *objectName, bool a2) {
} else {
Actor_Says(kActorMcCoy, 3840, 18);
Delay(1000);
- if (Actor_Query_Friendliness_To_Other(kActorDektora, kActorMcCoy) > 59 && !Global_Variable_Query(45)) {
+ if (Actor_Query_Friendliness_To_Other(kActorDektora, kActorMcCoy) > 59 && Global_Variable_Query(kVariableAffectionTowards) == 0) {
Music_Play(21, 35, 0, 3, -1, 0, 0);
}
Loop_Actor_Walk_To_XYZ(kActorDektora, -135.0f, 0.33f, -267.0f, 0, 0, false, 0);
@@ -164,8 +164,8 @@ bool SceneScriptNR11::ClickedOn3DObject(const char *objectName, bool a2) {
Actor_Says(kActorMcCoy, 3870, 3);
Actor_Says(kActorDektora, 1070, 14);
Actor_Modify_Friendliness_To_Other(kActorDektora, kActorMcCoy, 5);
- if (Actor_Query_Friendliness_To_Other(kActorDektora, kActorMcCoy) > 55 && !Global_Variable_Query(45)) {
- Global_Variable_Set(45, 2);
+ if (Actor_Query_Friendliness_To_Other(kActorDektora, kActorMcCoy) > 55 && Global_Variable_Query(kVariableAffectionTowards) == 0) {
+ Global_Variable_Set(kVariableAffectionTowards, 2);
Actor_Says(kActorDektora, 1130, 17);
Actor_Says(kActorMcCoy, 6365, 12);
Actor_Says(kActorDektora, 1140, 14);
diff --git a/engines/bladerunner/script/scene/ps10.cpp b/engines/bladerunner/script/scene/ps10.cpp
index d45a4b8e67..3957ee1c7d 100644
--- a/engines/bladerunner/script/scene/ps10.cpp
+++ b/engines/bladerunner/script/scene/ps10.cpp
@@ -24,8 +24,301 @@
namespace BladeRunner {
+enum PoliceMazePS10Tracks {
+ kPoliceMazePS10Track1 = 0,
+ kPoliceMazePS10Track2 = 1,
+ kPoliceMazePS10Track3 = 2,
+ kPoliceMazePS10Track4 = 3,
+ kPoliceMazePS10Track5 = 4,
+ kPoliceMazePS10Track6 = 5,
+ kPoliceMazePS10Track7 = 6,
+ kPoliceMazePS10Track8 = 7,
+ kPoliceMazePS10Track9 = 8
+};
+
+static int kPoliceMazePS10TargetCount = 20;
+
+static const int *getPoliceMazePS10TrackData1() {
+ static int trackData[] = {
+ kPMTIActivate, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIVariableInc, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIObstacleReset, kItemPoliceMazeTarget1,
+ kPMTIObstacleReset, kItemPoliceMazeTarget2,
+ kPMTIFacing, 989,
+ kPMTIPosition, 0,
+ kPMTITargetSet, kItemPoliceMazeTarget1, 1,
+ kPMTITargetSet, kItemPoliceMazeTarget2, 1,
+ kPMTIEnemyReset, kItemPoliceMazeTarget1,
+ kPMTIWaitRandom, 3000, 5000,
+ kPMTIObstacleSet, kItemPoliceMazeTarget1,
+ kPMTIPlaySound, 159, 100,
+ kPMTIMove, 14,
+ kPMTIWait, 1000,
+ kPMTIRotate, 740, 80,
+ kPMTIEnemySet, kItemPoliceMazeTarget1,
+ kPMTIWait, 0,
+ kPMTIRotate, 488, 80,
+ kPMTIWait, 1000,
+ kPMTIShoot, 27, 33,
+ kPMTIWait, 0,
+ kPMTIRotate, 740, 80,
+ kPMTIPausedReset, kPoliceMazePS10Track2,
+ kPMTIObstacleReset, kItemPoliceMazeTarget1,
+ kPMTIObstacleSet, kItemPoliceMazeTarget2,
+ kPMTIPausedSet, kPoliceMazePS10Track1,
+ kPMTIPosition, 0,
+ kPMTIRestart
+ };
+
+ return trackData;
+}
+
+static const int *getPoliceMazePS10TrackData2() {
+ static int trackData[] = {
+ kPMTIFacing, 740,
+ kPMTIPosition, 0,
+ kPMTIEnemySet, kItemPoliceMazeTarget2,
+ kPMTIMove, 69,
+ kPMTIWait, 500,
+ kPMTIObstacleReset, kItemPoliceMazeTarget2,
+ kPMTIPausedReset, kPoliceMazePS10Track5,
+ kPMTIPausedSet, kPoliceMazePS10Track2,
+ kPMTIPosition, 0,
+ kPMTIRestart
+ };
+ return trackData;
+}
+
+static const int *getPoliceMazePS10TrackData3() {
+ static int trackData[] = {
+ kPMTIActivate, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIVariableInc, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIObstacleReset, kItemPoliceMazeTarget3,
+ kPMTIFacing, 993,
+ kPMTIPosition, 0,
+ kPMTIWaitRandom, 3000, 5000,
+ kPMTIObstacleSet, kItemPoliceMazeTarget3,
+ kPMTIPlaySound, 159, 100,
+ kPMTITargetSet, kItemPoliceMazeTarget3, 1,
+ kPMTIEnemyReset, kItemPoliceMazeTarget3,
+ kPMTIMove, 5,
+ kPMTIWait, 1000,
+ kPMTIEnemySet, kItemPoliceMazeTarget3,
+ kPMTIRotate, 233, 80,
+ kPMTIWait, 0,
+ kPMTIRotate, 491, 80,
+ kPMTIWait, 500,
+ kPMTIShoot, 27, 33,
+ kPMTIWait, 500,
+ kPMTIRotate, 233, 80,
+ kPMTIWait, 0,
+ kPMTIRotate, 993, 80,
+ kPMTIPlaySound, 34, 33,
+ kPMTIMove, 0,
+ kPMTIObstacleReset, kItemPoliceMazeTarget3,
+ kPMTIRestart
+ };
+ return trackData;
+}
+
+static const int *getPoliceMazePS10TrackData4() {
+ static int trackData[] = {
+ kPMTIActivate, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIVariableInc, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIObstacleReset, kItemPoliceMazeTarget4,
+ kPMTIFacing, 993,
+ kPMTIPosition, 0,
+ kPMTIWaitRandom, 3000, 6000,
+ kPMTIObstacleSet, kItemPoliceMazeTarget4,
+ kPMTIPlaySound, 159, 100,
+ kPMTITargetSet, kItemPoliceMazeTarget4, 1,
+ kPMTIEnemyReset, kItemPoliceMazeTarget4,
+ kPMTIMove, 34,
+ kPMTIWait, 500,
+ kPMTIRotate, 491, 80,
+ kPMTIMove, 0,
+ kPMTILeave,
+ kPMTIObstacleReset, kItemPoliceMazeTarget4,
+ kPMTIPausedReset, kPoliceMazePS10Track8,
+ kPMTIPausedSet, kPoliceMazePS10Track4,
+ kPMTIRestart
+ };
+ return trackData;
+}
+
+static const int *getPoliceMazePS10TrackData5() {
+ static int trackData[] = {
+ kPMTIActivate, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIVariableInc, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIObstacleReset, kItemPoliceMazeTarget5,
+ kPMTIFacing, 0,
+ kPMTIPosition, 0,
+ kPMTIWaitRandom, 4000, 6000,
+ kPMTIObstacleSet, kItemPoliceMazeTarget5,
+ kPMTIPlaySound, 159, 100,
+ kPMTITargetSet, kItemPoliceMazeTarget5, 1,
+ kPMTIEnemyReset, kItemPoliceMazeTarget5,
+ kPMTIMove, 5,
+ kPMTIWait, 1000,
+ kPMTIRotate, 512, 100,
+ kPMTIWait, 2000,
+ kPMTIRotate, 0, -100,
+ kPMTIPlaySound, 34, 33,
+ kPMTIMove, 0,
+ kPMTILeave,
+ kPMTIObstacleReset, kItemPoliceMazeTarget5,
+ kPMTIPausedReset, kPoliceMazePS10Track1,
+ kPMTIPausedSet, kPoliceMazePS10Track5,
+ kPMTIRestart
+ };
+ return trackData;
+}
+
+static const int *getPoliceMazePS10TrackData6() {
+ static int trackData[] = {
+ kPMTIActivate, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIVariableInc, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIObstacleReset, kItemPoliceMazeTarget6,
+ kPMTIFacing, 999,
+ kPMTIPosition, 0,
+ kPMTIWaitRandom, 4000, 6000,
+ kPMTIObstacleSet, kItemPoliceMazeTarget6,
+ kPMTIPlaySound, 159, 100,
+ kPMTITargetSet, kItemPoliceMazeTarget6, 1,
+ kPMTIEnemyReset, kItemPoliceMazeTarget6,
+ kPMTIMove, 7,
+ kPMTIWait, 500,
+ kPMTIEnemySet, kItemPoliceMazeTarget6,
+ kPMTIRotate, 750, 80,
+ kPMTIWait, 0,
+ kPMTIRotate, 500, 80,
+ kPMTIWait, 1000,
+ kPMTIShoot, 27, 33,
+ kPMTIWait, 0,
+ kPMTIRotate, 750, 80,
+ kPMTIWait, 0,
+ kPMTIRotate, 999, 80,
+ kPMTIPlaySound, 34, 33,
+ kPMTIMove, 0,
+ kPMTIObstacleReset, kItemPoliceMazeTarget6,
+ kPMTIPausedReset, kPoliceMazePS10Track7,
+ kPMTIPausedReset, kPoliceMazePS10Track9,
+ kPMTIPausedSet, kPoliceMazePS10Track6,
+ kPMTIRestart
+ };
+ return trackData;
+}
+
+static const int *getPoliceMazePS10TrackData7() {
+ static int trackData[] = {
+ kPMTIActivate, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIVariableInc, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIObstacleReset, kItemPoliceMazeTarget7,
+ kPMTIFacing, 264,
+ kPMTIPosition, 0,
+ kPMTIWaitRandom, 3000, 6000,
+ kPMTITargetSet, kItemPoliceMazeTarget7, 1,
+ kPMTIEnemyReset, kItemPoliceMazeTarget7,
+ kPMTIObstacleSet, kItemPoliceMazeTarget7,
+ kPMTIMove, 89,
+ kPMTIWaitRandom, 4000, 8000,
+ kPMTIFacing, 776,
+ kPMTIMove, 0,
+ kPMTILeave,
+ kPMTIObstacleReset, kItemPoliceMazeTarget7,
+ kPMTIPausedSet, kPoliceMazePS10Track7,
+ kPMTIRestart
+ };
+ return trackData;
+}
+
+static const int *getPoliceMazePS10TrackData8() {
+ static int trackData[] = {
+ kPMTIActivate, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIVariableInc, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIObstacleReset, kItemPoliceMazeTarget8,
+ kPMTIFacing, 993,
+ kPMTIPosition, 0,
+ kPMTIWaitRandom, 4000, 6000,
+ kPMTIObstacleSet, kItemPoliceMazeTarget8,
+ kPMTIPlaySound, 159, 100,
+ kPMTITargetSet, kItemPoliceMazeTarget8, 1,
+ kPMTIEnemyReset, kItemPoliceMazeTarget8,
+ kPMTIMove, 34,
+ kPMTIWait, 500,
+ kPMTIEnemySet, kItemPoliceMazeTarget8,
+ kPMTIRotate, 491, 80,
+ kPMTIMove, 20,
+ kPMTIWait, 0,
+ kPMTIShoot, 27, 33,
+ kPMTIMove, 0,
+ kPMTIObstacleReset, kItemPoliceMazeTarget8,
+ kPMTIPausedReset, kPoliceMazePS10Track4,
+ kPMTIPausedSet, kPoliceMazePS10Track8,
+ kPMTIRestart
+ };
+ return trackData;
+}
+
+static const int *getPoliceMazePS10TrackData9() {
+ static int trackData[] = {
+ kPMTIActivate, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIVariableInc, kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount,
+ kPMTIObstacleReset, kItemPoliceMazeTarget9,
+ kPMTIFacing, 738,
+ kPMTIPosition, 0,
+ kPMTIWaitRandom, 2000, 5000,
+ kPMTITargetSet, kItemPoliceMazeTarget9, 1,
+ kPMTIEnemySet, kItemPoliceMazeTarget9,
+ kPMTIObstacleSet, kItemPoliceMazeTarget9,
+ kPMTIPlaySound, 0, 33,
+ kPMTIMove, 23,
+ kPMTIPlaySound, 0, 33,
+ kPMTIWait, 200,
+ kPMTIPlaySound, 32, 33,
+ kPMTIRotate, 498, 100,
+ kPMTIPlaySound, 0, 33,
+ kPMTIWait, 100,
+ kPMTIShoot, 27, 33,
+ kPMTIPlaySound, 32, 33,
+ kPMTIMove, 35,
+ kPMTIPlaySound, 32, 33,
+ kPMTIWait, 100,
+ kPMTIShoot, 27, 33,
+ kPMTIPlaySound, 0, 33,
+ kPMTIMove, 23,
+ kPMTIPlaySound, 32, 33,
+ kPMTIWait, 100,
+ kPMTIShoot, 27, 33,
+ kPMTIPlaySound, 32, 33,
+ kPMTIRotate, 758, 100,
+ kPMTIPlaySound, 32, 33,
+ kPMTIMove, 89,
+ kPMTIPlaySound, 0, 33,
+ kPMTIWaitRandom, 4000, 6000,
+ kPMTITargetSet, kItemPoliceMazeTarget9, 1,
+ kPMTIEnemySet, kItemPoliceMazeTarget9,
+ kPMTIFacing, 216,
+ kPMTIPlaySound, 32, 33,
+ kPMTIMove, 69,
+ kPMTIWait, 100,
+ kPMTIPlaySound, 32, 33,
+ kPMTIRotate, 498, 100,
+ kPMTIWait, 100,
+ kPMTIShoot, 27, 33,
+ kPMTIPlaySound, 0, 33,
+ kPMTIRotate, 216, 100,
+ kPMTIPlaySound, 32, 33,
+ kPMTIMove, 0,
+ kPMTIObstacleReset, kItemPoliceMazeTarget9,
+ kPMTIPausedSet, kPoliceMazePS10Track9,
+ kPMTIRestart
+ };
+ return trackData;
+}
+
void SceneScriptPS10::InitializeScene() {
- Police_Maze_Set_Pause_State(1);
+ Police_Maze_Set_Pause_State(true);
if (Game_Flag_Query(15)) {
float x = World_Waypoint_Query_X(4);
float y = World_Waypoint_Query_Y(4);
@@ -38,30 +331,20 @@ void SceneScriptPS10::InitializeScene() {
Ambient_Sounds_Remove_All_Non_Looping_Sounds(0);
Ambient_Sounds_Add_Looping_Sound(387, 50, 1, 1);
Ambient_Sounds_Add_Looping_Sound(54, 50, 1, 1);
- Ambient_Sounds_Add_Sound(1, 10, 50, 16, 25, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(389, 5, 50, 16, 25, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(390, 6, 50, 16, 25, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(443, 2, 100, 14, 16, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(444, 2, 100, 14, 16, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(445, 2, 100, 14, 16, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(446, 2, 100, 14, 16, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(303, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(304, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(305, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(306, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(307, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
- Ambient_Sounds_Add_Sound(308, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
-}
-
-static int track_data_0[] = {-26, 10, 20, -18, 10, 20, -9, 0, -9, 1,-5, 989, -1, 0, -15, 0, 1, -15, 1, 1,-23, 0, -7, 3000, 5000, -8, 0, -10, 159, 100,-2, 14, -3, 1000, -6, 740, 80, -22, 0, -3,0, -6, 488, 80, -3, 1000, -24, 27, 33, -3, 0, -6, 740, 80, -11, 1, -9, 0, -8, 1, -12, 0, -1, 0, -4};
-static int track_data_1[] = {-5, 740, -1, 0, -22, 1, -2, 69, -3, 500, -9, 1, -11, 4, -12, 1, -1, 0, -4};
-static int track_data_2[] = {-26, 10, 20, -18, 10, 20, -9, 2, -5, 993, -1, 0, -7, 3000, 5000, -8, 2, -10, 159, 100, -15, 2, 1, -23, 2, -2, 5, -3, 1000, -22, 2, -6, 233, 80, -3, 0, -6, 491, 80, -3, 500, -24, 27, 33, -3, 500, -6, 233, 80, -3, 0, -6, 993, 80, -10, 34, 33, -2, 0, -9, 2, -4};
-static int track_data_3[] = {-26, 10, 20, -18, 10, 20, -9, 3, -5, 993, -1, 0, -7, 3000, 6000, -8, 3, -10, 159, 100, -15, 3, 1, -23, 3, -2, 34, -3, 500, -6, 491, 80, -2, 0, -25, -9, 3, -11, 7, -12, 3, -4};
-static int track_data_4[] = {-26, 10, 20, -18, 10, 20, -9, 4, -5, 0, -1, 0, -7, 4000, 6000, -8, 4, -10, 159, 100, -15, 4, 1, -23, 4, -2, 5, -3, 1000, -6, 512, 100, -3, 2000, -6, 0, -100, -10, 34, 33, -2, 0, -25, -9, 4, -11, 0, -12, 4, -4};
-static int track_data_5[] = {-26, 10, 20, -18, 10, 20, -9, 5, -5, 999, -1, 0, -7, 4000, 6000, -8, 5, -10, 159, 100, -15, 5, 1, -23, 5, -2, 7, -3, 500, -22, 5, -6, 750, 80, -3, 0, -6, 500, 80, -3, 1000, -24, 27, 33, -3, 0, -6, 750, 80, -3, 0, -6, 999, 80, -10, 34, 33, -2, 0, -9, 5, -11, 6, -11, 8, -12, 5, -4};
-static int track_data_6[] = {-26, 10, 20, -18, 10, 20, -9, 6, -5, 264, -1, 0, -7, 3000, 6000, -15, 6, 1, -23, 6, -8, 6, -2, 89, -7, 4000, 8000, -5, 776, -2, 0, -25, -9, 6, -12, 6, -4};
-static int track_data_7[] = {-26, 10, 20, -18, 10, 20, -9, 7, -5, 993, -1, 0, -7, 4000, 6000, -8, 7, -10, 159, 100, -15, 7, 1, -23, 7, -2, 34, -3, 500, -22, 7, -6, 491, 80, -2, 20, -3, 0, -24, 27, 33, -2, 0, -9, 7, -11, 3, -12, 7, -4};
-static int track_data_8[] = {-26, 10, 20, -18, 10, 20, -9, 8, -5, 738, -1, 0, -7, 2000, 5000, -15, 8, 1, -22, 8, -8, 8, -10, 0, 33, -2, 23, -10, 0, 33, -3, 200, -10, 32, 33, -6, 498, 100, -10, 0, 33, -3, 100, -24, 27, 33, -10, 32, 33, -2, 35, -10, 32, 33, -3, 100, -24, 27, 33, -10, 0, 33, -2, 23, -10, 32, 33, -3, 100, -24, 27, 33, -10, 32, 33, -6, 758, 100, -10, 32, 33, -2, 89, -10, 0, 33, -7, 4000, 6000, -15, 8, 1, -22, 8, -5, 216, -10, 32, 33, -2, 69, -3, 100, -10, 32, 33, -6, 498, 100, -3, 100, -24, 27, 33, -10, 0, 33, -6, 216, 100, -10, 32, 33, -2, 0, -9, 8, -12, 8, -4};
+ Ambient_Sounds_Add_Sound( 1, 10, 50, 16, 25, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(389, 5, 50, 16, 25, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(390, 6, 50, 16, 25, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(443, 2, 100, 14, 16, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(444, 2, 100, 14, 16, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(445, 2, 100, 14, 16, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(446, 2, 100, 14, 16, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(303, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(304, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(305, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(306, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(307, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
+ Ambient_Sounds_Add_Sound(308, 5, 100, 17, 27, -100, 100, -101, -101, 0, 0);
+}
void SceneScriptPS10::SceneLoaded() {
Obstacle_Object("PARKMETR01", true);
@@ -85,26 +368,26 @@ void SceneScriptPS10::SceneLoaded() {
Unclickable_Object("PARKMETR16");
Unobstacle_Object("E.SM.WIRE01", true);
if (!Query_System_Currently_Loading_Game()) {
- Item_Add_To_World(0, 443, 14, -240.0f, -80.74f, 145.0f, 989, 72, 36, true, false, false, true);
- Item_Add_To_World(1, 443, 14, -240.0f, -8.74f, 145.0f, 740, 72, 36, true, false, false, true);
- Item_Add_To_World(2, 445, 14, -165.0f, 111.53f, -10.0f, 993, 72, 36, true, false, false, true);
- Item_Add_To_World(3, 447, 14, -125.0f, 160.0f, -10.0f, 993, 72, 36, true, false, false, true);
- Item_Add_To_World(4, 441, 14, -246.71f, 205.51f, -20.0f, 0, 72, 36, true, false, false, true);
- Item_Add_To_World(5, 445, 14, -27.69f, -86.92f, 434.0f, 999, 72, 36, true, false, false, true);
- Item_Add_To_World(6, 441, 14, -347.15f, 7.68f, -20.0f, 264, 72, 36, true, false, false, true);
- Item_Add_To_World(7, 449, 14, -51.0f, 160.0f, -10.0f, 993, 72, 36, true, false, false, true);
- Item_Add_To_World(8, 445, 14, 39.0f, 9.16f, -20.0f, 738, 72, 36, true, false, false, true);
+ Item_Add_To_World(kItemPoliceMazeTarget1, 443, 14, -240.0f, -80.74f, 145.0f, 989, 72, 36, true, false, false, true);
+ Item_Add_To_World(kItemPoliceMazeTarget2, 443, 14, -240.0f, -8.74f, 145.0f, 740, 72, 36, true, false, false, true);
+ Item_Add_To_World(kItemPoliceMazeTarget3, 445, 14, -165.0f, 111.53f, -10.0f, 993, 72, 36, true, false, false, true);
+ Item_Add_To_World(kItemPoliceMazeTarget4, 447, 14, -125.0f, 160.0f, -10.0f, 993, 72, 36, true, false, false, true);
+ Item_Add_To_World(kItemPoliceMazeTarget5, 441, 14, -246.71f, 205.51f, -20.0f, 0, 72, 36, true, false, false, true);
+ Item_Add_To_World(kItemPoliceMazeTarget6, 445, 14, -27.69f, -86.92f, 434.0f, 999, 72, 36, true, false, false, true);
+ Item_Add_To_World(kItemPoliceMazeTarget7, 441, 14, -347.15f, 7.68f, -20.0f, 264, 72, 36, true, false, false, true);
+ Item_Add_To_World(kItemPoliceMazeTarget8, 449, 14, -51.0f, 160.0f, -10.0f, 993, 72, 36, true, false, false, true);
+ Item_Add_To_World(kItemPoliceMazeTarget9, 445, 14, 39.0f, 9.16f, -20.0f, 738, 72, 36, true, false, false, true);
}
- Police_Maze_Target_Track_Add(0, -240.0f, -80.74f, 145.0f, -240.0f, -8.74f, 145.0f, 15, track_data_0, false);
- Police_Maze_Target_Track_Add(1, -240.0f, -8.74f, 145.0f, -450.0f, -8.74f, 145.0f, 70, track_data_1, false);
- Police_Maze_Target_Track_Add(2, -165.0f, 111.53f, -10.0f, -165.0f, 167.53f, -10.0f, 6, track_data_2, true);
- Police_Maze_Target_Track_Add(3, -125.0f, 160.0f, -10.0f, -51.0f, 160.0f, -10.0f, 35, track_data_3, false);
- Police_Maze_Target_Track_Add(4, -246.71f, 205.51f, -20.0f, -246.71f, 241.51f, -20.0f, 6, track_data_4, true);
- Police_Maze_Target_Track_Add(5, -27.69f, -86.92f, 434.0f, -27.69f, -18.92f, 434.0f, 8, track_data_5, true);
- Police_Maze_Target_Track_Add(6, -347.15f, 7.68f, -20.0f, 39.0f, 9.16f, -20.0f, 90, track_data_6, false);
- Police_Maze_Target_Track_Add(7, -51.0f, 160.0f, -10.0f, -125.0f, 160.0f, -10.0f, 35, track_data_7, true);
- Police_Maze_Target_Track_Add(8, 39.0f, 9.16f, -20.0f, -347.15f, 7.68f, -20.0f, 90, track_data_8, false);
+ Police_Maze_Target_Track_Add(kItemPoliceMazeTarget1, -240.0f, -80.74f, 145.0f, -240.0f, -8.74f, 145.0f, 15, getPoliceMazePS10TrackData1(), false);
+ Police_Maze_Target_Track_Add(kItemPoliceMazeTarget2, -240.0f, -8.74f, 145.0f, -450.0f, -8.74f, 145.0f, 70, getPoliceMazePS10TrackData2(), false);
+ Police_Maze_Target_Track_Add(kItemPoliceMazeTarget3, -165.0f, 111.53f, -10.0f, -165.0f, 167.53f, -10.0f, 6, getPoliceMazePS10TrackData3(), true);
+ Police_Maze_Target_Track_Add(kItemPoliceMazeTarget4, -125.0f, 160.0f, -10.0f, -51.0f, 160.0f, -10.0f, 35, getPoliceMazePS10TrackData4(), false);
+ Police_Maze_Target_Track_Add(kItemPoliceMazeTarget5, -246.71f, 205.51f, -20.0f, -246.71f, 241.51f, -20.0f, 6, getPoliceMazePS10TrackData5(), true);
+ Police_Maze_Target_Track_Add(kItemPoliceMazeTarget6, -27.69f, -86.92f, 434.0f, -27.69f, -18.92f, 434.0f, 8, getPoliceMazePS10TrackData6(), true);
+ Police_Maze_Target_Track_Add(kItemPoliceMazeTarget7, -347.15f, 7.68f, -20.0f, 39.0f, 9.16f, -20.0f, 90, getPoliceMazePS10TrackData7(), false);
+ Police_Maze_Target_Track_Add(kItemPoliceMazeTarget8, -51.0f, 160.0f, -10.0f, -125.0f, 160.0f, -10.0f, 35, getPoliceMazePS10TrackData8(), true);
+ Police_Maze_Target_Track_Add(kItemPoliceMazeTarget9, 39.0f, 9.16f, -20.0f, -347.15f, 7.68f, -20.0f, 90, getPoliceMazePS10TrackData9(), false);
Preload(441);
Preload(442);
Preload(443);
@@ -132,13 +415,13 @@ bool SceneScriptPS10::ClickedOnActor(int actorId) {
bool SceneScriptPS10::ClickedOnItem(int itemId, bool a2) {
if (Player_Query_Combat_Mode()) {
switch (itemId) {
- case 3:
+ case kItemPoliceMazeTarget4:
Sound_Play(4, 50, 0, 0, 50);
break;
- case 4:
+ case kItemPoliceMazeTarget5:
Sound_Play(555, 50, 0, 0, 50);
break;
- case 6:
+ case kItemPoliceMazeTarget7:
Sound_Play(555, 50, 0, 0, 50);
break;
default:
@@ -146,34 +429,34 @@ bool SceneScriptPS10::ClickedOnItem(int itemId, bool a2) {
break;
}
Item_Spin_In_World(itemId);
- if (itemId == 0) {
- Item_Flag_As_Non_Target(0);
- Item_Flag_As_Non_Target(1);
+ if (itemId == kItemPoliceMazeTarget1) {
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget1);
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget2);
}
- if (itemId == 1) {
- Item_Flag_As_Non_Target(0);
- Item_Flag_As_Non_Target(1);
+ if (itemId == kItemPoliceMazeTarget2) {
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget1);
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget2);
}
- if (itemId == 2) {
- Item_Flag_As_Non_Target(2);
+ if (itemId == kItemPoliceMazeTarget3) {
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget3);
}
- if (itemId == 3) {
- Item_Flag_As_Non_Target(3);
+ if (itemId == kItemPoliceMazeTarget4) {
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget4);
}
- if (itemId == 4) {
- Item_Flag_As_Non_Target(4);
+ if (itemId == kItemPoliceMazeTarget5) {
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget5);
}
- if (itemId == 5) {
- Item_Flag_As_Non_Target(5);
+ if (itemId == kItemPoliceMazeTarget6) {
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget6);
}
- if (itemId == 6) {
- Item_Flag_As_Non_Target(6);
+ if (itemId == kItemPoliceMazeTarget7) {
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget7);
}
- if (itemId == 7) {
- Item_Flag_As_Non_Target(7);
+ if (itemId == kItemPoliceMazeTarget8) {
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget8);
}
- if (itemId == 8) {
- Item_Flag_As_Non_Target(8);
+ if (itemId == kItemPoliceMazeTarget9) {
+ Item_Flag_As_Non_Target(kItemPoliceMazeTarget9);
} else {
Item_Flag_As_Non_Target(itemId);
}
@@ -185,12 +468,12 @@ bool SceneScriptPS10::ClickedOnItem(int itemId, bool a2) {
bool SceneScriptPS10::ClickedOnExit(int exitId) {
if (exitId == 1) {
- if (!Loop_Actor_Walk_To_Waypoint(kActorMcCoy, 6, 12, 1, false)) {
+ if (!Loop_Actor_Walk_To_Waypoint(kActorMcCoy, 6, 12, true, false)) {
Game_Flag_Set(14);
- sub_402238();
- Global_Variable_Decrement(9, 20 - Global_Variable_Query(10));
- Global_Variable_Set(10, 20);
- Set_Enter(14, kScenePS11);
+ removeTargets();
+ Global_Variable_Decrement(kVariablePoliceMazeScore, kPoliceMazePS10TargetCount - Global_Variable_Query(kVariablePoliceMazePS10TargetCounter));
+ Global_Variable_Set(kVariablePoliceMazePS10TargetCounter, kPoliceMazePS10TargetCount);
+ Set_Enter(kSetPS10_PS11_PS12_PS13, kScenePS11);
}
return true;
}
@@ -210,18 +493,18 @@ void SceneScriptPS10::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bo
void SceneScriptPS10::PlayerWalkedIn() {
if (Game_Flag_Query(15)) {
- Loop_Actor_Walk_To_XYZ(kActorMcCoy, -352.09f, -9.23f, 267.95f, 0, 0, true, 0);
- Police_Maze_Set_Pause_State(0);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, -352.09f, -9.23f, 267.95f, 0, false, true, 0);
+ Police_Maze_Set_Pause_State(false);
Game_Flag_Reset(15);
//return true;
return;
} else {
Player_Set_Combat_Mode(true);
- Loop_Actor_Walk_To_Waypoint(kActorMcCoy, 5, 0, 0, true);
- Actor_Says(kActorAnsweringMachine, 280, 3);
- Actor_Says(kActorAnsweringMachine, 290, 3);
- Actor_Says(kActorAnsweringMachine, 300, 3);
- Police_Maze_Set_Pause_State(0);
+ Loop_Actor_Walk_To_Waypoint(kActorMcCoy, 5, 0, false, true);
+ Actor_Says(kActorAnsweringMachine, 280, kAnimationModeTalk);
+ Actor_Says(kActorAnsweringMachine, 290, kAnimationModeTalk);
+ Actor_Says(kActorAnsweringMachine, 300, kAnimationModeTalk);
+ Police_Maze_Set_Pause_State(false);
//return true;
return;
}
@@ -233,16 +516,16 @@ void SceneScriptPS10::PlayerWalkedOut() {
void SceneScriptPS10::DialogueQueueFlushed(int a1) {
}
-void SceneScriptPS10::sub_402238() {
- Item_Remove_From_World(0);
- Item_Remove_From_World(1);
- Item_Remove_From_World(2);
- Item_Remove_From_World(3);
- Item_Remove_From_World(4);
- Item_Remove_From_World(5);
- Item_Remove_From_World(6);
- Item_Remove_From_World(7);
- Item_Remove_From_World(8);
+void SceneScriptPS10::removeTargets() {
+ Item_Remove_From_World(kItemPoliceMazeTarget1);
+ Item_Remove_From_World(kItemPoliceMazeTarget2);
+ Item_Remove_From_World(kItemPoliceMazeTarget3);
+ Item_Remove_From_World(kItemPoliceMazeTarget4);
+ Item_Remove_From_World(kItemPoliceMazeTarget5);
+ Item_Remove_From_World(kItemPoliceMazeTarget6);
+ Item_Remove_From_World(kItemPoliceMazeTarget7);
+ Item_Remove_From_World(kItemPoliceMazeTarget8);
+ Item_Remove_From_World(kItemPoliceMazeTarget9);
}
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/scene/ps11.cpp b/engines/bladerunner/script/scene/ps11.cpp
index 1aa227b022..e6311b3ca1 100644
--- a/engines/bladerunner/script/scene/ps11.cpp
+++ b/engines/bladerunner/script/scene/ps11.cpp
@@ -254,7 +254,7 @@ void SceneScriptPS11::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bo
}
void SceneScriptPS11::PlayerWalkedIn() {
- Police_Maze_Set_Pause_State(0);
+ Police_Maze_Set_Pause_State(false);
}
void SceneScriptPS11::PlayerWalkedOut() {
diff --git a/engines/bladerunner/script/scene/ps12.cpp b/engines/bladerunner/script/scene/ps12.cpp
index 7db642891e..d4d771a94f 100644
--- a/engines/bladerunner/script/scene/ps12.cpp
+++ b/engines/bladerunner/script/scene/ps12.cpp
@@ -25,7 +25,7 @@
namespace BladeRunner {
void SceneScriptPS12::InitializeScene() {
- Police_Maze_Set_Pause_State(1);
+ Police_Maze_Set_Pause_State(true);
if (Game_Flag_Query(16)) {
Scene_Loop_Start_Special(0, 0, 0);
Scene_Loop_Set_Default(1);
@@ -96,9 +96,9 @@ void SceneScriptPS12::SceneLoaded() {
}
Police_Maze_Target_Track_Add(29, -691.8f, -9.06f, 587.67f, -649.11f, -9.06f, 587.71f, 6, track_data_29, true);
Police_Maze_Target_Track_Add(30, -679.6f, -45.4f, 721.05f, -679.6f, -1.4f, 721.05f, 6, track_data_30, true);
- Police_Maze_Target_Track_Add(31, -414.04f, -8.98f, 711.917f, -459.54f, -8.99f, 707.81f, 6, track_data_31, false);
+ Police_Maze_Target_Track_Add(31, -414.04f, -8.98f, 711.91f, -459.54f, -8.99f, 707.81f, 6, track_data_31, false);
Police_Maze_Target_Track_Add(32, -440.0f, -8.97f, 1137.0f, -430.0f, -8.97f, 921.0f, 6, track_data_32, false);
- Police_Maze_Target_Track_Add(33, -764.92f, -0.84f, 950.21997f, -722.92f, -0.84f, 950.22f, 6, track_data_33, false);
+ Police_Maze_Target_Track_Add(33, -764.92f, -0.84f, 950.22f, -722.92f, -0.84f, 950.22f, 6, track_data_33, false);
Police_Maze_Target_Track_Add(34, -696.0f, -5.7f, 1185.0f, -635.0f, -5.7f, 1185.0f, 20, track_data_34, false);
Police_Maze_Target_Track_Add(35, -635.0f, -5.7f, 1165.0f, -620.0f, -8.63f, 1366.0f, 10, track_data_35, false);
Police_Maze_Target_Track_Add(36, -620.0f, -8.63f, 1366.0f, -595.0f, -8.63f, 1366.0f, 10, track_data_36, false);
@@ -270,7 +270,7 @@ void SceneScriptPS12::PlayerWalkedIn() {
Loop_Actor_Walk_To_XYZ(kActorMcCoy, -546.0f, -9.06f, 570.0f, 0, 1, false, 0);
Game_Flag_Reset(16);
}
- Police_Maze_Set_Pause_State(0);
+ Police_Maze_Set_Pause_State(false);
}
void SceneScriptPS12::PlayerWalkedOut() {
diff --git a/engines/bladerunner/script/scene/ps13.cpp b/engines/bladerunner/script/scene/ps13.cpp
index 83f99faf4f..f525d48137 100644
--- a/engines/bladerunner/script/scene/ps13.cpp
+++ b/engines/bladerunner/script/scene/ps13.cpp
@@ -25,7 +25,7 @@
namespace BladeRunner {
void SceneScriptPS13::InitializeScene() {
- Police_Maze_Set_Pause_State(1);
+ Police_Maze_Set_Pause_State(true);
if (Game_Flag_Query(18)) {
Scene_Loop_Start_Special(0, 0, 0);
Scene_Loop_Set_Default(1);
@@ -99,7 +99,7 @@ void SceneScriptPS13::SceneLoaded() {
Item_Add_To_World(51, 443, 14, -24.0f, 102.0f, 1625.0f, 823, 72, 36, true, false, false, true);
Item_Add_To_World(52, 449, 14, 180.0f, -72.7f, 1605.0f, 305, 72, 36, true, false, false, true);
Item_Add_To_World(53, 443, 14, 127.79f, 14.56f, 1703.03f, 356, 72, 36, true, false, false, true);
- Item_Add_To_World(54, 443, 14, 136.37f, -6.84f, 1425.4301f, 512, 72, 36, true, false, false, true);
+ Item_Add_To_World(54, 443, 14, 136.37f, -6.84f, 1425.43f, 512, 72, 36, true, false, false, true);
Item_Add_To_World(55, 441, 14, 77.83f, -79.8f, 1520.5f, 327, 72, 36, true, false, false, true);
Item_Add_To_World(56, 441, 14, 77.83f, -7.8f, 1520.5f, 327, 72, 36, true, false, false, true);
Item_Add_To_World(57, 443, 14, -88.0f, -8.8f, 1520.5f, 327, 72, 36, true, false, false, true);
@@ -115,7 +115,7 @@ void SceneScriptPS13::SceneLoaded() {
Police_Maze_Target_Track_Add(51, -24.0f, 102.0f, 1625.0f, -24.0f, 138.0f, 1625.0f, 10, track_data_51, false);
Police_Maze_Target_Track_Add(52, 180.0f, -72.7f, 1605.0f, 180.0f, -0.7f, 1605.0f, 10, track_data_52, false);
Police_Maze_Target_Track_Add(53, 127.79f, 14.56f, 1703.03f, -56.07f, 1.89f, 1589.04f, 6, track_data_53, false);
- Police_Maze_Target_Track_Add(54, 136.37f, -6.84f, 1425.4301f, 117.55f, -6.84f, 1442.09f, 4, track_data_54, false);
+ Police_Maze_Target_Track_Add(54, 136.37f, -6.84f, 1425.43f, 117.55f, -6.84f, 1442.09f, 4, track_data_54, false);
Police_Maze_Target_Track_Add(55, 77.83f, -79.8f, 1520.5f, 77.83f, -7.8f, 1520.5f, 15, track_data_55, false);
Police_Maze_Target_Track_Add(56, 77.83f, -7.8f, 1520.5f, -88.0f, -8.8f, 1520.5f, 15, track_data_56, false);
Police_Maze_Target_Track_Add(57, -88.0f, -8.8f, 1520.5f, -88.0f, -80.8f, 1520.5f, 15, track_data_57, false);
@@ -255,7 +255,7 @@ void SceneScriptPS13::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bo
}
void SceneScriptPS13::PlayerWalkedIn() {
- Police_Maze_Set_Pause_State(0);
+ Police_Maze_Set_Pause_State(false);
}
void SceneScriptPS13::PlayerWalkedOut() {
diff --git a/engines/bladerunner/script/scene/rc01.cpp b/engines/bladerunner/script/scene/rc01.cpp
index 867e3bd661..db89807022 100644
--- a/engines/bladerunner/script/scene/rc01.cpp
+++ b/engines/bladerunner/script/scene/rc01.cpp
@@ -74,6 +74,8 @@ void SceneScriptRC01::InitializeScene() {
// Global_Variable_Set(kVariableChapter, 2);
// Chapter_Enter(2, kSetRC03, kSceneRC03);
+ Set_Enter(14, 73);
+
#endif
if (!Game_Flag_Query(kFlagIntroPlayed)) {
diff --git a/engines/bladerunner/script/scene/tb05.cpp b/engines/bladerunner/script/scene/tb05.cpp
index b3299292f1..a7797414d6 100644
--- a/engines/bladerunner/script/scene/tb05.cpp
+++ b/engines/bladerunner/script/scene/tb05.cpp
@@ -52,10 +52,10 @@ void SceneScriptTB05::SceneLoaded() {
Clickable_Object("MONITOR05");
Unclickable_Object("SMUDGE_GLASS01");
if (!Actor_Clue_Query(kActorMcCoy, kClueDragonflyEarring)) {
- Item_Add_To_World(76, 940, 72, 76.160004f, 147.36f, -235.14999f, 0, 6, 6, false, true, false, true);
+ Item_Add_To_World(76, 940, 72, 76.16f, 147.36f, -235.15f, 0, 6, 6, false, true, false, true);
}
if (!Actor_Clue_Query(kActorMcCoy, kClueTyrellSalesPamphlet1) && !Actor_Clue_Query(kActorMcCoy, kClueTyrellSalesPamphlet2) && (Game_Flag_Query(kFlagGordoIsReplicant) || Game_Flag_Query(kFlagLucyIsReplicant))) {
- Item_Add_To_World(119, 972, 72, 129.00999f, 147.12f, -162.98f, 0, 8, 8, false, true, false, true);
+ Item_Add_To_World(119, 972, 72, 129.01f, 147.12f, -162.98f, 0, 8, 8, false, true, false, true);
}
}
diff --git a/engines/bladerunner/script/scene/ug02.cpp b/engines/bladerunner/script/scene/ug02.cpp
index c6b96c65a5..f8f1e84578 100644
--- a/engines/bladerunner/script/scene/ug02.cpp
+++ b/engines/bladerunner/script/scene/ug02.cpp
@@ -153,9 +153,9 @@ bool SceneScriptUG02::ClickedOnExit(int exitId) {
Loop_Actor_Travel_Stairs(kActorMcCoy, 4, 0, 0);
Footstep_Sound_Override_Off();
int v3 = Player_Query_Combat_Mode();
- Loop_Actor_Walk_To_XYZ(kActorMcCoy, -96.57f, 74.870003f, -271.28f, 0, 0, v3, 0);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, -96.57f, 74.87f, -271.28f, 0, 0, v3, 0);
int v4 = Player_Query_Combat_Mode();
- Loop_Actor_Walk_To_XYZ(kActorMcCoy, -95.0f, 74.870003f, -503.0f, 0, 0, v4, 0);
+ Loop_Actor_Walk_To_XYZ(kActorMcCoy, -95.0f, 74.87f, -503.0f, 0, 0, v4, 0);
Game_Flag_Set(315);
Set_Enter(74, kSceneUG01);
}
diff --git a/engines/bladerunner/script/scene/ug05.cpp b/engines/bladerunner/script/scene/ug05.cpp
index c3996dca37..3348ebbfb6 100644
--- a/engines/bladerunner/script/scene/ug05.cpp
+++ b/engines/bladerunner/script/scene/ug05.cpp
@@ -222,10 +222,10 @@ void SceneScriptUG05::DialogueQueueFlushed(int a1) {
}
int SceneScriptUG05::sub_4021B0() {
- if (Global_Variable_Query(45) == 2 && Actor_Query_Goal_Number(kActorDektora) != 599) {
+ if (Global_Variable_Query(kVariableAffectionTowards) == 2 && Actor_Query_Goal_Number(kActorDektora) != 599) {
return kActorDektora;
}
- if (Global_Variable_Query(45) == 3 && Actor_Query_Goal_Number(kActorLucy) != 599) {
+ if (Global_Variable_Query(kVariableAffectionTowards) == 3 && Actor_Query_Goal_Number(kActorLucy) != 599) {
return kActorLucy;
}
return -1;
diff --git a/engines/bladerunner/script/scene/ug07.cpp b/engines/bladerunner/script/scene/ug07.cpp
index 9a586407fc..4a256b02c7 100644
--- a/engines/bladerunner/script/scene/ug07.cpp
+++ b/engines/bladerunner/script/scene/ug07.cpp
@@ -119,7 +119,7 @@ bool SceneScriptUG07::ClickedOnExit(int exitId) {
Actor_Set_At_XYZ(kActorClovis, 118.02f, -12.21f, -154.0f, 768);
Player_Set_Combat_Mode(true);
Actor_Face_Actor(kActorMcCoy, kActorClovis, true);
- Loop_Actor_Walk_To_XYZ(kActorClovis, 98.019997f, -12.21f, -154.0f, 0, 0, false, 0);
+ Loop_Actor_Walk_To_XYZ(kActorClovis, 98.02f, -12.21f, -154.0f, 0, 0, false, 0);
Actor_Face_Actor(kActorClovis, kActorMcCoy, true);
Actor_Set_Goal_Number(kActorMcCoy, 301);
Actor_Face_Heading(kActorMcCoy, 0, true);
diff --git a/engines/bladerunner/script/scene/ug15.cpp b/engines/bladerunner/script/scene/ug15.cpp
index 8477e5b46f..3503992457 100644
--- a/engines/bladerunner/script/scene/ug15.cpp
+++ b/engines/bladerunner/script/scene/ug15.cpp
@@ -26,9 +26,9 @@ namespace BladeRunner {
void SceneScriptUG15::InitializeScene() {
if (Game_Flag_Query(353)) {
- Setup_Scene_Information(-25.0f, 26.309999f, -434.0f, 520);
+ Setup_Scene_Information(-25.0f, 26.31f, -434.0f, 520);
} else if (Game_Flag_Query(153)) {
- Setup_Scene_Information(-17.0f, 26.309999f, -346.0f, 711);
+ Setup_Scene_Information(-17.0f, 26.31f, -346.0f, 711);
} else if (Game_Flag_Query(355)) {
Setup_Scene_Information(-18.0f, 48.07f, 62.0f, 650);
} else {
diff --git a/engines/bladerunner/script/scene/ug18.cpp b/engines/bladerunner/script/scene/ug18.cpp
index cafe42654a..05ef4559fb 100644
--- a/engines/bladerunner/script/scene/ug18.cpp
+++ b/engines/bladerunner/script/scene/ug18.cpp
@@ -110,7 +110,7 @@ bool SceneScriptUG18::ClickedOnItem(int itemId, bool a2) {
bool SceneScriptUG18::ClickedOnExit(int exitId) {
if (exitId == 0) {
- if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, -684.712f, 0.0f, 171.59f, 0, 1, false, 0)) {
+ if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, -684.71f, 0.0f, 171.59f, 0, 1, false, 0)) {
Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
Ambient_Sounds_Remove_All_Looping_Sounds(1);
Game_Flag_Set(435);
@@ -323,9 +323,8 @@ void SceneScriptUG18::sub_402734() {
}
void SceneScriptUG18::sub_402DE8() {
-
if (Player_Query_Agenda()) {
- if (Global_Variable_Query(45) > 1 || Player_Query_Agenda() == 2) {
+ if (Global_Variable_Query(kVariableAffectionTowards) > 1 || Player_Query_Agenda() == 2) {
sub_403114();
} else {
sub_402F8C();
diff --git a/engines/bladerunner/script/scene_script.cpp b/engines/bladerunner/script/scene_script.cpp
index 01fe3e3b1e..ff43853044 100644
--- a/engines/bladerunner/script/scene_script.cpp
+++ b/engines/bladerunner/script/scene_script.cpp
@@ -161,8 +161,10 @@ void SceneScript::initializeScene() {
}
void SceneScript::sceneLoaded() {
+ _vm->_sceneIsLoading = true;
_inScriptCounter++;
_currentScript->SceneLoaded();
+ _vm->_sceneIsLoading = false;
_inScriptCounter--;
}
diff --git a/engines/bladerunner/script/scene_script.h b/engines/bladerunner/script/scene_script.h
index 54047ed8a8..51cac52db6 100644
--- a/engines/bladerunner/script/scene_script.h
+++ b/engines/bladerunner/script/scene_script.h
@@ -385,7 +385,7 @@ DECLARE_SCRIPT(PS09)
END_SCRIPT
DECLARE_SCRIPT(PS10)
- void sub_402238();
+ void removeTargets();
END_SCRIPT
DECLARE_SCRIPT(PS11)
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 2aca6db9d3..3c68717116 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -45,6 +45,7 @@
#include "bladerunner/set_effects.h"
#include "bladerunner/scene.h"
#include "bladerunner/scene_objects.h"
+#include "bladerunner/script/police_maze.h"
#include "bladerunner/slice_animations.h"
#include "bladerunner/slice_renderer.h"
#include "bladerunner/suspects_database.h"
@@ -52,6 +53,7 @@
#include "bladerunner/ui/elevator.h"
#include "bladerunner/ui/esper.h"
#include "bladerunner/ui/kia.h"
+#include "bladerunner/ui/scores.h"
#include "bladerunner/ui/spinner.h"
#include "bladerunner/ui/vk.h"
#include "bladerunner/vector.h"
@@ -130,7 +132,7 @@ void ScriptBase::Actor_Face_Heading(int actorId, int heading, bool animate) {
}
int ScriptBase::Actor_Query_Friendliness_To_Other(int actorId, int otherActorId) {
- return _vm->_actors[actorId]->_friendlinessToOther[otherActorId];
+ return _vm->_actors[actorId]->getFriendlinessToOther(otherActorId);
}
void ScriptBase::Actor_Modify_Friendliness_To_Other(int actorId, int otherActorId, signed int change) {
@@ -158,27 +160,27 @@ void ScriptBase::Actor_Set_Combat_Aggressiveness(int actorId, int combatAggressi
}
int ScriptBase::Actor_Query_Current_HP(int actorId) {
- return _vm->_actors[actorId]->_currentHP;
+ return _vm->_actors[actorId]->getCurrentHP();
}
int ScriptBase::Actor_Query_Max_HP(int actorId) {
- return _vm->_actors[actorId]->_maxHP;
+ return _vm->_actors[actorId]->getMaxHP();
}
int ScriptBase::Actor_Query_Combat_Aggressiveness(int actorId) {
- return _vm->_actors[actorId]->_combatAggressiveness;
+ return _vm->_actors[actorId]->getCombatAggressiveness();
}
int ScriptBase::Actor_Query_Honesty(int actorId) {
- return _vm->_actors[actorId]->_honesty;
+ return _vm->_actors[actorId]->getHonesty();
}
int ScriptBase::Actor_Query_Intelligence(int actorId) {
- return _vm->_actors[actorId]->_intelligence;
+ return _vm->_actors[actorId]->getIntelligence();
}
int ScriptBase::Actor_Query_Stability(int actorId) {
- return _vm->_actors[actorId]->_stability;
+ return _vm->_actors[actorId]->getStability();
}
void ScriptBase::Actor_Modify_Current_HP(int actorId, signed int change) {
@@ -218,8 +220,8 @@ void ScriptBase::Actor_Combat_AI_Hit_Attempt(int actorId) {
_vm->_actors[actorId]->_combatInfo->hitAttempt();
}
-void ScriptBase::Non_Player_Actor_Combat_Mode_On(int actorId, int a2, int a3, int otherActorId, int a5, int animationModeCombatIdle, int animationModeCombatWalk, int animationModeCombatRun, int a9, int a10, int a11, int a12, int a13, int a14) {
- _vm->_actors[actorId]->combatModeOn(a2, a3, otherActorId, a5, animationModeCombatIdle, animationModeCombatWalk, animationModeCombatRun, a9, a10, a11, a12, a13, a14);
+void ScriptBase::Non_Player_Actor_Combat_Mode_On(int actorId, int initialState, bool rangedAttack, int enemyId, int waypointType, int animationModeCombatIdle, int animationModeCombatWalk, int animationModeCombatRun, int fleeRatio, int coverRatio, int actionRatio, int damage, int range, bool unstoppable) {
+ _vm->_actors[actorId]->combatModeOn(initialState, rangedAttack, enemyId, waypointType, animationModeCombatIdle, animationModeCombatWalk, animationModeCombatRun, fleeRatio, coverRatio, actionRatio, damage, range, unstoppable);
}
void ScriptBase::Non_Player_Actor_Combat_Mode_Off(int actorId) {
@@ -680,15 +682,20 @@ void ScriptBase::Item_Remove_From_World(int itemId) {
}
void ScriptBase::Item_Spin_In_World(int itemId) {
- warning("Item_Spin_In_World(%d)", itemId);
+ _vm->_items->spinInWorld(itemId);
+ if (_vm->_items->isPoliceMazeEnemy(itemId)) {
+ Police_Maze_Increment_Score(1);
+ } else {
+ Police_Maze_Decrement_Score(1);
+ }
}
void ScriptBase::Item_Flag_As_Target(int itemId) {
- warning("Item_Flag_As_Target(%d)", itemId);
+ _vm->_items->setIsTarget(itemId, true);
}
void ScriptBase::Item_Flag_As_Non_Target(int itemId) {
- warning("Item_Flag_As_Non_Target(%d)", itemId);
+ _vm->_items->setIsTarget(itemId, false);
}
void ScriptBase::Item_Pickup_Spin_Effect(int animationId, int x, int y) {
@@ -723,8 +730,9 @@ int ScriptBase::Animation_Skip_To_Frame() {
void ScriptBase::Delay(int miliseconds) {
Player_Loses_Control();
int endTime = _vm->getTotalPlayTime() + miliseconds;
- while ((int)_vm->getTotalPlayTime() < endTime)
+ while ((int)_vm->getTotalPlayTime() < endTime) {
_vm->gameTick();
+ }
Player_Gains_Control();
}
@@ -825,8 +833,7 @@ int ScriptBase::Random_Query(int min, int max) {
}
void ScriptBase::Sound_Play(int id, int volume, int panFrom, int panTo, int priority) {
- const char *name = _vm->_gameInfo->getSfxTrack(id);
- _vm->_audioPlayer->playAud(name, volume, panFrom, panTo, priority);
+ _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(id), volume, panFrom, panTo, priority);
}
void ScriptBase::Sound_Play_Speech_Line(int actorId, int sentenceId, int volume, int a4, int priority) {
@@ -892,8 +899,7 @@ void ScriptBase::Footstep_Sound_Override_Off() {
}
bool ScriptBase::Music_Play(int musicId, int volume, int pan, int timeFadeIn, int timePlay, int loop, int timeFadeOut) {
- const char *musicName = _vm->_gameInfo->getMusicTrack(musicId);
- return _vm->_music->play(musicName, volume, pan, timeFadeIn, timePlay, loop, timeFadeOut);
+ return _vm->_music->play(_vm->_gameInfo->getMusicTrack(musicId), volume, pan, timeFadeIn, timePlay, loop, timeFadeOut);
}
void ScriptBase::Music_Adjust(int volume, int pan, int delay) {
@@ -1075,31 +1081,56 @@ float ScriptBase::World_Waypoint_Query_Z(int waypointId) {
return _vm->_waypoints->getZ(waypointId);
}
-void ScriptBase::Combat_Cover_Waypoint_Set_Data(int combatCoverId, int type, int setId, int sceneId, float x, float y, float z) {
- //TODO
- warning("Combat_Cover_Waypoint_Set_Data(%d, %d, %d, %d, %f, %f, %f)", combatCoverId, type, setId, sceneId, x, y, z);
+void ScriptBase::Combat_Cover_Waypoint_Set_Data(int coverWaypointId, int type, int setId, int sceneId, float x, float y, float z) {
+ assert(coverWaypointId < (int)_vm->_combat->_coverWaypoints.size());
+
+ _vm->_combat->_coverWaypoints[coverWaypointId].type = type;
+ _vm->_combat->_coverWaypoints[coverWaypointId].setId = setId;
+ _vm->_combat->_coverWaypoints[coverWaypointId].sceneId = sceneId;
+ _vm->_combat->_coverWaypoints[coverWaypointId].position.x = x;
+ _vm->_combat->_coverWaypoints[coverWaypointId].position.y = y;
+ _vm->_combat->_coverWaypoints[coverWaypointId].position.z = z;
}
-void ScriptBase::Combat_Flee_Waypoint_Set_Data(int combatFleeWaypointId, int type, int setId, int sceneId, float x, float y, float z, int a8) {
- //TODO
- warning("Combat_Cover_Waypoint_Set_Data(%d, %d, %d, %d, %f, %f, %f, %d)", combatFleeWaypointId, type, setId, sceneId, x, y, z, a8);
+void ScriptBase::Combat_Flee_Waypoint_Set_Data(int fleeWaypointId, int type, int setId, int sceneId, float x, float y, float z, int a8) {
+ assert(fleeWaypointId < (int)_vm->_combat->_fleeWaypoints.size());
+
+ _vm->_combat->_fleeWaypoints[fleeWaypointId].type = type;
+ _vm->_combat->_fleeWaypoints[fleeWaypointId].setId = setId;
+ _vm->_combat->_fleeWaypoints[fleeWaypointId].sceneId = sceneId;
+ _vm->_combat->_fleeWaypoints[fleeWaypointId].position.x = x;
+ _vm->_combat->_fleeWaypoints[fleeWaypointId].position.y = y;
+ _vm->_combat->_fleeWaypoints[fleeWaypointId].position.z = z;
+ _vm->_combat->_fleeWaypoints[fleeWaypointId].field7 = a8;
}
-void ScriptBase::Police_Maze_Target_Track_Add(int itemId, float startX, float startY, float startZ, float endX, float endY, float endZ, int steps, signed int data[], bool a10) {
- //TODO
- warning("Police_Maze_Target_Track_Add(%d, %f, %f, %f, %f, %f, %f, %d, %p, %d)", itemId, startX, startY, startZ, endX, endY, endZ, steps, (void *)data, a10);
+void ScriptBase::Police_Maze_Target_Track_Add(int itemId, float startX, float startY, float startZ, float endX, float endY, float endZ, int steps, const int* instructions, bool isActive) {
+ _vm->_policeMaze->_tracks[itemId]->add(itemId, startX, startY, startZ, endX, endY, endZ, steps, instructions, isActive);
+ _vm->_policeMaze->activate();
+}
+
+int ScriptBase::Police_Maze_Query_Score() {
+ return Global_Variable_Query(kVariablePoliceMazeScore);
+}
+void ScriptBase::Police_Maze_Zero_Score() {
+ Global_Variable_Reset(kVariablePoliceMazeScore);
}
-// ScriptBase::Police_Maze_Query_Score
-// ScriptBase::Police_Maze_Zero_Score
-// ScriptBase::Police_Maze_Increment_Score
-// ScriptBase::Police_Maze_Decrement_Score
-// ScriptBase::Police_Maze_Set_Score
+void ScriptBase::Police_Maze_Increment_Score(int delta) {
+ Global_Variable_Set(kVariablePoliceMazeScore, Global_Variable_Query(kVariablePoliceMazeScore) + delta);
+}
-void ScriptBase::Police_Maze_Set_Pause_State(int a1) {
- //TODO
- warning("Police_Maze_Set_Pause_State(%d)", a1);
+void ScriptBase::Police_Maze_Decrement_Score(int delta) {
+ Global_Variable_Set(kVariablePoliceMazeScore, Global_Variable_Query(kVariablePoliceMazeScore) - delta);
+}
+
+void ScriptBase::Police_Maze_Set_Score(int value) {
+ Global_Variable_Set(kVariablePoliceMazeScore, value);
+}
+
+void ScriptBase::Police_Maze_Set_Pause_State(bool state) {
+ _vm->_policeMaze->setPauseState(state);
}
void ScriptBase::CDB_Set_Crime(int clueId, int crimeId) {
@@ -1181,18 +1212,15 @@ int ScriptBase::Elevator_Activate(int elevatorId) {
}
void ScriptBase::View_Score_Board() {
- //TODO
- warning("View_Score_Board()");
+ _vm->_scores->open();
}
-int ScriptBase::Query_Score(int a0) {
- warning("Query_Score(%d)", a0);
-
- return 0;
+int ScriptBase::Query_Score(int index) {
+ return _vm->_scores->query(index);
}
-void ScriptBase::Set_Score(int a0, int a1) {
- warning("Set_Score(%d, %d)", a0, a1);
+void ScriptBase::Set_Score(int index, int value) {
+ _vm->_scores->set(index, value);
}
void ScriptBase::Give_McCoy_Ammo(int ammoType, int ammo) {
@@ -1221,10 +1249,8 @@ bool ScriptBase::Query_System_Currently_Loading_Game() {
void ScriptBase::Actor_Retired_Here(int actorId, int width, int height, int retired, int retiredByActorId) {
Actor *actor = _vm->_actors[actorId];
- Vector3 actorPosition;
- actor->getXYZ(&actorPosition.x, &actorPosition.y, &actorPosition.z);
actor->retire(retired, width, height, retiredByActorId);
- actor->setAtXYZ(actorPosition, actor->getFacing(), true, false, true);
+ actor->setAtXYZ(actor->getXYZ(), actor->getFacing(), true, false, true);
_vm->_sceneObjects->setRetired(actorId + kSceneObjectOffsetActors, true);
}
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 7faf3886b2..09c372d009 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -23,16 +23,18 @@
#ifndef BLADERUNNER_SCRIPT_H
#define BLADERUNNER_SCRIPT_H
-#include "common/str.h"
-
#include "bladerunner/bladerunner.h"
#include "bladerunner/game_constants.h"
+#include "common/str.h"
+
namespace BladeRunner {
class BladeRunnerEngine;
class ScriptBase {
+friend class SceneScript;
+
protected:
BladeRunnerEngine *_vm;
@@ -78,7 +80,7 @@ protected:
void Actor_Set_Flag_Damage_Anim_If_Moving(int actorId, bool value);
bool Actor_Query_Flag_Damage_Anim_If_Moving(int actorId);
void Actor_Combat_AI_Hit_Attempt(int actorId);
- void Non_Player_Actor_Combat_Mode_On(int actorId, int a2, int a3, int otherActorId, int a5, int animationModeCombatIdle, int animationModeCombatWalk, int animationModeCombatRun, int a9, int a10, int a11, int a12, int a13, int a14);
+ void Non_Player_Actor_Combat_Mode_On(int actorId, int initialState, bool rangedAttack, int enemyId, int waypointType, int animationModeCombatIdle, int animationModeCombatWalk, int animationModeCombatRun, int fleeRatio, int coverRatio, int actionRatio, int damage, int range, bool unstoppable);
void Non_Player_Actor_Combat_Mode_Off(int actorId);
void Actor_Set_Health(int actorId, int hp, int maxHp);
void Actor_Set_Targetable(int actorId, bool targetable);
@@ -205,15 +207,15 @@ protected:
float World_Waypoint_Query_X(int waypointId);
float World_Waypoint_Query_Y(int waypointId);
float World_Waypoint_Query_Z(int waypointId);
- void Combat_Cover_Waypoint_Set_Data(int combatCoverId, int a2, int setId, int a4, float x, float y, float z);
- void Combat_Flee_Waypoint_Set_Data(int combatFleeWaypointId, int a2, int setId, int a4, float x, float y, float z, int a8);
- void Police_Maze_Target_Track_Add(int itemId, float startX, float startY, float startZ, float endX, float endY, float endZ, int steps, signed int data[], bool a10);
- // Police_Maze_Query_Score
- // Police_Maze_Zero_Score
- // Police_Maze_Increment_Score
- // Police_Maze_Decrement_Score
- // Police_Maze_Set_Score
- void Police_Maze_Set_Pause_State(int a1);
+ void Combat_Cover_Waypoint_Set_Data(int coverWaypointId, int a2, int setId, int a4, float x, float y, float z);
+ void Combat_Flee_Waypoint_Set_Data(int fleeWaypointId, int a2, int setId, int a4, float x, float y, float z, int a8);
+ void Police_Maze_Target_Track_Add(int itemId, float startX, float startY, float startZ, float endX, float endY, float endZ, int steps, const int* instructions, bool isActive);
+ int Police_Maze_Query_Score();
+ void Police_Maze_Zero_Score();
+ void Police_Maze_Increment_Score(int delta);
+ void Police_Maze_Decrement_Score(int delta);
+ void Police_Maze_Set_Score(int value);
+ void Police_Maze_Set_Pause_State(bool state);
void CDB_Set_Crime(int clueId, int crimeId);
void CDB_Set_Clue_Asset_Type(int clueId, int assetType);
void SDB_Set_Actor(int suspectId, int actorId);
diff --git a/engines/bladerunner/script/vk_script.cpp b/engines/bladerunner/script/vk_script.cpp
index 8a7ddb26eb..eef5f5bdaf 100644
--- a/engines/bladerunner/script/vk_script.cpp
+++ b/engines/bladerunner/script/vk_script.cpp
@@ -1209,12 +1209,12 @@ void VKScript::askDektora(int questionId) {
VK_Play_Speech_Line(kActorDektora, 1520, 0.5f);
VK_Play_Speech_Line(kActorMcCoy, 7840, 0.5f);
VK_Subject_Reacts(20, -1, 9, 10);
- VK_Play_Speech_Line(kActorDektora, 1540, 0.80000001f);
+ VK_Play_Speech_Line(kActorDektora, 1540, 0.8f);
VK_Play_Speech_Line(kActorDektora, 1550, 0.5f);
} else {
VK_Play_Speech_Line(kActorDektora, 1560, 0.5f);
VK_Subject_Reacts(25, 13, -3, 0);
- VK_Play_Speech_Line(kActorDektora, 1570, 0.80000001f);
+ VK_Play_Speech_Line(kActorDektora, 1570, 0.8f);
VK_Play_Speech_Line(kActorDektora, 1580, 0.5f);
}
break;
@@ -1234,7 +1234,7 @@ void VKScript::askDektora(int questionId) {
VK_Subject_Reacts(25, -1, 9, 0);
} else {
VK_Subject_Reacts(25, 14, -2, 0);
- VK_Play_Speech_Line(kActorDektora, 1630, 0.89999998f);
+ VK_Play_Speech_Line(kActorDektora, 1630, 0.9f);
VK_Play_Speech_Line(kActorDektora, 1640, 0.5f);
}
break;
@@ -1274,7 +1274,7 @@ void VKScript::askDektora(int questionId) {
VK_Play_Speech_Line(kActorDektora, 1740, 0.5f);
VK_Play_Speech_Line(kActorMcCoy, 7805, 0.5f);
VK_Eye_Animates(2);
- VK_Play_Speech_Line(kActorDektora, 1750, 0.89999998f);
+ VK_Play_Speech_Line(kActorDektora, 1750, 0.9f);
VK_Play_Speech_Line(kActorDektora, 1760, 0.5f);
break;
case 7455:
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index fe10c189b6..ac026a4d76 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/bladerunner.h"
#include "bladerunner/game_constants.h"
#include "bladerunner/lights.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/scene_objects.h"
#include "bladerunner/set_effects.h"
#include "bladerunner/slice_renderer.h"
@@ -67,8 +68,10 @@ bool Set::open(const Common::String &name) {
_objectCount = s->readUint32LE();
assert(_objectCount <= 85);
+ char buf[20];
for (int i = 0; i < _objectCount; ++i) {
- s->read(_objects[i].name, 20);
+ s->read(buf, sizeof(buf));
+ _objects[i].name = buf;
float x0, y0, z0, x1, y1, z1;
x0 = s->readFloatLE();
@@ -82,6 +85,7 @@ bool Set::open(const Common::String &name) {
_objects[i].isObstacle = s->readByte();
_objects[i].isClickable = s->readByte();
_objects[i].isHotMouse = 0;
+ _objects[i].unknown1 = 0;
_objects[i].isTarget = 0;
s->skip(4);
@@ -94,7 +98,9 @@ bool Set::open(const Common::String &name) {
for (int i = 0; i < _walkboxCount; ++i) {
float x, z;
- s->read(_walkboxes[i].name, 20);
+ s->read(buf, sizeof(buf));
+ _walkboxes[i].name = buf;
+
_walkboxes[i].altitude = s->readFloatLE();
_walkboxes[i].vertexCount = s->readUint32LE();
@@ -129,7 +135,7 @@ bool Set::open(const Common::String &name) {
void Set::addObjectsToScene(SceneObjects *sceneObjects) const {
for (int i = 0; i < _objectCount; i++) {
- sceneObjects->addObject(i + kSceneObjectOffsetObjects, &_objects[i].bbox, _objects[i].isClickable, _objects[i].isObstacle, _objects[i].unknown1, _objects[i].isTarget);
+ sceneObjects->addObject(i + kSceneObjectOffsetObjects, _objects[i].bbox, _objects[i].isClickable, _objects[i].isObstacle, _objects[i].unknown1, _objects[i].isTarget);
}
}
@@ -207,15 +213,14 @@ int Set::findWalkbox(float x, float z) const {
return result;
}
-int Set::findObject(const char *objectName) const {
- int i;
- for (i = 0; i < (int)_objectCount; i++) {
- if (scumm_stricmp(objectName, _objects[i].name) == 0) {
+int Set::findObject(const Common::String &objectName) const {
+ for (int i = 0; i < _objectCount; ++i) {
+ if (objectName.compareToIgnoreCase(_objects[i].name) == 0) {
return i;
}
}
- debug("Set::findObject didn't find \"%s\"", objectName);
+ debug("Set::findObject didn't find \"%s\"", objectName.c_str());
return -1;
}
@@ -256,7 +261,7 @@ void Set::objectSetIsTarget(int objectId, bool isTarget) {
_objects[objectId].isTarget = isTarget;
}
-const char *Set::objectGetName(int objectId) const {
+const Common::String &Set::objectGetName(int objectId) const {
return _objects[objectId].name;
}
@@ -327,4 +332,74 @@ int Set::getWalkboxSoundRunLeft(int walkboxId) const {
int Set::getWalkboxSoundRunRight(int walkboxId) const {
return getWalkboxSoundWalkRight(walkboxId);
}
+
+void Set::save(SaveFileWriteStream &f) {
+ f.writeBool(_loaded);
+ f.writeInt(_objectCount);
+ f.writeInt(_walkboxCount);
+
+ for (int i = 0; i != _objectCount; ++i) {
+ f.writeStringSz(_objects[i].name, 20);
+ f.writeBoundingBox(_objects[i].bbox);
+ f.writeBool(_objects[i].isObstacle);
+ f.writeBool(_objects[i].isClickable);
+ f.writeBool(_objects[i].isHotMouse);
+ f.writeInt(_objects[i].unknown1);
+ f.writeBool(_objects[i].isTarget);
+ }
+
+ for (int i = 0; i != _walkboxCount; ++i) {
+ f.writeStringSz(_walkboxes[i].name, 20);
+ f.writeFloat(_walkboxes[i].altitude);
+ f.writeInt(_walkboxes[i].vertexCount);
+ for (int j = 0; j != 8; ++j) {
+ f.writeVector3(_walkboxes[i].vertices[j]);
+
+ // In BLADE.EXE vertices are a vec5
+ f.writeInt(0);
+ f.writeInt(0);
+ }
+ }
+
+ for (int i = 0; i != 85; ++i) {
+ f.writeInt(_walkboxStepSound[i]);
+ }
+
+ f.writeInt(_footstepSoundOverride);
+}
+
+void Set::load(SaveFileReadStream &f) {
+ _loaded = f.readBool();
+ _objectCount = f.readInt();
+ _walkboxCount = f.readInt();
+
+ for (int i = 0; i != _objectCount; ++i) {
+ _objects[i].name = f.readStringSz(20);
+ _objects[i].bbox = f.readBoundingBox();
+ _objects[i].isObstacle = f.readBool();
+ _objects[i].isClickable = f.readBool();
+ _objects[i].isHotMouse = f.readBool();
+ _objects[i].unknown1 = f.readInt();
+ _objects[i].isTarget = f.readBool();
+ }
+
+ for (int i = 0; i != _walkboxCount; ++i) {
+ _walkboxes[i].name = f.readStringSz(20);
+ _walkboxes[i].altitude = f.readFloat();
+ _walkboxes[i].vertexCount = f.readInt();
+ for (int j = 0; j != 8; ++j) {
+ _walkboxes[i].vertices[j] = f.readVector3();
+
+ // In BLADE.EXE vertices are a vec5
+ f.skip(8);
+ }
+ }
+
+ for (int i = 0; i != 85; ++i) {
+ _walkboxStepSound[i] = f.readInt();
+ }
+
+ _footstepSoundOverride = f.readInt();
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index a6e7e9f3df..c6c1081196 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -32,28 +32,30 @@ namespace BladeRunner {
class BladeRunnerEngine;
-class VQADecoder;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class SetEffects;
class SceneObjects;
+class VQADecoder;
class Set {
friend class Debugger;
struct Object {
- char name[20];
- BoundingBox bbox;
- uint8 isObstacle;
- uint8 isClickable;
- uint8 isHotMouse;
- uint8 isTarget;
- uint8 unknown1;
+ Common::String name;
+ BoundingBox bbox;
+ uint8 isObstacle;
+ uint8 isClickable;
+ uint8 isHotMouse;
+ uint8 isTarget;
+ uint8 unknown1;
};
struct Walkbox {
- char name[20];
- float altitude;
- int vertexCount;
- Vector3 vertices[8];
+ Common::String name;
+ float altitude;
+ int vertexCount;
+ Vector3 vertices[8];
};
BladeRunnerEngine *_vm;
@@ -82,23 +84,27 @@ public:
float getAltitudeAtXZ(float x, float z, bool *inWalkbox) const;
int findWalkbox(float x, float z) const;
- int findObject(const char *objectName) const;
+ int findObject(const Common::String &objectName) const;
bool objectSetHotMouse(int objectId) const;
bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox) const;
void objectSetIsClickable(int objectId, bool isClickable);
void objectSetIsObstacle(int objectId, bool isObstacle);
void objectSetIsTarget(int objectId, bool isTarget);
- const char *objectGetName(int objectId) const;
+ const Common::String &objectGetName(int objectId) const;
void setWalkboxStepSound(int walkboxId, int soundId);
void setFoodstepSoundOverride(int soundId);
void resetFoodstepSoundOverride();
+
int getWalkboxSoundWalkLeft(int walkboxId) const;
int getWalkboxSoundWalkRight(int walkboxId) const;
int getWalkboxSoundRunLeft(int walkboxId) const;
int getWalkboxSoundRunRight(int walkboxId) const;
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
private:
static bool isXZInWalkbox(float x, float z, const Walkbox &walkbox);
};
diff --git a/engines/bladerunner/set_effects.cpp b/engines/bladerunner/set_effects.cpp
index 5c7b2487a8..3d46e41e7b 100644
--- a/engines/bladerunner/set_effects.cpp
+++ b/engines/bladerunner/set_effects.cpp
@@ -104,7 +104,7 @@ void SetEffects::setFadeDensity(float density) {
_fadeDensity = density;
}
-void SetEffects::setFogColor(const char *fogName, float r, float g, float b) {
+void SetEffects::setFogColor(const Common::String &fogName, float r, float g, float b) {
Fog *fog = findFog(fogName);
if (fog == nullptr) {
return;
@@ -115,7 +115,7 @@ void SetEffects::setFogColor(const char *fogName, float r, float g, float b) {
fog->_fogColor.b = b;
}
-void SetEffects::setFogDensity(const char *fogName, float density) {
+void SetEffects::setFogDensity(const Common::String &fogName, float density) {
Fog *fog = findFog(fogName);
if (fog == nullptr) {
return;
@@ -151,7 +151,7 @@ void SetEffects::calculateColor(Vector3 viewPosition, Vector3 position, float *o
outColor->b = outColor->b * (1.0f - _fadeDensity) + _fadeColor.b * _fadeDensity;
}
-Fog *SetEffects::findFog(const char *fogName) const {
+Fog *SetEffects::findFog(const Common::String &fogName) const {
if (!_fogs) {
return nullptr;
}
@@ -159,7 +159,7 @@ Fog *SetEffects::findFog(const char *fogName) const {
Fog *fog = _fogs;
while (fog != nullptr) {
- if (strcmp(fogName, fog->_name) == 0) {
+ if (fogName.compareTo(fog->_name) == 0) {
break;
}
fog = fog->_next;
diff --git a/engines/bladerunner/set_effects.h b/engines/bladerunner/set_effects.h
index 81d7b93149..6bd139c4d6 100644
--- a/engines/bladerunner/set_effects.h
+++ b/engines/bladerunner/set_effects.h
@@ -53,13 +53,13 @@ public:
void setFadeColor(float r, float g, float b);
void setFadeDensity(float density);
- void setFogColor(const char *fogName, float r, float g, float b);
- void setFogDensity(const char *fogName, float density);
+ void setFogColor(const Common::String &fogName, float r, float g, float b);
+ void setFogDensity(const Common::String &fogName, float density);
void calculateColor(Vector3 viewPosition, Vector3 position, float *outCoeficient, Color *outColor) const;
private:
- Fog *findFog(const char *fogName) const;
+ Fog *findFog(const Common::String &fogName) const;
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
index a5540fcb04..071adf6dd5 100644
--- a/engines/bladerunner/settings.cpp
+++ b/engines/bladerunner/settings.cpp
@@ -22,10 +22,14 @@
#include "bladerunner/settings.h"
+#include "bladerunner/actor.h"
#include "bladerunner/ambient_sounds.h"
#include "bladerunner/bladerunner.h"
#include "bladerunner/chapters.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/game_info.h"
#include "bladerunner/music.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/scene.h"
#include "common/debug.h"
@@ -39,14 +43,23 @@ Settings::Settings(BladeRunnerEngine *vm) {
_playerAgenda = 1;
_chapter = 1;
+ _scene = -1;
+ _set = -1;
+ _unk0 = 0;
_gamma = 1.0f;
+ _ammoType = 0;
+ _ammoAmounts[0] = 1;
+ _ammoAmounts[1] = 0;
+ _ammoAmounts[2] = 0;
+
+ // The remaining fields are not reset in BLADE.EXE
_chapterChanged = false;
_newChapter = -1;
_newScene = -1;
_newSet = -1;
- _startingGame = true;
+ _startingGame = false;
_loadingGame = false;
_fullHDFrames = true;
@@ -83,8 +96,9 @@ bool Settings::openNewScene() {
_vm->_scene->close(!_loadingGame && !_startingGame);
}
if (_chapterChanged) {
- if (_vm->_chapters->hasOpenResources())
+ if (_vm->_chapters->hasOpenResources()) {
_vm->_chapters->closeResources();
+ }
int newChapter = _newChapter;
_chapterChanged = false;
@@ -103,8 +117,23 @@ bool Settings::openNewScene() {
return false;
}
+ _set = newSet;
+ _scene = newScene;
+
if (!_loadingGame && currentSet != newSet) {
- // TODO: Reset actors for new set
+ for (int i = 0; i < (int)_vm->_gameInfo->getActorCount(); ++i) {
+ Actor *actor = _vm->_actors[i];
+ if (i != kActorMcCoy && actor->getSetId() == currentSet) {
+ if (!actor->isRetired()) {
+ actor->stopWalking(false);
+ actor->movementTrackWaypointReached();
+ }
+ if (actor->inCombat()) {
+ actor->setSetId(kSetFreeSlotG);
+ actor->combatModeOff();
+ }
+ }
+ }
}
_loadingGame = false;
@@ -171,4 +200,30 @@ void Settings::setLearyMode(bool learyMode) {
_learyMode = learyMode;
}
+void Settings::save(SaveFileWriteStream &f) {
+ f.writeInt(_scene);
+ f.writeInt(_set);
+ f.writeInt(_chapter);
+ f.writeInt(_playerAgenda);
+ f.writeInt(_unk0);
+ f.writeInt(_difficulty);
+ f.writeInt(_ammoType);
+ for (int i = 0; i != 3; ++i) {
+ f.writeInt(_ammoAmounts[i]);
+ }
+}
+
+void Settings::load(SaveFileReadStream &f) {
+ _scene = f.readInt();
+ _set = f.readInt();
+ _chapter = f.readInt();
+ _playerAgenda = f.readInt();
+ _unk0 = f.readInt();
+ _difficulty = f.readInt();
+ _ammoType = f.readInt();
+ for (int i = 0; i != 3; ++i) {
+ _ammoAmounts[i] = f.readInt();
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/settings.h b/engines/bladerunner/settings.h
index bf2d2d3162..413786e2e5 100644
--- a/engines/bladerunner/settings.h
+++ b/engines/bladerunner/settings.h
@@ -26,6 +26,8 @@
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
enum PlayerAgenda {
kPlayerAgendaPolite = 0,
@@ -39,6 +41,9 @@ class Settings {
BladeRunnerEngine *_vm;
int _chapter;
+ int _scene;
+ int _set;
+ int _unk0;
float _gamma;
bool _chapterChanged;
@@ -49,6 +54,8 @@ class Settings {
bool _startingGame;
bool _loadingGame;
+ // int _unk1;
+
int _fullHDFrames;
int _mst3k;
@@ -85,6 +92,18 @@ public:
return _newSet;
}
+ int getScene() const {
+ return _scene;
+ }
+
+ int getSet() const {
+ return _set;
+ }
+
+ int getChapter() const {
+ return _chapter;
+ }
+
void setChapter(int newChapter) {
_chapterChanged = true;
_newChapter = newChapter;
@@ -117,6 +136,9 @@ public:
bool getLearyMode() const;
void setLearyMode(bool learyMode);
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
};
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp
index 181b11d9f1..8678c1726b 100644
--- a/engines/bladerunner/slice_animations.cpp
+++ b/engines/bladerunner/slice_animations.cpp
@@ -93,8 +93,28 @@ bool SliceAnimations::openCoreAnim() {
return _coreAnimPageFile.open("COREANIM.DAT");
}
-bool SliceAnimations::openHDFrames() {
- return _framesPageFile.open("HDFRAMES.DAT");
+bool SliceAnimations::openFrames(int fileNumber) {
+ if (_framesPageFile._fileNumber == -1) { // Running for the first time, need to probe
+ // First, try HDFRAMES.DAT
+ if (_framesPageFile.open("HDFRAMES.DAT")) {
+ _framesPageFile._fileNumber = 0;
+
+ return true;
+ }
+ }
+
+ if (_framesPageFile._fileNumber == 0) // HDFRAMES.DAT
+ return true;
+
+ if (_framesPageFile._fileNumber == fileNumber)
+ return true;
+
+ _framesPageFile.close();
+
+ if (fileNumber == 1 && _framesPageFile.open("CDFRAMES.DAT")) // For Chapter1 we try both CDFRAMES.DAT and CDFRAMES1.DAT
+ return true;
+
+ return _framesPageFile.open(Common::String::format("CDFRAMES%d.DAT", fileNumber));
}
bool SliceAnimations::PageFile::open(const Common::String &name) {
@@ -119,11 +139,17 @@ bool SliceAnimations::PageFile::open(const Common::String &name) {
_pageOffsets[pageNumber] = dataOffset + i * _sliceAnimations->_pageSize;
}
- // debug("PageFile::Open: page file \"%s\" opened with %d pages", name.c_str(), pageCount);
+ debug(5, "PageFile::Open: page file \"%s\" opened with %d pages", name.c_str(), pageCount);
return true;
}
+void SliceAnimations::PageFile::close() {
+ if (_file.isOpen()) {
+ _file.close();
+ }
+}
+
void *SliceAnimations::PageFile::loadPage(uint32 pageNumber) {
if (_pageOffsets[pageNumber] == -1)
return nullptr;
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
index edc0684140..0732e596ea 100644
--- a/engines/bladerunner/slice_animations.h
+++ b/engines/bladerunner/slice_animations.h
@@ -64,13 +64,15 @@ class SliceAnimations {
};
struct PageFile {
+ int _fileNumber;
SliceAnimations *_sliceAnimations;
Common::File _file;
Common::Array<int32> _pageOffsets;
- PageFile(SliceAnimations *sliceAnimations) : _sliceAnimations(sliceAnimations) {}
+ PageFile(SliceAnimations *sliceAnimations) : _sliceAnimations(sliceAnimations), _fileNumber(-1) {}
bool open(const Common::String &name);
+ void close();
void *loadPage(uint32 page);
};
@@ -102,7 +104,7 @@ public:
bool open(const Common::String &name);
bool openCoreAnim();
- bool openHDFrames();
+ bool openFrames(int fileNumber);
Palette &getPalette(int i) { return _palettes[i]; };
void *getFramePtr(uint32 animation, uint32 frame);
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 15633f6581..31da697c20 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -122,7 +122,7 @@ Matrix3x2 SliceRenderer::calculateFacingRotationMatrix() {
float s = sinf(dir);
float c = cosf(dir);
- Matrix3x2 mRotation( c, -s, 0.0f,
+ Matrix3x2 mRotation(c, -s, 0.0f,
s, c, 0.0f);
Matrix3x2 mView(_view->_sliceViewMatrix(0,0), _view->_sliceViewMatrix(0,1), 0.0f,
@@ -164,29 +164,20 @@ void SliceRenderer::calculateBoundingRect() {
Matrix3x2 mScale(_frameScale.x, 0.0f, 0.0f,
0.0f, _frameScale.y, 0.0f);
- _modelMatrix = mProjection * (facingRotation * (mOffset * mScale));
+ _mvpMatrix = mProjection * (facingRotation * (mOffset * mScale));
Vector4 startScreenVector(
- _view->_viewportPosition.x + top.x / top.z * _view->_viewportPosition.z,
- _view->_viewportPosition.y + top.y / top.z * _view->_viewportPosition.z,
+ _view->_viewportPosition.x + (top.x / top.z) * _view->_viewportPosition.z,
+ _view->_viewportPosition.y + (top.y / top.z) * _view->_viewportPosition.z,
1.0f / top.z,
_frameSliceCount * (1.0f / top.z));
Vector4 endScreenVector(
- _view->_viewportPosition.x + bottom.x / bottom.z * _view->_viewportPosition.z,
- _view->_viewportPosition.y + bottom.y / bottom.z * _view->_viewportPosition.z,
+ _view->_viewportPosition.x + (bottom.x / bottom.z) * _view->_viewportPosition.z,
+ _view->_viewportPosition.y + (bottom.y / bottom.z) * _view->_viewportPosition.z,
1.0f / bottom.z,
0.0f);
- _startScreenVector.x = startScreenVector.x;
- _startScreenVector.y = startScreenVector.y;
- _startScreenVector.z = startScreenVector.z;
- _endScreenVector.x = endScreenVector.x;
- _endScreenVector.y = endScreenVector.y;
- _endScreenVector.z = endScreenVector.z;
- _startSlice = startScreenVector.w;
- _endSlice = endScreenVector.w;
-
Vector4 delta = endScreenVector - startScreenVector;
if (delta.y == 0.0f) {
@@ -197,60 +188,68 @@ void SliceRenderer::calculateBoundingRect() {
* Calculate min and max Y
*/
- float screenMinY = 0.0f;
- float screenMaxY = 479.0f;
+ float screenTop = 0.0f;
+ float screenBottom = 479.0f;
- if (startScreenVector.y < screenMinY) {
- if (endScreenVector.y < screenMinY)
+ if (startScreenVector.y < screenTop) {
+ if (endScreenVector.y < screenTop) {
return;
-
- float f = (screenMinY - startScreenVector.y) / delta.y;
+ }
+ float f = (screenTop - startScreenVector.y) / delta.y;
startScreenVector = startScreenVector + f * delta;
- } else if (startScreenVector.y > screenMaxY) {
- if (endScreenVector.y >= screenMaxY)
+ } else if (startScreenVector.y > screenBottom) {
+ if (endScreenVector.y >= screenBottom) {
return;
-
- float f = (screenMaxY - startScreenVector.y) / delta.y;
+ }
+ float f = (screenBottom - startScreenVector.y) / delta.y;
startScreenVector = startScreenVector + f * delta;
}
- if (endScreenVector.y < screenMinY) {
- float f = (screenMinY - endScreenVector.y) / delta.y;
+ if (endScreenVector.y < screenTop) {
+ float f = (screenTop - endScreenVector.y) / delta.y;
endScreenVector = endScreenVector + f * delta;
- } else if (endScreenVector.y > screenMaxY) {
- float f = (screenMaxY - endScreenVector.y) / delta.y;
+ } else if (endScreenVector.y > screenBottom) {
+ float f = (screenBottom - endScreenVector.y) / delta.y;
endScreenVector = endScreenVector + f * delta;
}
- int bbox_min_y = (int)MIN(startScreenVector.y, endScreenVector.y);
- int bbox_max_y = (int)MAX(startScreenVector.y, endScreenVector.y) + 1;
+ _screenRectangle.top = (int)MIN(startScreenVector.y, endScreenVector.y);
+ _screenRectangle.bottom = (int)MAX(startScreenVector.y, endScreenVector.y) + 1;
/*
* Calculate min and max X
*/
- Matrix3x2 mB6 = _modelMatrix + Vector2(startScreenVector.x, 25.5f / startScreenVector.z);
- Matrix3x2 mC2 = _modelMatrix + Vector2(endScreenVector.x, 25.5f / endScreenVector.z);
+ Matrix3x2 mStart(
+ 1.0f, 0.0f, startScreenVector.x,
+ 0.0f, 1.0f, 25.5f / startScreenVector.z
+ );
- float min_x = 640.0f;
- float max_x = 0.0f;
+ Matrix3x2 mEnd(
+ 1.0f, 0.0f, endScreenVector.x,
+ 0.0f, 1.0f, 25.5f / endScreenVector.z
+ );
- for (float i = 0.0f; i <= 256.0f; i += 255.0f) {
- for (float j = 0.0f; j <= 256.0f; j += 255.0f) {
- Vector2 v1 = mB6 * Vector2(i, j);
+ Matrix3x2 mStartMVP = mStart * _mvpMatrix;
+ Matrix3x2 mEndMVP = mEnd * _mvpMatrix;
- min_x = MIN(min_x, v1.x);
- max_x = MAX(max_x, v1.x);
+ float minX = 640.0f;
+ float maxX = 0.0f;
- Vector2 v2 = mC2 * Vector2(i, j);
+ for (float i = 0.0f; i <= 256.0f; i += 255.0f) {
+ for (float j = 0.0f; j <= 256.0f; j += 255.0f) {
+ Vector2 v1 = mStartMVP * Vector2(i, j);
+ minX = MIN(minX, v1.x);
+ maxX = MAX(maxX, v1.x);
- min_x = MIN(min_x, v2.x);
- max_x = MAX(max_x, v2.x);
+ Vector2 v2 = mEndMVP * Vector2(i, j);
+ minX = MIN(minX, v2.x);
+ maxX = MAX(maxX, v2.x);
}
}
- int bbox_min_x = CLIP((int)min_x, 0, 640);
- int bbox_max_x = CLIP((int)max_x + 1, 0, 640);
+ _screenRectangle.left = CLIP((int)minX, 0, 640);
+ _screenRectangle.right = CLIP((int)maxX + 1, 0, 640);
_startScreenVector.x = startScreenVector.x;
_startScreenVector.y = startScreenVector.y;
@@ -260,11 +259,6 @@ void SliceRenderer::calculateBoundingRect() {
_endScreenVector.z = endScreenVector.z;
_startSlice = startScreenVector.w;
_endSlice = endScreenVector.w;
-
- _screenRectangle.left = bbox_min_x;
- _screenRectangle.right = bbox_max_x;
- _screenRectangle.top = bbox_min_y;
- _screenRectangle.bottom = bbox_max_y;
}
void SliceRenderer::loadFrame(int animation, int frame) {
@@ -285,7 +279,8 @@ void SliceRenderer::loadFrame(int animation, int frame) {
}
struct SliceLineIterator {
- int _sliceMatrix[2][3];
+ // int _sliceMatrix[2][3];
+ Matrix3x2 _sliceMatrix;
int _startY;
int _endY;
@@ -316,8 +311,9 @@ void SliceLineIterator::setup(
float size = endScreenY - startScreenY;
- if (size <= 0.0f || startScreenZ <= 0.0f)
+ if (size <= 0.0f || startScreenZ <= 0.0f) {
_currentY = _endY + 1;
+ }
_currentZ = startScreenZ;
_stepZ = (endScreenZ - startScreenZ) / size;
@@ -328,7 +324,7 @@ void SliceLineIterator::setup(
_currentX = startScreenX;
_stepX = (endScreenX - startScreenX) / size;
- _field_38 = (int)((25.5f / size) * (1.0f / endScreenZ - 1.0f / startScreenZ) * 64.0);
+ _field_38 = (int)((25.5f / size) * (1.0f / endScreenZ - 1.0f / startScreenZ) * 64.0f);
_currentY = _startY;
float offsetX = _currentX;
@@ -342,9 +338,7 @@ void SliceLineIterator::setup(
m = scale_matrix * (translate_matrix * m);
- for (int r = 0; r != 2; ++r)
- for (int c = 0; c != 3; ++c)
- _sliceMatrix[r][c] = m(r, c);
+ _sliceMatrix = m;
}
float SliceLineIterator::line() {
@@ -364,8 +358,8 @@ void SliceLineIterator::advance() {
_currentSlice += _stepSlice;
_currentX += _stepX;
_currentY += 1;
- _sliceMatrix[0][2] += (int)(65536.0f * _stepX);
- _sliceMatrix[1][2] += _field_38;
+ _sliceMatrix._m[0][2] += (int)(65536.0f * _stepX);
+ _sliceMatrix._m[1][2] += _field_38;
}
static void setupLookupTable(int t[256], int inc) {
@@ -393,7 +387,7 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
_endScreenVector.x, _endScreenVector.y, _endScreenVector.z,
_startScreenVector.x, _startScreenVector.y, _startScreenVector.z,
_endSlice, _startSlice,
- _modelMatrix
+ _mvpMatrix
);
SliceRendererLights sliceRendererLights = SliceRendererLights(_lights);
@@ -424,12 +418,12 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
_setEffectColor.g = setEffectColor.g * 31.0f * 65536.0f;
_setEffectColor.b = setEffectColor.b * 31.0f * 65536.0f;
- setupLookupTable(_m11lookup, sliceLineIterator._sliceMatrix[0][0]);
- setupLookupTable(_m12lookup, sliceLineIterator._sliceMatrix[0][1]);
- _m13 = sliceLineIterator._sliceMatrix[0][2];
- setupLookupTable(_m21lookup, sliceLineIterator._sliceMatrix[1][0]);
- setupLookupTable(_m22lookup, sliceLineIterator._sliceMatrix[1][1]);
- _m23 = sliceLineIterator._sliceMatrix[1][2];
+ setupLookupTable(_m12lookup, sliceLineIterator._sliceMatrix(0, 1));
+ setupLookupTable(_m11lookup, sliceLineIterator._sliceMatrix(0, 0));
+ _m13 = sliceLineIterator._sliceMatrix(0, 2);
+ setupLookupTable(_m21lookup, sliceLineIterator._sliceMatrix(1, 0));
+ setupLookupTable(_m22lookup, sliceLineIterator._sliceMatrix(1, 1));
+ _m23 = sliceLineIterator._sliceMatrix(1, 2);
if (_animationsShadowEnabled[_animation]) {
float coeficientShadow;
@@ -545,8 +539,9 @@ void SliceRenderer::drawOnScreen(int animationId, int animationFrame, int screen
}
void SliceRenderer::drawSlice(int slice, bool advanced, uint16 *frameLinePtr, uint16 *zbufLinePtr, int y) {
- if (slice < 0 || (uint32)slice >= _frameSliceCount)
+ if (slice < 0 || (uint32)slice >= _frameSliceCount) {
return;
+ }
SliceAnimations::Palette &palette = _vm->_sliceAnimations->getPalette(_framePaletteIndex);
@@ -714,7 +709,12 @@ void SliceRenderer::drawShadowPolygon(int transparency, Graphics::Surface &surfa
yMax = CLIP(yMax, 0, 480);
yMin = CLIP(yMin, 0, 480);
- int ditheringFactor[] = { 0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5 };
+ int ditheringFactor[] = {
+ 0, 8, 2, 10,
+ 12, 4, 14, 6,
+ 3, 11, 1, 9,
+ 15, 7, 13, 5
+ };
for (int y = yMin; y < yMax; ++y) {
int xMin = CLIP(polygonLeft[y], 0, 640);
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index d2de61e279..2e3617162c 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -67,7 +67,7 @@ class SliceRenderer {
uint32 _framePaletteIndex;
uint32 _frameSliceCount;
- Matrix3x2 _modelMatrix;
+ Matrix3x2 _mvpMatrix;
Vector3 _startScreenVector;
Vector3 _endScreenVector;
float _startSlice;
diff --git a/engines/bladerunner/text_resource.cpp b/engines/bladerunner/text_resource.cpp
index 2a4840c833..8f54f8a976 100644
--- a/engines/bladerunner/text_resource.cpp
+++ b/engines/bladerunner/text_resource.cpp
@@ -46,11 +46,11 @@ TextResource::~TextResource() {
bool TextResource::open(const Common::String &name) {
assert(name.size() <= 8);
- char resName[13];
- sprintf(resName, "%s.TR%s", name.c_str(), _vm->_languageCode);
+ Common::String resName = Common::String::format("%s.TR%s", name.c_str(), _vm->_languageCode.c_str());
Common::ScopedPtr<Common::SeekableReadStream> s(_vm->getResourceStream(resName));
- if (!s)
+ if (!s) {
return false;
+ }
_count = s->readUint32LE();
diff --git a/engines/bladerunner/time.cpp b/engines/bladerunner/time.cpp
new file mode 100644
index 0000000000..a395a811d1
--- /dev/null
+++ b/engines/bladerunner/time.cpp
@@ -0,0 +1,68 @@
+/* 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 "bladerunner/time.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/timer.h"
+
+namespace BladeRunner {
+
+Time::Time(BladeRunnerEngine *vm) {
+ _vm = vm;
+
+ _start = _vm->getTotalPlayTime();
+ _pauseCount = 0;
+ _offset = 0;
+ _pauseStart = 0;
+}
+
+int Time::current() {
+ int time = _vm->getTotalPlayTime() - _offset;
+ return time - _start;
+}
+
+int Time::pause() {
+ if (_pauseCount == 0) {
+ _pauseStart = current();
+ }
+ return ++_pauseCount;
+}
+
+int Time::getPauseStart() {
+ return _pauseStart;
+}
+
+int Time::unpause() {
+ assert(_pauseCount > 0);
+ if (--_pauseCount == 0) {
+ _offset += current() - _pauseStart;
+ }
+ return _pauseCount;
+}
+
+bool Time::isLocked() {
+ return _pauseCount > 0;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/time.h b/engines/bladerunner/time.h
new file mode 100644
index 0000000000..bda8c84d14
--- /dev/null
+++ b/engines/bladerunner/time.h
@@ -0,0 +1,50 @@
+/* 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 BLADERUNNER_TIME_H
+#define BLADERUNNER_TIME_H
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class Time {
+ BladeRunnerEngine *_vm;
+
+ int _start;
+ int _pauseCount;
+ int _offset;
+ int _pauseStart;
+
+public:
+ Time(BladeRunnerEngine *vm);
+
+ int current();
+ int pause();
+ int getPauseStart();
+ int unpause();
+ bool isLocked();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/elevator.cpp b/engines/bladerunner/ui/elevator.cpp
index 3f668efd75..7a6ab3ca35 100644
--- a/engines/bladerunner/ui/elevator.cpp
+++ b/engines/bladerunner/ui/elevator.cpp
@@ -315,8 +315,7 @@ void Elevator::mouseOutCallback(int, void *self) {
void Elevator::mouseDownCallback(int, void *self) {
Elevator *elevator = ((Elevator *)self);
- const char *name = elevator->_vm->_gameInfo->getSfxTrack(515);
- elevator->_vm->_audioPlayer->playAud(name, 100, 0, 0, 50, 0);
+ elevator->_vm->_audioPlayer->playAud(elevator->_vm->_gameInfo->getSfxTrack(515), 100, 0, 0, 50, 0);
}
void Elevator::mouseUpCallback(int buttonId, void *self) {
diff --git a/engines/bladerunner/ui/end_credits.cpp b/engines/bladerunner/ui/end_credits.cpp
new file mode 100644
index 0000000000..6d964d0290
--- /dev/null
+++ b/engines/bladerunner/ui/end_credits.cpp
@@ -0,0 +1,170 @@
+/* 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/rect.h"
+
+#include "audio/mixer.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/ambient_sounds.h"
+#include "bladerunner/audio_speech.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/mouse.h"
+#include "bladerunner/music.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/ui/end_credits.h"
+
+namespace BladeRunner {
+
+EndCredits::EndCredits(BladeRunnerEngine *vm) {
+ _vm = vm;
+}
+
+EndCredits::~EndCredits() {
+}
+
+void EndCredits::show() {
+ _vm->_mouse->disable();
+ _vm->_mixer->stopAll();
+ _vm->_ambientSounds->removeAllNonLoopingSounds(true);
+ _vm->_ambientSounds->removeAllLoopingSounds(4);
+ _vm->_audioSpeech->stopSpeech();
+
+ _vm->_music->play(_vm->_gameInfo->getMusicTrack(17), 100, 0, 2, -1, 0, 3);
+
+ Font *fontBig = new Font(_vm);
+ fontBig->open("TAHOMA24.FON", 640, 480, -1, 0, 0);
+ fontBig->setSpacing(1, 0);
+
+ Font *fontSmall = new Font(_vm);
+ fontSmall->open("TAHOMA18.FON", 640, 480, -1, 0, 0);
+ fontSmall->setSpacing(1, 0);
+
+ TextResource *textResource = new TextResource(_vm);
+ textResource->open("ENDCRED");
+
+ int textCount = textResource->getCount();
+ int *textPositions = (int *)malloc(textCount * sizeof(int));
+ int y = 452;
+ bool small = false;
+
+ for (int i = 0; i < textCount; i++) {
+ Common::String s = textResource->getText(i);
+ if (s.hasPrefix("^")) {
+ if (!small) {
+ y += 28;
+ }
+ small = false;
+ } else {
+ if (small) {
+ y += 24;
+ } else {
+ y += 28;
+ }
+ small = true;
+ }
+ if (s.hasPrefix("^")) {
+ textPositions[i] = y;
+ } else {
+ textPositions[i] = y + 2;
+ }
+ }
+
+ _vm->_vqaIsPlaying = true;
+ _vm->_vqaStopIsRequested = false;
+
+ double position = 0.0;
+ uint32 timeLast = _vm->getTotalPlayTime();
+
+ while (!_vm->_vqaStopIsRequested && !_vm->shouldQuit()) {
+ if (position >= textPositions[textCount - 1]) {
+ break;
+ }
+
+ //soundSystem::tick(SoundSystem);
+ _vm->handleEvents();
+
+ if (!_vm->_gameIsRunning) {
+ timeLast = _vm->getTotalPlayTime();
+
+ continue;
+ }
+
+ uint32 timeNow = _vm->getTotalPlayTime();
+ position += (double)(timeNow - timeLast) * 0.05f;
+ timeLast = timeNow;
+
+ _vm->_surfaceFront.fillRect(Common::Rect(640, 480), 0);
+
+ for (int i = 0; i < textCount; i++) {
+ Common::String s = textResource->getText(i);
+ Font *font;
+ int height;
+
+ if (s.hasPrefix("^")) {
+ font = fontBig;
+ height = 28;
+ s.deleteChar(0);
+ } else {
+ font = fontSmall;
+ height = 24;
+ }
+
+ y = textPositions[i] - (int)position;
+
+ if (y < 452 && y + height > 28) {
+ int x;
+
+ if (font == fontBig) {
+ x = 280;
+ } else {
+ x = 270 - font->getTextWidth(s);
+ }
+
+ font->draw(s, _vm->_surfaceFront, x, y);
+ }
+ }
+
+ _vm->_surfaceFront.fillRect(Common::Rect(0, 0, 640, 28), 0);
+ _vm->_surfaceFront.fillRect(Common::Rect(0, 452, 640, 480), 0);
+
+ _vm->blitToScreen(_vm->_surfaceFront);
+
+ _vm->_system->delayMillis(10);
+ }
+
+ _vm->_vqaIsPlaying = false;
+ _vm->_vqaStopIsRequested = false;
+
+ free(textPositions);
+ delete textResource;
+
+ delete fontSmall;
+ delete fontBig;
+
+ _vm->_music->stop(0);
+ _vm->_mouse->enable();
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/end_credits.h b/engines/bladerunner/ui/end_credits.h
new file mode 100644
index 0000000000..39086cd796
--- /dev/null
+++ b/engines/bladerunner/ui/end_credits.h
@@ -0,0 +1,42 @@
+/* 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 BLADERUNNER_UI_END_CREDITS_H
+#define BLADERUNNER_UI_END_CREDITS_H
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class EndCredits {
+ BladeRunnerEngine *_vm;
+
+public:
+ EndCredits(BladeRunnerEngine *vm);
+ ~EndCredits();
+
+ void show();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/kia.cpp b/engines/bladerunner/ui/kia.cpp
index 86fdc9254a..756f1bd2cd 100644
--- a/engines/bladerunner/ui/kia.cpp
+++ b/engines/bladerunner/ui/kia.cpp
@@ -350,7 +350,7 @@ void KIA::tick() {
_shapes->get(47)->draw(_vm->_surfaceFront, 182, 446);
}
}
- _vm->_mainFont->drawColor("1.00", _vm->_surfaceFront, 438, 471, 0x1CE7);
+ _vm->_mainFont->drawColor("1.00", _vm->_surfaceFront, 438, 471, 0x1CE7); // TODO: 1.01 for DVD version
if (!_transitionId) {
_buttons->drawTooltip(_vm->_surfaceFront, mouse.x, mouse.y);
}
diff --git a/engines/bladerunner/ui/kia_log.cpp b/engines/bladerunner/ui/kia_log.cpp
index 51b922a8f7..7f75f2e944 100644
--- a/engines/bladerunner/ui/kia_log.cpp
+++ b/engines/bladerunner/ui/kia_log.cpp
@@ -55,7 +55,7 @@ void KIALog::add(int type, int dataSize, const void *data) {
_entries[_currentIndex].dataSize = dataSize;
if (dataSize > 0) {
- char *dataCopy = new char[dataSize];
+ unsigned char *dataCopy = new unsigned char[dataSize];
memcpy(dataCopy, data, dataSize);
_entries[_currentIndex].data = dataCopy;
} else {
diff --git a/engines/bladerunner/ui/kia_log.h b/engines/bladerunner/ui/kia_log.h
index 4a89492817..99c834e3f0 100644
--- a/engines/bladerunner/ui/kia_log.h
+++ b/engines/bladerunner/ui/kia_log.h
@@ -33,7 +33,7 @@ class KIALog {
struct Entry {
int type;
int dataSize;
- const char *data;
+ const unsigned char *data;
};
BladeRunnerEngine *_vm;
diff --git a/engines/bladerunner/ui/scores.cpp b/engines/bladerunner/ui/scores.cpp
new file mode 100644
index 0000000000..c4a7df778c
--- /dev/null
+++ b/engines/bladerunner/ui/scores.cpp
@@ -0,0 +1,218 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/ui/scores.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/font.h"
+#include "bladerunner/savefile.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/vqa_player.h"
+
+#include "common/keyboard.h"
+
+namespace BladeRunner {
+
+Scores::Scores(BladeRunnerEngine *vm) {
+ _vm = vm;
+
+ _font = nullptr;
+ _txtScorers = nullptr;
+
+ reset();
+}
+
+Scores::~Scores() {
+}
+
+void Scores::open() {
+ if (!_vm->openArchive("MODE.MIX")) {
+ return;
+ }
+
+ _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack);
+
+ if (!_vqaPlayer->open("SCORE.VQA")) {
+ return;
+ }
+
+ _vqaPlayer->setLoop(1, -1, 0, nullptr, nullptr);
+
+ // TODO: Freeze game time
+
+ _txtScorers = new TextResource(_vm);
+ _txtScorers->open("SCORERS");
+
+ _font = new Font(_vm);
+ _font->open("TAHOMA24.FON", 640, 480, -1, 0, 0);
+ _font->setSpacing(1, 0);
+
+ fill();
+
+ _isOpen = true;
+ _isLoaded = false;
+}
+
+bool Scores::isOpen() const {
+ return _isOpen;
+}
+
+void Scores::close() {
+ _isOpen = false;
+
+ delete _font;
+ _font = nullptr;
+
+ delete _txtScorers;
+ _txtScorers = nullptr;
+
+ if (_vqaPlayer) {
+ _vqaPlayer->close();
+ delete _vqaPlayer;
+ _vqaPlayer = nullptr;
+ }
+
+ _vm->closeArchive("MODE.MIX");
+
+ // TODO: Unfreeze game time
+ _vm->_scene->resume();
+}
+
+void Scores::set(int index, int value) {
+ if (value > _scores[index]) {
+ _scores[index] = value;
+ }
+
+ _lastScoreId = index;
+ _lastScoreValue = value;
+}
+
+void Scores::handleKeyDown(const Common::KeyState &kbd) {
+ close();
+}
+
+int Scores::handleMouseUp(int x, int y) {
+ if (_isLoaded) {
+ close();
+ }
+
+ _isLoaded = false;
+
+ return false;
+}
+
+int Scores::handleMouseDown(int x, int y) {
+ _isLoaded = true;
+
+ return false;
+}
+
+void Scores::tick() {
+ if (!_vm->_gameIsRunning) {
+ return;
+ }
+
+ int frame = _vqaPlayer->update();
+ assert(frame >= -1);
+
+ // vqaPlayer renders to _surfaceBack
+ blit(_vm->_surfaceBack, _vm->_surfaceFront);
+
+ _vm->_surfaceFront.hLine(200, 139, 400, 0x3e0);
+ _vm->_surfaceFront.hLine(200, 347, 400, 0x1f);
+
+ _font->draw(_txtScorers->getText(7), _vm->_surfaceFront, 200, 114);
+
+ int y = 140;
+
+ for (int i = 0; i < 7; i++) {
+ _font->draw(_txtScorers->getText(_scorers[i]), _vm->_surfaceFront, 220, y);
+ _font->drawNumber(_scores[_scorers[i]], _vm->_surfaceFront, 360, y);
+
+ y += 26;
+ }
+
+ _font->draw(_txtScorers->getText(8), _vm->_surfaceFront, 200, 322);
+ _font->draw(_txtScorers->getText(_lastScoreId), _vm->_surfaceFront, 220, 348);
+ _font->drawNumber(_lastScoreValue, _vm->_surfaceFront, 360, 348);
+
+ _vm->blitToScreen(_vm->_surfaceFront);
+}
+
+void Scores::fill() {
+ for (int i = 0; i < 7; i++) {
+ _scorers[i] = i;
+ }
+
+ // Network sorting using Bose-Nelson Algorithm
+ const byte network[32] = { // Bose-Nelson
+ 1,2, 3,4, 5,6,
+ 0,2, 3,5, 4,6,
+ 0,1, 4,5, 2,6,
+ 0,4, 1,5,
+ 0,3, 2,5,
+ 1,3, 2,4,
+ 2,3
+ };
+
+ for (int i = 0; i < 32; i += 2) {
+ int i1 = network[i], i2 = network[i + 1];
+ if (_scores[_scorers[i1]] < _scores[_scorers[i2]]) {
+ SWAP(_scorers[i1], _scorers[i2]);
+ }
+ }
+}
+
+void Scores::reset() {
+ _isOpen = false;
+ _isLoaded = false;
+ _vqaPlayer = nullptr;
+
+ for (int i = 0; i < 7; i++) {
+ _scores[i] = -80;
+ _scorers[i] = 0;
+ }
+
+ _lastScoreId = 0;
+ _lastScoreValue = 0;
+}
+
+void Scores::save(SaveFileWriteStream &f) {
+ for (int i = 0; i < 7; i++) {
+ f.writeInt(_scores[i]);
+ }
+
+ f.writeInt(_lastScoreId);
+ f.writeInt(_lastScoreValue);
+}
+
+void Scores::load(SaveFileReadStream &f) {
+ for (int i = 0; i < 7; i++) {
+ _scores[i] = f.readInt();
+ }
+
+ _lastScoreId = f.readInt();
+ _lastScoreValue = f.readInt();
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/scores.h b/engines/bladerunner/ui/scores.h
new file mode 100644
index 0000000000..80fd409675
--- /dev/null
+++ b/engines/bladerunner/ui/scores.h
@@ -0,0 +1,82 @@
+/* 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 BLADERUNNER_SCORES_H
+#define BLADERUNNER_SCORES_H
+
+#include "common/array.h"
+
+namespace Common {
+struct KeyState;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class Font;
+class Shape;
+class SaveFileReadStream;
+class SaveFileWriteStream;
+class TextResource;
+class VQAPlayer;
+class UIImagePicker;
+
+class Scores {
+ BladeRunnerEngine *_vm;
+ bool _isOpen;
+ bool _isLoaded;
+ VQAPlayer *_vqaPlayer;
+ int _scores[7];
+ int _scorers[7];
+
+ int _lastScoreId;
+ int _lastScoreValue;
+
+ Font *_font;
+ TextResource *_txtScorers;
+
+public:
+ Scores(BladeRunnerEngine *vm);
+ ~Scores();
+
+ void open();
+ bool isOpen() const;
+ void close();
+
+ int query(int index) { return _scores[index]; }
+ void set(int index, int value);
+
+ void handleKeyDown(const Common::KeyState &kbd);
+ int handleMouseUp(int x, int y);
+ int handleMouseDown(int x, int y);
+
+ void tick();
+ void fill();
+
+ void reset();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/ui/spinner.cpp b/engines/bladerunner/ui/spinner.cpp
index 0740715fc4..9e491f719c 100644
--- a/engines/bladerunner/ui/spinner.cpp
+++ b/engines/bladerunner/ui/spinner.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/bladerunner.h"
#include "bladerunner/game_constants.h"
#include "bladerunner/mouse.h"
+#include "bladerunner/savefile.h"
#include "bladerunner/scene.h"
#include "bladerunner/shape.h"
#include "bladerunner/text_resource.h"
@@ -262,6 +263,20 @@ void Spinner::resume() {
_vqaPlayer->setLoop(1, -1, kLoopSetModeJustStart, nullptr, nullptr);
}
+void Spinner::save(SaveFileWriteStream &f) {
+ assert(!_isOpen);
+
+ for (int i = 0; i != kSpinnerDestinations; ++i) {
+ f.writeBool(_isDestinationSelectable[i]);
+ }
+}
+
+void Spinner::load(SaveFileReadStream &f) {
+ for (int i = 0; i != kSpinnerDestinations; ++i) {
+ _isDestinationSelectable[i] = f.readBool();
+ }
+}
+
const Spinner::Destination *Spinner::getDestinationsFar() {
static const Destination destinations[] = {
{ 0, Common::Rect(220, 227, 246, 262) },
diff --git a/engines/bladerunner/ui/spinner.h b/engines/bladerunner/ui/spinner.h
index b1785a57eb..d2d666e8e1 100644
--- a/engines/bladerunner/ui/spinner.h
+++ b/engines/bladerunner/ui/spinner.h
@@ -29,9 +29,11 @@
namespace BladeRunner {
class BladeRunnerEngine;
+class SaveFileReadStream;
+class SaveFileWriteStream;
class Shape;
-class VQAPlayer;
class UIImagePicker;
+class VQAPlayer;
class Spinner {
static const int kSpinnerDestinations = 10;
@@ -70,6 +72,9 @@ public:
void reset();
void resume();
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
+
private:
static void mouseUpCallback(int, void *);
static const Destination *getDestinationsFar();
diff --git a/engines/bladerunner/ui/ui_scroll_box.cpp b/engines/bladerunner/ui/ui_scroll_box.cpp
index 6bd4dabdd4..a030e534c5 100644
--- a/engines/bladerunner/ui/ui_scroll_box.cpp
+++ b/engines/bladerunner/ui/ui_scroll_box.cpp
@@ -481,7 +481,7 @@ void UIScrollBox::draw(Graphics::Surface &surface) {
}
if (_center) {
- x = (_rect.width() - _vm->_mainFont->getTextWidth(_lines[i]->text)) / 2;
+ x = _rect.left + (_rect.width() - _vm->_mainFont->getTextWidth(_lines[i]->text)) / 2;
}
_vm->_mainFont->drawColor(_lines[i]->text, surface, x, y, color);
@@ -490,8 +490,7 @@ void UIScrollBox::draw(Graphics::Surface &surface) {
y2 += kLineHeight;
y += kLineHeight;
++i;
- }
- while (i < lastLineVisible);
+ } while (i < lastLineVisible);
}
// draw scroll up button
diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h
index f3cc1f1e6d..22ef5cd839 100644
--- a/engines/bladerunner/vector.h
+++ b/engines/bladerunner/vector.h
@@ -37,6 +37,14 @@ public:
Vector2(float ax, float ay) : x(ax), y(ay) {}
};
+inline bool operator==(const Vector2 &a, const Vector2 &b) {
+ return a.x == b.x && a.y == b.y;
+}
+
+inline bool operator!=(const Vector2 &a, const Vector2 &b) {
+ return !(a == b);
+}
+
class Vector3 {
public:
float x;
@@ -132,6 +140,10 @@ inline float distance(float x1, float z1, float x2, float z2) {
return int_part + frac_part;
}
+inline float distance(const Vector2 &v1, const Vector2 &v2) {
+ return distance(v1.x, v1.y, v2.x, v2.y);
+}
+
inline float distance(const Vector3 &v1, const Vector3 &v2) {
return distance(v1.x, v1.z, v2.x, v2.z);
}
diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp
index d304b92bb1..72c070ecc0 100644
--- a/engines/bladerunner/view.cpp
+++ b/engines/bladerunner/view.cpp
@@ -31,8 +31,9 @@ bool View::readVqa(Common::ReadStream *stream) {
_frame = stream->readUint32LE();
float d[12];
- for (int i = 0; i != 12; ++i)
+ for (int i = 0; i != 12; ++i) {
d[i] = stream->readFloatLE();
+ }
_frameViewMatrix = Matrix4x3(d);
@@ -54,17 +55,11 @@ void View::setFovX(float fovX) {
}
void View::calculateSliceViewMatrix() {
- Matrix4x3 m = _frameViewMatrix;
-
- m = m * rotationMatrixX(float(M_PI) / 2.0f);
-
- Matrix4x3 a(-1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, -1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f);
-
- m = a * m;
-
- _sliceViewMatrix = m;
+ Matrix4x3 mRotation = rotationMatrixX(float(M_PI) / 2.0f);
+ Matrix4x3 mInvert(-1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f);
+ _sliceViewMatrix = mInvert * (_frameViewMatrix * mRotation);
}
void View::calculateCameraPosition() {
diff --git a/engines/bladerunner/waypoints.cpp b/engines/bladerunner/waypoints.cpp
index 4d80841e50..bf2f09b8a6 100644
--- a/engines/bladerunner/waypoints.cpp
+++ b/engines/bladerunner/waypoints.cpp
@@ -22,6 +22,8 @@
#include "bladerunner/waypoints.h"
+#include "bladerunner/savefile.h"
+
namespace BladeRunner {
Waypoints::Waypoints(BladeRunnerEngine *vm, int count) {
@@ -89,4 +91,24 @@ float Waypoints::getZ(int waypointId) const {
return _waypoints[waypointId].position.z;
}
+void Waypoints::save(SaveFileWriteStream &f) {
+ f.writeInt(_count);
+ for (int i = 0; i < _count; ++i) {
+ Waypoint &w = _waypoints[i];
+ f.writeInt(w.setId);
+ f.writeVector3(w.position);
+ f.writeInt(w.present);
+ }
+}
+
+void Waypoints::load(SaveFileReadStream &f) {
+ _count = f.readInt();
+ for (int i = 0; i < _count; ++i) {
+ Waypoint &w = _waypoints[i];
+ w.setId = f.readInt();
+ w.position = f.readVector3();
+ w.present = f.readInt();
+ }
+}
+
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/waypoints.h b/engines/bladerunner/waypoints.h
index 826f8f5a94..6bbe8d3db4 100644
--- a/engines/bladerunner/waypoints.h
+++ b/engines/bladerunner/waypoints.h
@@ -30,6 +30,9 @@
namespace BladeRunner {
+class SaveFileReadStream;
+class SaveFileWriteStream;
+
class Waypoints {
friend class Debugger;
@@ -55,6 +58,9 @@ public:
bool set(int waypointId, int setId, Vector3 position);
bool reset(int waypointId);
+
+ void save(SaveFileWriteStream &f);
+ void load(SaveFileReadStream &f);
};
} // End of namespace BladeRunner
diff --git a/engines/cge/cge.h b/engines/cge/cge.h
index d3f8a93c1d..9a8ea0dde9 100644
--- a/engines/cge/cge.h
+++ b/engines/cge/cge.h
@@ -56,7 +56,7 @@ class Walk;
class Text;
class Talk;
-#define kSavegameVersion 2
+#define kSavegameVersion 3
#define kSavegameStrSize 11
#define kPocketX 174
#define kPocketY 176
@@ -99,8 +99,9 @@ struct SavegameHeader {
uint8 version;
Common::String saveName;
Graphics::Surface *thumbnail;
- int saveYear, saveMonth, saveDay;
- int saveHour, saveMinutes;
+ int16 saveYear, saveMonth, saveDay;
+ int16 saveHour, saveMinutes;
+ uint32 playTime;
};
extern const char *savegameStr;
@@ -246,7 +247,7 @@ public:
void mainLoop();
void handleFrame();
void saveGame(int slotNumber, const Common::String &desc);
- static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail = true);
void switchMusic();
void selectPocket(int n);
void expandSprite(Sprite *spr);
diff --git a/engines/cge/cge_main.cpp b/engines/cge/cge_main.cpp
index b60f201cb0..05461e30e1 100644
--- a/engines/cge/cge_main.cpp
+++ b/engines/cge/cge_main.cpp
@@ -243,9 +243,7 @@ bool CGEEngine::loadGame(int slotNumber, SavegameHeader *header, bool tiny) {
return true;
}
- // Delete the thumbnail
- saveHeader.thumbnail->free();
- delete saveHeader.thumbnail;
+ g_engine->setTotalPlayTime(saveHeader.playTime * 1000);
}
// Get in the savegame
@@ -371,6 +369,8 @@ void CGEEngine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &he
out->writeSint16LE(td.tm_mday);
out->writeSint16LE(td.tm_hour);
out->writeSint16LE(td.tm_min);
+
+ out->writeUint32LE(g_engine->getTotalPlayTime() / 1000);
}
void CGEEngine::syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream, bool tiny) {
@@ -424,8 +424,16 @@ void CGEEngine::syncGame(Common::SeekableReadStream *readStream, Common::WriteSt
}
}
-bool CGEEngine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) {
- header.thumbnail = nullptr;
+WARN_UNUSED_RESULT bool CGEEngine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail) {
+ header.version = 0;
+ header.saveName.clear();
+ header.thumbnail = nullptr;
+ header.saveYear = 0;
+ header.saveMonth = 0;
+ header.saveDay = 0;
+ header.saveHour = 0;
+ header.saveMinutes = 0;
+ header.playTime = 0;
// Get the savegame version
header.version = in->readByte();
@@ -433,23 +441,26 @@ bool CGEEngine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &heade
return false;
// Read in the string
- header.saveName.clear();
char ch;
while ((ch = (char)in->readByte()) != '\0')
header.saveName += ch;
// Get the thumbnail
- header.thumbnail = Graphics::loadThumbnail(*in);
- if (!header.thumbnail)
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
- header.saveYear = in->readSint16LE();
- header.saveMonth = in->readSint16LE();
- header.saveDay = in->readSint16LE();
- header.saveHour = in->readSint16LE();
+ header.saveYear = in->readSint16LE();
+ header.saveMonth = in->readSint16LE();
+ header.saveDay = in->readSint16LE();
+ header.saveHour = in->readSint16LE();
header.saveMinutes = in->readSint16LE();
+ if (header.version >= 3) {
+ header.playTime = in->readUint32LE();
+ }
+
return true;
}
diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp
index 482591bf50..f6399d484c 100644
--- a/engines/cge/detection.cpp
+++ b/engines/cge/detection.cpp
@@ -126,7 +126,7 @@ public:
return "Soltys (C) 1994-1996 L.K. Avalon";
}
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
virtual int getMaximumSaveSlot() const;
@@ -135,13 +135,8 @@ public:
virtual void removeSaveState(const char *target, int slot) const;
};
-static const ADFileBasedFallback fileBasedFallback[] = {
- { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } },
- { 0, { 0 } }
-};
-
static ADGameDescription s_fallbackDesc = {
- "Soltys",
+ "soltys",
"Unknown version",
AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
Common::UNK_LANG,
@@ -150,38 +145,40 @@ static ADGameDescription s_fallbackDesc = {
GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
};
-const ADGameDescription *CGEMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- ADFilePropertiesMap filesProps;
+static const ADFileBasedFallback fileBasedFallback[] = {
+ { &s_fallbackDesc, { "vol.cat", "vol.dat", 0 } },
+ { 0, { 0 } }
+};
- const ADGameDescription *game;
- game = detectGameFilebased(allFiles, fslist, CGE::fileBasedFallback, &filesProps);
+ADDetectedGame CGEMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADDetectedGame game = detectGameFilebased(allFiles, fslist, CGE::fileBasedFallback);
- if (!game)
- return nullptr;
+ if (!game.desc)
+ return ADDetectedGame();
SearchMan.addDirectory("CGEMetaEngine::fallbackDetect", fslist.begin()->getParent());
ResourceManager *resman;
resman = new ResourceManager();
- bool result = resman->exist("CGE.SAY");
+ bool sayFileFound = resman->exist("CGE.SAY");
delete resman;
SearchMan.remove("CGEMetaEngine::fallbackDetect");
- if (!result)
- return nullptr;
+ if (!sayFileFound)
+ return ADDetectedGame();
- reportUnknown(fslist.begin()->getParent(), filesProps);
- return &s_fallbackDesc;
+ return game;
}
bool CGEMetaEngine::hasFeature(MetaEngineFeature f) const {
return
- (f == kSupportsListSaves) ||
- (f == kSupportsLoadingDuringStartup) ||
- (f == kSupportsDeleteSave) ||
- (f == kSavesSupportMetaInfo) ||
- (f == kSavesSupportThumbnail) ||
- (f == kSavesSupportCreationDate) ||
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate) ||
+ (f == kSavesSupportPlayTime) ||
(f == kSimpleSavesNames);
}
@@ -221,10 +218,6 @@ SaveStateList CGEMetaEngine::listSaves(const char *target) const {
// Valid savegame
if (CGE::CGEEngine::readSavegameHeader(file, header)) {
saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
- if (header.thumbnail) {
- header.thumbnail->free();
- delete header.thumbnail;
- }
}
} else {
// Must be an original format savegame
@@ -253,7 +246,7 @@ SaveStateDescriptor CGEMetaEngine::querySaveMetaInfos(const char *target, int sl
f->read(buffer, kSavegameStrSize + 1);
bool hasHeader = !strncmp(buffer, CGE::savegameStr, kSavegameStrSize + 1) &&
- CGE::CGEEngine::readSavegameHeader(f, header);
+ CGE::CGEEngine::readSavegameHeader(f, header, false);
delete f;
if (!hasHeader) {
@@ -267,6 +260,10 @@ SaveStateDescriptor CGEMetaEngine::querySaveMetaInfos(const char *target, int sl
desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
desc.setSaveTime(header.saveHour, header.saveMinutes);
+ if (header.playTime) {
+ desc.setPlayTime(header.playTime * 1000);
+ }
+
// Slot 0 is used for the 'automatic save on exit' save in Soltys, thus
// we prevent it from being deleted or overwritten by accident.
desc.setDeletableFlag(slot != 0);
diff --git a/engines/cge/vga13h.cpp b/engines/cge/vga13h.cpp
index 4d3a103663..a7e065fe01 100644
--- a/engines/cge/vga13h.cpp
+++ b/engines/cge/vga13h.cpp
@@ -707,7 +707,7 @@ uint8 Vga::closest(Dac *pal, const uint8 colR, const uint8 colG, const uint8 col
uint16 D = ((r > R) ? (r - R) : (R - r)) +
((g > G) ? (g - G) : (G - g)) +
((b > B) ? (b - B) : (B - b)) +
- ((l > L) ? (l - L) : (L - l)) * 10 ;
+ ((l > L) ? (l - L) : (L - l)) * 10;
if (D < dif) {
found = i;
diff --git a/engines/cge2/cge2.h b/engines/cge2/cge2.h
index 18f919b5eb..1fa23ad6f7 100644
--- a/engines/cge2/cge2.h
+++ b/engines/cge2/cge2.h
@@ -32,12 +32,13 @@
#include "common/savefile.h"
#include "common/serializer.h"
#include "engines/engine.h"
-#include "engines/advancedDetector.h"
#include "common/system.h"
#include "cge2/fileio.h"
#include "cge2/console.h"
#include "audio/mixer.h"
+struct ADGameDescription;
+
namespace CGE2 {
class Vga;
@@ -105,7 +106,7 @@ struct SavegameHeader;
#define kQuitText 201
#define kNoQuitText 202
-#define kSavegameVersion 1
+#define kSavegameVersion 2
#define kSavegameStrSize 12
#define kSavegameStr "SCUMMVM_CGE2"
@@ -115,8 +116,9 @@ struct SavegameHeader {
uint8 version;
Common::String saveName;
Graphics::Surface *thumbnail;
- int saveYear, saveMonth, saveDay;
- int saveHour, saveMinutes;
+ int16 saveYear, saveMonth, saveDay;
+ int16 saveHour, saveMinutes;
+ uint32 playTime;
};
enum ColorBank { kCBRel, kCBStd, kCBSay, kCBInf, kCBMnu, kCBWar };
@@ -161,7 +163,7 @@ public:
virtual Common::Error loadGameState(int slot);
virtual Common::Error run();
- static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail = true);
GUI::Debugger *getDebugger() {
return _console;
diff --git a/engines/cge2/detection.cpp b/engines/cge2/detection.cpp
index d05dfffedc..ec6925ac74 100644
--- a/engines/cge2/detection.cpp
+++ b/engines/cge2/detection.cpp
@@ -62,6 +62,16 @@ static const ADGameDescription gameDescriptions[] = {
},
{
+ "sfinx", "Freeware v1.1",
+ {
+ {"vol.cat", 0, "aa402aed24a72c53a4d1211c456b79dd", 129024},
+ {"vol.dat", 0, "5966ac26d91d664714349669f9dd09b5", 34180367},
+ AD_LISTEND
+ },
+ Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
+ },
+
+ {
"sfinx", "Freeware v0.3",
{
{"vol.cat", 0, "f158e469dccbebc5a632eb848df89779", 129024},
@@ -122,7 +132,7 @@ public:
return "Sfinx (C) 1994-1997 Janus B. Wisniewski and L.K. Avalon";
}
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
virtual bool hasFeature(MetaEngineFeature f) const;
virtual int getMaximumSaveSlot() const;
@@ -131,13 +141,8 @@ public:
virtual void removeSaveState(const char *target, int slot) const;
};
-static const ADFileBasedFallback fileBasedFallback[] = {
- { &gameDescriptions[0], { "vol.cat", "vol.dat", 0 } },
- { 0, { 0 } }
-};
-
static ADGameDescription s_fallbackDesc = {
- "Sfinx",
+ "sfinx",
"Unknown version",
AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
Common::UNK_LANG,
@@ -146,30 +151,31 @@ static ADGameDescription s_fallbackDesc = {
GUIO1(GAMEOPTION_COLOR_BLIND_DEFAULT_OFF)
};
+static const ADFileBasedFallback fileBasedFallback[] = {
+ { &s_fallbackDesc, { "vol.cat", "vol.dat", 0 } },
+ { 0, { 0 } }
+};
+
// This fallback detection looks identical to the one used for CGE. In fact, the difference resides
// in the ResourceManager which handles a different archive format. The rest of the detection is identical.
-const ADGameDescription *CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- ADFilePropertiesMap filesProps;
-
- const ADGameDescription *game;
- game = detectGameFilebased(allFiles, fslist, CGE2::fileBasedFallback, &filesProps);
+ADDetectedGame CGE2MetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADDetectedGame game = detectGameFilebased(allFiles, fslist, CGE2::fileBasedFallback);
- if (!game)
- return 0;
+ if (!game.desc)
+ return ADDetectedGame();
SearchMan.addDirectory("CGE2MetaEngine::fallbackDetect", fslist.begin()->getParent());
ResourceManager *resman;
resman = new ResourceManager();
- bool result = resman->exist("CGE.SAY");
+ bool sayFileFound = resman->exist("CGE.SAY");
delete resman;
SearchMan.remove("CGE2MetaEngine::fallbackDetect");
- if (!result)
- return 0;
+ if (!sayFileFound)
+ return ADDetectedGame();
- reportUnknown(fslist.begin()->getParent(), filesProps);
- return &s_fallbackDesc;
+ return game;
}
bool CGE2MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
@@ -185,6 +191,7 @@ bool CGE2MetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
(f == kSavesSupportCreationDate) ||
+ (f == kSavesSupportPlayTime) ||
(f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
(f == kSimpleSavesNames);
@@ -221,10 +228,6 @@ SaveStateList CGE2MetaEngine::listSaves(const char *target) const {
// Valid savegame
if (CGE2::CGE2Engine::readSavegameHeader(file, header)) {
saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
- if (header.thumbnail) {
- header.thumbnail->free();
- delete header.thumbnail;
- }
}
} else {
// Must be an original format savegame
@@ -253,7 +256,7 @@ SaveStateDescriptor CGE2MetaEngine::querySaveMetaInfos(const char *target, int s
f->read(buffer, kSavegameStrSize + 1);
bool hasHeader = !strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) &&
- CGE2::CGE2Engine::readSavegameHeader(f, header);
+ CGE2::CGE2Engine::readSavegameHeader(f, header, false);
delete f;
if (!hasHeader) {
@@ -267,6 +270,10 @@ SaveStateDescriptor CGE2MetaEngine::querySaveMetaInfos(const char *target, int s
desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
desc.setSaveTime(header.saveHour, header.saveMinutes);
+ if (header.playTime) {
+ desc.setPlayTime(header.playTime * 1000);
+ }
+
// Slot 0 is used for the 'automatic save on exit' save in Soltys, thus
// we prevent it from being deleted or overwritten by accident.
desc.setDeletableFlag(slot != 0);
diff --git a/engines/cge2/events.cpp b/engines/cge2/events.cpp
index 2dac04a0a5..b5c452745b 100644
--- a/engines/cge2/events.cpp
+++ b/engines/cge2/events.cpp
@@ -29,7 +29,6 @@
#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"
#include "cge2/cge2_main.h"
diff --git a/engines/cge2/saveload.cpp b/engines/cge2/saveload.cpp
index cd0be84567..a8120c1017 100644
--- a/engines/cge2/saveload.cpp
+++ b/engines/cge2/saveload.cpp
@@ -118,9 +118,7 @@ bool CGE2Engine::loadGame(int slotNumber) {
return false;
}
- // Delete the thumbnail
- saveHeader.thumbnail->free();
- delete saveHeader.thumbnail;
+ g_engine->setTotalPlayTime(saveHeader.playTime * 1000);
}
resetGame();
@@ -178,10 +176,20 @@ void CGE2Engine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &h
out->writeSint16LE(td.tm_mday);
out->writeSint16LE(td.tm_hour);
out->writeSint16LE(td.tm_min);
+
+ out->writeUint32LE(g_engine->getTotalPlayTime() / 1000);
}
-bool CGE2Engine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) {
- header.thumbnail = nullptr;
+WARN_UNUSED_RESULT bool CGE2Engine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail) {
+ header.version = 0;
+ header.saveName.clear();
+ header.thumbnail = nullptr;
+ header.saveYear = 0;
+ header.saveMonth = 0;
+ header.saveDay = 0;
+ header.saveHour = 0;
+ header.saveMinutes = 0;
+ header.playTime = 0;
// Get the savegame version
header.version = in->readByte();
@@ -189,23 +197,27 @@ bool CGE2Engine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &head
return false;
// Read in the string
- header.saveName.clear();
char ch;
while ((ch = (char)in->readByte()) != '\0')
header.saveName += ch;
// Get the thumbnail
- header.thumbnail = Graphics::loadThumbnail(*in);
- if (!header.thumbnail)
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
- header.saveYear = in->readSint16LE();
- header.saveMonth = in->readSint16LE();
- header.saveDay = in->readSint16LE();
- header.saveHour = in->readSint16LE();
+ header.saveYear = in->readSint16LE();
+ header.saveMonth = in->readSint16LE();
+ header.saveDay = in->readSint16LE();
+ header.saveHour = in->readSint16LE();
header.saveMinutes = in->readSint16LE();
+ if (header.version >= 2) {
+ header.playTime = in->readUint32LE();
+ }
+
+
return true;
}
diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp
index 8b0d8b6c77..8b8acb6ade 100644
--- a/engines/cge2/vga13h.cpp
+++ b/engines/cge2/vga13h.cpp
@@ -938,13 +938,13 @@ uint8 Vga::closest(Dac *pal, const uint8 colR, const uint8 colG, const uint8 col
uint16 D = ((r > R) ? (r - R) : (R - r)) +
((g > G) ? (g - G) : (G - g)) +
((b > B) ? (b - B) : (B - b)) +
- ((l > L) ? (l - L) : (L - l)) * 10 ;
+ ((l > L) ? (l - L) : (L - l)) * 10;
if (D < dif) {
found = i;
dif = D;
if (D == 0)
- break; // exact!
+ break; // exact!
}
}
return found;
diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index 75c2a8d51b..81f8c7d03a 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -94,7 +94,7 @@ Common::Error ChewyEngine::run() {
}*/
//_graphics->playVideo(0);
-
+
_scene->change(0);
//_sound->playSpeech(1);
//_sound->playSound(1);
diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index 65c4a681d6..af62bf017b 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -113,7 +113,7 @@ bool Console::Cmd_DrawImage(int argc, const char **argv) {
Common::String filename = argv[1];
int resNum = atoi(argv[2]);
-
+
_vm->_graphics->drawImage(filename, resNum);
return false;
diff --git a/engines/chewy/detection.cpp b/engines/chewy/detection.cpp
index f6f66efba0..7b7f29f9e8 100644
--- a/engines/chewy/detection.cpp
+++ b/engines/chewy/detection.cpp
@@ -70,7 +70,7 @@ static const ChewyGameDescription gameDescriptions[] = {
GUIO1(GUIO_NONE)
},
},
-
+
{
// Chewy - ESC von F5 - German
// Master version 1.1 (CHEWY.EXE - offset 0x8AB28)
@@ -87,7 +87,7 @@ static const ChewyGameDescription gameDescriptions[] = {
GUIO1(GUIO_NONE)
},
},
-
+
{
// Chewy - ESC von F5 - German
// Master version 1.0 (CHEWY.EXE - offset 0x8AB10)
diff --git a/engines/chewy/scene.cpp b/engines/chewy/scene.cpp
index 11bb4b38cd..5398a8da12 100644
--- a/engines/chewy/scene.cpp
+++ b/engines/chewy/scene.cpp
@@ -138,7 +138,7 @@ void Scene::change(uint scene) {
_curScene = scene;
_vm->_cursor->setCursor(0);
_vm->_cursor->showCursor();
-
+
loadSceneInfo();
draw();
}
@@ -320,14 +320,14 @@ void Scene::loadSceneInfo() {
_sceneInfo->roomInfo.picNum = indexFile.readByte();
_sceneInfo->roomInfo.autoMoveCount = indexFile.readByte();
_sceneInfo->roomInfo.loadTaf = indexFile.readByte();
-
+
_sceneInfo->roomInfo.tafName = "";
for (int i = 0; i < 14; i++)
_sceneInfo->roomInfo.tafName += indexFile.readByte();
_sceneInfo->roomInfo.zoomFactor = indexFile.readByte();
indexFile.readByte(); // padding
-
+
for (int i = 0; i < MAX_AUTOMOVE; i++) {
_sceneInfo->autoMove[i].x = indexFile.readSint16LE();
_sceneInfo->autoMove[i].y = indexFile.readSint16LE();
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index 6c8b4a676d..f1636c902b 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -84,7 +84,7 @@ public:
_guiOptions = GUIO2(GUIO_NOSPEECH, GAMEOPTION_ORIGINAL_SAVELOAD);
}
- virtual GameDescriptor findGame(const char *gameId) const {
+ PlainGameDescriptor findGame(const char *gameId) const override {
return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
}
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index a8b4c085ff..70ce8fec98 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -299,11 +299,7 @@ void AdLibSoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) {
void AdLibSoundDriver::setupChannel(int channel, const byte *data, int instrument, int volume) {
assert(channel < 4);
if (data) {
- if (volume > 80) {
- volume = 80;
- } else if (volume < 0) {
- volume = 0;
- }
+ volume = CLIP(volume, 0, 80);
volume += volume / 4;
_channelsVolumeTable[channel] = volume;
diff --git a/engines/composer/detection.cpp b/engines/composer/detection.cpp
index dd1ce2751c..c90dfe5131 100644
--- a/engines/composer/detection.cpp
+++ b/engines/composer/detection.cpp
@@ -511,10 +511,9 @@ SaveStateList ComposerMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray filenames;
Common::String saveDesc;
- Common::String pattern = Common::String::format("%s.??", target);
+ Common::String pattern = Common::String::format("%s.##", target);
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) {
@@ -531,6 +530,7 @@ SaveStateList ComposerMetaEngine::listSaves(const char *target) const {
}
}
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index 6f5d236173..3dfd414fd2 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -241,9 +241,8 @@ SaveStateList CruiseMetaEngine::listSaves(const char *target) const {
Common::InSaveFile *in = saveFileMan->openForLoading(*file);
if (in) {
Cruise::CruiseSavegameHeader header;
- Cruise::readSavegameHeader(in, header);
- saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
- delete header.thumbnail;
+ if (Cruise::readSavegameHeader(in, header))
+ saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
delete in;
}
}
@@ -264,7 +263,11 @@ SaveStateDescriptor CruiseMetaEngine::querySaveMetaInfos(const char *target, int
if (f) {
Cruise::CruiseSavegameHeader header;
- Cruise::readSavegameHeader(f, header);
+ if (!Cruise::readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
+
delete f;
// Create the return descriptor
diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp
index a62648df08..7aaeb06905 100644
--- a/engines/cruise/saveload.cpp
+++ b/engines/cruise/saveload.cpp
@@ -43,9 +43,8 @@ struct overlayRestoreTemporary {
overlayRestoreTemporary ovlRestoreData[90];
-bool readSavegameHeader(Common::InSaveFile *in, CruiseSavegameHeader &header) {
+WARN_UNUSED_RESULT bool readSavegameHeader(Common::InSaveFile *in, CruiseSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[6];
- header.thumbnail = NULL;
// Validate the header Id
in->read(saveIdentBuffer, 6);
@@ -62,9 +61,9 @@ bool readSavegameHeader(Common::InSaveFile *in, CruiseSavegameHeader &header) {
while ((ch = (char)in->readByte()) != '\0') header.saveName += ch;
// Get the thumbnail
- header.thumbnail = Graphics::loadThumbnail(*in);
- if (!header.thumbnail)
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
return false;
+ }
return true;
}
@@ -827,8 +826,10 @@ Common::Error loadSavegameData(int saveGameIdx) {
// Skip over the savegame header
CruiseSavegameHeader header;
- readSavegameHeader(f, header);
- delete header.thumbnail;
+ if (!readSavegameHeader(f, header)) {
+ delete f;
+ return Common::kReadingFailed;
+ }
// Synchronise the remaining data of the savegame
Common::Serializer s(f, NULL);
diff --git a/engines/cruise/saveload.h b/engines/cruise/saveload.h
index 6fb1f4b545..c92f0e9da5 100644
--- a/engines/cruise/saveload.h
+++ b/engines/cruise/saveload.h
@@ -38,7 +38,7 @@ struct CruiseSavegameHeader {
Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName);
Common::Error loadSavegameData(int saveGameIdx);
-bool readSavegameHeader(Common::InSaveFile *in, CruiseSavegameHeader &header);
+WARN_UNUSED_RESULT bool readSavegameHeader(Common::InSaveFile *in, CruiseSavegameHeader &header, bool skipThumbnail = true);
void initVars();
} // End of namespace Cruise
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index 57dcfcea8f..8d6ca571d1 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -334,11 +334,7 @@ void AdLibSoundDriver::syncSounds() {
void AdLibSoundDriver::adjustVolume(int channel, int volume) {
_channelsVolumeTable[channel].original = volume;
- if (volume > 80) {
- volume = 80;
- } else if (volume < 0) {
- volume = 0;
- }
+ volume = CLIP(volume, 0, 80);
volume += volume / 4;
// The higher possible value for volume is 100
diff --git a/engines/cryo/cryo.h b/engines/cryo/cryo.h
index 515849ffea..9a8bc913ba 100644
--- a/engines/cryo/cryo.h
+++ b/engines/cryo/cryo.h
@@ -25,7 +25,6 @@
#include "common/scummsys.h"
#include "common/config-manager.h"
-#include "engines/advancedDetector.h"
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/error.h"
@@ -39,6 +38,8 @@
#include "cryo/video.h"
#include "cryo/debugger.h"
+struct ADGameDescription;
+
namespace Cryo {
class Console;
diff --git a/engines/cryo/eden.cpp b/engines/cryo/eden.cpp
index 103d9fde9e..c4a76a47a2 100644
--- a/engines/cryo/eden.cpp
+++ b/engines/cryo/eden.cpp
@@ -26,7 +26,6 @@
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/error.h"
-#include "gui/EventRecorder.h"
#include "common/file.h"
#include "common/savefile.h"
#include "common/fs.h"
@@ -2321,7 +2320,7 @@ void EdenGame::my_bulle() {
} else if (c >= 0x80 && c < 0x90)
SysBeep(1);
else if (c >= 0x90 && c < 0xA0) {
- while (*textPtr++ != 0xFF) ;
+ while (*textPtr++ != 0xFF) {}
textPtr--;
} else if (c >= 0xA0 && c < 0xC0)
_globals->_textToken1 = c & 0xF;
@@ -2333,7 +2332,7 @@ void EdenGame::my_bulle() {
#ifdef FAKE_DOS_VERSION
_globals->_textWidthLimit = c1 + 160;
#else
- _globals->_textWidthLimit = c1 + _subtitlesXCenter; //TODO: signed? 160 in pc ver
+ _globals->_textWidthLimit = c1 + _subtitlesXCenter; // TODO: signed? 160 in pc ver
#endif
else {
byte c2 = *textPtr++;
diff --git a/engines/cryo/sound.cpp b/engines/cryo/sound.cpp
index 68f067588f..95bf39eca9 100644
--- a/engines/cryo/sound.cpp
+++ b/engines/cryo/sound.cpp
@@ -1,113 +1,113 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "cryo/sound.h"
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "audio/decoders/raw.h"
-
-namespace Cryo {
-
-CSoundChannel::CSoundChannel(Audio::Mixer *mixer, unsigned int sampleRate, bool stereo, bool is16bits) : _mixer(mixer), _sampleRate(sampleRate), _stereo(stereo) {
- _bufferFlags = is16bits ? (Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_16BITS) : Audio::FLAG_UNSIGNED;
- if (stereo)
- _bufferFlags |= Audio::FLAG_STEREO;
- _audioStream = nullptr;
- _volumeLeft = _volumeRight = Audio::Mixer::kMaxChannelVolume;
-}
-
-CSoundChannel::~CSoundChannel() {
- stop();
- if (_audioStream)
- delete _audioStream;
-}
-
-void CSoundChannel::queueBuffer(byte *buffer, unsigned int size, bool playNow, bool playQueue, bool buffering) {
- if (playNow)
- stop();
-
- if (!buffer || !size)
- return;
-
- if (!_audioStream)
- _audioStream = Audio::makeQueuingAudioStream(_sampleRate, _stereo);
-
- if (buffering) {
- byte *localBuffer = (byte*)malloc(size);
- memcpy(localBuffer, buffer, size);
- _audioStream->queueBuffer(localBuffer, size, DisposeAfterUse::YES, _bufferFlags);
- } else
- _audioStream->queueBuffer(buffer, size, DisposeAfterUse::NO, _bufferFlags);
- if (playNow || playQueue)
- play();
-}
-
-void CSoundChannel::play() {
- if (!_audioStream)
- return;
- if (!_mixer->isSoundHandleActive(_soundHandle)) {
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
- applyVolumeChange();
- }
-}
-
-void CSoundChannel::stop() {
- if (_mixer->isSoundHandleActive(_soundHandle))
- _mixer->stopHandle(_soundHandle);
-
- if (_audioStream) {
- _audioStream->finish();
- delete _audioStream;
- _audioStream = nullptr;
- }
-}
-
-unsigned int CSoundChannel::numQueued() {
- return _audioStream ? _audioStream->numQueuedStreams() : 0;
-}
-
-unsigned int CSoundChannel::getVolume() {
- return (_volumeRight + _volumeLeft) / 2;
-}
-
-void CSoundChannel::setVolume(unsigned int volumeLeft, unsigned int volumeRight) {
- _volumeLeft = volumeLeft;
- _volumeRight = volumeRight;
- applyVolumeChange();
-}
-
-void CSoundChannel::setVolumeLeft(unsigned int volume) {
- setVolume(volume, _volumeRight);
-}
-
-void CSoundChannel::setVolumeRight(unsigned int volume) {
- setVolume(_volumeLeft, volume);
-}
-
-void CSoundChannel::applyVolumeChange() {
- unsigned int volume = (_volumeRight + _volumeLeft) / 2;
- int balance = (signed int)(_volumeRight - _volumeLeft) / 2;
- _mixer->setChannelVolume(_soundHandle, volume);
- _mixer->setChannelBalance(_soundHandle, balance);
-}
-
-}
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "cryo/sound.h"
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+
+namespace Cryo {
+
+CSoundChannel::CSoundChannel(Audio::Mixer *mixer, unsigned int sampleRate, bool stereo, bool is16bits) : _mixer(mixer), _sampleRate(sampleRate), _stereo(stereo) {
+ _bufferFlags = is16bits ? (Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_16BITS) : Audio::FLAG_UNSIGNED;
+ if (stereo)
+ _bufferFlags |= Audio::FLAG_STEREO;
+ _audioStream = nullptr;
+ _volumeLeft = _volumeRight = Audio::Mixer::kMaxChannelVolume;
+}
+
+CSoundChannel::~CSoundChannel() {
+ stop();
+ if (_audioStream)
+ delete _audioStream;
+}
+
+void CSoundChannel::queueBuffer(byte *buffer, unsigned int size, bool playNow, bool playQueue, bool buffering) {
+ if (playNow)
+ stop();
+
+ if (!buffer || !size)
+ return;
+
+ if (!_audioStream)
+ _audioStream = Audio::makeQueuingAudioStream(_sampleRate, _stereo);
+
+ if (buffering) {
+ byte *localBuffer = (byte*)malloc(size);
+ memcpy(localBuffer, buffer, size);
+ _audioStream->queueBuffer(localBuffer, size, DisposeAfterUse::YES, _bufferFlags);
+ } else
+ _audioStream->queueBuffer(buffer, size, DisposeAfterUse::NO, _bufferFlags);
+ if (playNow || playQueue)
+ play();
+}
+
+void CSoundChannel::play() {
+ if (!_audioStream)
+ return;
+ if (!_mixer->isSoundHandleActive(_soundHandle)) {
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ applyVolumeChange();
+ }
+}
+
+void CSoundChannel::stop() {
+ if (_mixer->isSoundHandleActive(_soundHandle))
+ _mixer->stopHandle(_soundHandle);
+
+ if (_audioStream) {
+ _audioStream->finish();
+ delete _audioStream;
+ _audioStream = nullptr;
+ }
+}
+
+unsigned int CSoundChannel::numQueued() {
+ return _audioStream ? _audioStream->numQueuedStreams() : 0;
+}
+
+unsigned int CSoundChannel::getVolume() {
+ return (_volumeRight + _volumeLeft) / 2;
+}
+
+void CSoundChannel::setVolume(unsigned int volumeLeft, unsigned int volumeRight) {
+ _volumeLeft = volumeLeft;
+ _volumeRight = volumeRight;
+ applyVolumeChange();
+}
+
+void CSoundChannel::setVolumeLeft(unsigned int volume) {
+ setVolume(volume, _volumeRight);
+}
+
+void CSoundChannel::setVolumeRight(unsigned int volume) {
+ setVolume(_volumeLeft, volume);
+}
+
+void CSoundChannel::applyVolumeChange() {
+ unsigned int volume = (_volumeRight + _volumeLeft) / 2;
+ int balance = (signed int)(_volumeRight - _volumeLeft) / 2;
+ _mixer->setChannelVolume(_soundHandle, volume);
+ _mixer->setChannelBalance(_soundHandle, balance);
+}
+
+}
diff --git a/engines/cryo/sound.h b/engines/cryo/sound.h
index 72232cc4f1..ad5312f527 100644
--- a/engines/cryo/sound.h
+++ b/engines/cryo/sound.h
@@ -1,70 +1,70 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#pragma once
-
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "audio/decoders/raw.h"
-
-#include "cryo/cryolib.h"
-
-namespace Cryo {
-
-class CryoEngine;
-
-class CSoundChannel {
-private:
- Audio::Mixer *_mixer;
- Audio::QueuingAudioStream *_audioStream;
- Audio::SoundHandle _soundHandle;
- unsigned int _sampleRate;
- bool _stereo;
- unsigned int _bufferFlags;
-
- void applyVolumeChange();
-
-public:
- CSoundChannel(Audio::Mixer *mixer, unsigned int sampleRate, bool stereo, bool is16bits = false);
- ~CSoundChannel();
-
- // Queue a new buffer, cancel any previously queued buffers if playNow is set
- void queueBuffer(byte *buffer, unsigned int size, bool playNow = false, bool playQueue = true, bool buffering = true);
-
- // Play any queued buffers
- void play();
-
- // Stop playing and purge play queue
- void stop();
-
- // How many buffers in queue (including currently playing one)
- unsigned int numQueued();
-
- // Volume control
- int _volumeLeft, _volumeRight;
- unsigned int getVolume();
- void setVolume(unsigned int volumeLeft, unsigned int volumeRight);
- void setVolumeLeft(unsigned int volume);
- void setVolumeRight(unsigned int volume);
-};
-
-}
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#pragma once
+
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+
+#include "cryo/cryolib.h"
+
+namespace Cryo {
+
+class CryoEngine;
+
+class CSoundChannel {
+private:
+ Audio::Mixer *_mixer;
+ Audio::QueuingAudioStream *_audioStream;
+ Audio::SoundHandle _soundHandle;
+ unsigned int _sampleRate;
+ bool _stereo;
+ unsigned int _bufferFlags;
+
+ void applyVolumeChange();
+
+public:
+ CSoundChannel(Audio::Mixer *mixer, unsigned int sampleRate, bool stereo, bool is16bits = false);
+ ~CSoundChannel();
+
+ // Queue a new buffer, cancel any previously queued buffers if playNow is set
+ void queueBuffer(byte *buffer, unsigned int size, bool playNow = false, bool playQueue = true, bool buffering = true);
+
+ // Play any queued buffers
+ void play();
+
+ // Stop playing and purge play queue
+ void stop();
+
+ // How many buffers in queue (including currently playing one)
+ unsigned int numQueued();
+
+ // Volume control
+ int _volumeLeft, _volumeRight;
+ unsigned int getVolume();
+ void setVolume(unsigned int volumeLeft, unsigned int volumeRight);
+ void setVolumeLeft(unsigned int volume);
+ void setVolumeRight(unsigned int volume);
+};
+
+}
diff --git a/engines/cryo/video.cpp b/engines/cryo/video.cpp
index fe242425e5..fe8afb7ce8 100644
--- a/engines/cryo/video.cpp
+++ b/engines/cryo/video.cpp
@@ -102,7 +102,7 @@ void HnmPlayer::waitLoop() {
_nextFrameTime = _expectedFrameTime - _timeDrift;
if (_useSoundSync && _vm->_timerTicks > 1000.0 + _nextFrameTime)
_useSound = false;
- while (_vm->_timerTicks < _nextFrameTime) ; // waste time
+ while (_vm->_timerTicks < _nextFrameTime) {} // waste time
_timeDrift = _vm->_timerTicks - _nextFrameTime;
}
diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index 16d838fcca..9d293846bc 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -112,7 +112,7 @@ public:
return "Macromedia Director (C) Macromedia";
}
- const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
};
@@ -141,7 +141,7 @@ static Director::DirectorGameDescription s_fallbackDesc = {
static char s_fallbackFileNameBuffer[51];
-const ADGameDescription *DirectorMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ADDetectedGame DirectorMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
// TODO: Handle Mac fallback
// reset fallback description
@@ -230,10 +230,10 @@ const ADGameDescription *DirectorMetaEngine::fallbackDetect(const FileMap &allFi
warning("Director fallback detection D%d", desc->version);
- return (ADGameDescription *)desc;
+ return ADDetectedGame(&desc->desc);
}
- return 0;
+ return ADDetectedGame();
}
#if PLUGIN_ENABLED_DYNAMIC(DIRECTOR)
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 1b3b59e1ef..e42444dc00 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -241,7 +241,7 @@ void Frame::readChannels(Common::ReadStreamEndian *stream) {
sprite._width = stream->readUint16();
stream->readUint16();
stream->readUint16();
-
+
}
if (sprite._castId) {
diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp
index b8d9749052..c908b2e591 100644
--- a/engines/director/lingo/lingo-gr.cpp
+++ b/engines/director/lingo/lingo-gr.cpp
@@ -1596,7 +1596,7 @@ int yydebug;
# define YYMAXDEPTH 10000
#endif
-
+
#if YYERROR_VERBOSE
@@ -1807,7 +1807,7 @@ yysyntax_error (char *yyresult, int yystate, int yychar)
}
}
#endif /* YYERROR_VERBOSE */
-
+
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
@@ -1839,7 +1839,7 @@ yydestruct (yymsg, yytype, yyvaluep)
break;
}
}
-
+
/* Prevent warnings from -Wmissing-prototypes. */
@@ -1896,7 +1896,7 @@ yyparse ()
#endif
#endif
{
-
+
int yystate;
int yyn;
int yyresult;
diff --git a/engines/director/lingo/lingo-lex.cpp b/engines/director/lingo/lingo-lex.cpp
index 7b0398367b..de7005275d 100644
--- a/engines/director/lingo/lingo-lex.cpp
+++ b/engines/director/lingo/lingo-lex.cpp
@@ -168,7 +168,7 @@ extern FILE *yyin, *yyout;
#define EOB_ACT_LAST_MATCH 2
#define YY_LESS_LINENO(n)
-
+
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
@@ -225,7 +225,7 @@ struct yy_buffer_state
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
-
+
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
@@ -963,7 +963,7 @@ YY_DECL
register yy_state_type yy_current_state;
register char *yy_cp, *yy_bp;
register int yy_act;
-
+
#line 85 "engines/director/lingo/lingo-lex.l"
@@ -1859,7 +1859,7 @@ static int yy_get_next_buffer (void)
{
register yy_state_type yy_current_state;
register char *yy_cp;
-
+
yy_current_state = (yy_start);
yy_current_state += YY_AT_BOL();
@@ -1920,7 +1920,7 @@ static int yy_get_next_buffer (void)
{
int c;
-
+
*(yy_c_buf_p) = (yy_hold_char);
if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
@@ -1994,7 +1994,7 @@ static int yy_get_next_buffer (void)
*/
void yyrestart (FILE * input_file )
{
-
+
if ( ! YY_CURRENT_BUFFER ){
yyensure_buffer_stack ();
YY_CURRENT_BUFFER_LVALUE =
@@ -2011,7 +2011,7 @@ static int yy_get_next_buffer (void)
*/
void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
{
-
+
/* TODO. We should be able to replace this entire function body
* with
* yypop_buffer_state();
@@ -2057,7 +2057,7 @@ static void yy_load_buffer_state (void)
YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
{
YY_BUFFER_STATE b;
-
+
b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
@@ -2084,7 +2084,7 @@ static void yy_load_buffer_state (void)
*/
void yy_delete_buffer (YY_BUFFER_STATE b )
{
-
+
if ( ! b )
return;
@@ -2100,7 +2100,7 @@ static void yy_load_buffer_state (void)
#ifndef __cplusplus
extern int isatty (int );
#endif /* __cplusplus */
-
+
/* Initializes or reinitializes a buffer.
* This function is sometimes called more than once on the same buffer,
* such as during a yyrestart() or at EOF.
@@ -2109,7 +2109,7 @@ extern int isatty (int );
{
int oerrno = errno;
-
+
yy_flush_buffer(b );
b->yy_input_file = file;
@@ -2125,7 +2125,7 @@ extern int isatty (int );
}
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-
+
errno = oerrno;
}
@@ -2214,7 +2214,7 @@ void yypop_buffer_state (void)
static void yyensure_buffer_stack (void)
{
yy_size_t num_to_alloc;
-
+
if (!(yy_buffer_stack)) {
/* First allocation is just for 2 elements, since we don't know if this
@@ -2227,9 +2227,9 @@ static void yyensure_buffer_stack (void)
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
+
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
+
(yy_buffer_stack_max) = num_to_alloc;
(yy_buffer_stack_top) = 0;
return;
@@ -2263,7 +2263,7 @@ static void yyensure_buffer_stack (void)
YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
{
YY_BUFFER_STATE b;
-
+
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
@@ -2299,7 +2299,7 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
*/
YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
{
-
+
return yy_scan_bytes(yystr,strlen(yystr) );
}
@@ -2315,7 +2315,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len
YY_BUFFER_STATE b;
char *buf;
yy_size_t n, i;
-
+
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
buf = (char *) yyalloc(n );
@@ -2373,7 +2373,7 @@ static void yy_fatal_error (yyconst char* msg )
*/
int yyget_lineno (void)
{
-
+
return yylineno;
}
@@ -2416,7 +2416,7 @@ char *yyget_text (void)
*/
void yyset_lineno (int line_number )
{
-
+
yylineno = line_number;
}
@@ -2477,7 +2477,7 @@ static int yy_init_globals (void)
/* yylex_destroy is for both reentrant and non-reentrant scanners. */
int yylex_destroy (void)
{
-
+
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
yy_delete_buffer(YY_CURRENT_BUFFER );
diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index e748583146..22b33e7bcc 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -176,7 +176,7 @@ void DirectorEngine::loadEXEv4(Common::SeekableReadStream *stream) {
void DirectorEngine::loadEXEv5(Common::SeekableReadStream *stream) {
uint32 ver = stream->readUint32LE();
-
+
if (ver != MKTAG('P', 'J', '9', '5'))
error("Invalid projector tag found in v5 EXE [%s]", tag2str(ver));
diff --git a/engines/dm/dm.h b/engines/dm/dm.h
index 16307778ba..e330cb6be7 100644
--- a/engines/dm/dm.h
+++ b/engines/dm/dm.h
@@ -332,7 +332,7 @@ public:
Thing _thingParty; // @ C0xFFFF_THING_PARTY
};
-bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader *header);
+WARN_UNUSED_RESULT bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader *header, bool skipThumbnail = true);
} // End of namespace DM
diff --git a/engines/dm/dungeonman.cpp b/engines/dm/dungeonman.cpp
index ab35477183..7d7b80685e 100644
--- a/engines/dm/dungeonman.cpp
+++ b/engines/dm/dungeonman.cpp
@@ -1465,6 +1465,7 @@ Thing DungeonMan::getDiscardThing(uint16 thingType) {
case kDMThingTypeGroup:
if (((Group *)squareThingData)->getDoNotDiscard())
continue;
+ // fall through
case kDMThingTypeProjectile:
setCurrentMap(mapIndex);
if (thingType == kDMThingTypeGroup) {
diff --git a/engines/dm/gfx.cpp b/engines/dm/gfx.cpp
index 7f31b29575..f75e7eb170 100644
--- a/engines/dm/gfx.cpp
+++ b/engines/dm/gfx.cpp
@@ -2162,22 +2162,20 @@ void DisplayMan::drawSquareD0L(Direction dir, int16 posX, int16 posY) {
uint16 squareAspect[5];
_vm->_dungeonMan->setSquareAspect(squareAspect, dir, posX, posY);
switch (squareAspect[kDMSquareAspectElement]) {
- case kDMElementTypeWall:
- drawWallSetBitmap(bitmapWallSetWallD0L, _frameWalls163[kDMViewSquareD0L]);
- break;
+ case kDMElementTypeStairsSide:
+ drawFloorPitOrStairsBitmap(_stairsNativeBitmapIndexSideD0L, frameStairsSideD0L);
+ return;
+ case kDMElementTypePit:
+ drawFloorPitOrStairsBitmap(squareAspect[kDMSquareAspectPitInvisible] ? kDMGraphicIdxFloorPitInvisibleD0L : kDMGraphicIdxFloorPitD0L, frameFloorPitD0L);
+ // fall through
case kDMElementTypeCorridor:
- case kDMElementTypeTeleporter:
case kDMElementTypeDoorSide:
+ case kDMElementTypeTeleporter:
drawObjectsCreaturesProjectilesExplosions(Thing(squareAspect[kDMSquareAspectFirstGroupOrObject]), dir, posX, posY, kDMViewSquareD0L, kDMCellOrderBackRight);
break;
- case kDMElementTypePit:
- drawFloorPitOrStairsBitmap(squareAspect[kDMSquareAspectPitInvisible] ? kDMGraphicIdxFloorPitInvisibleD0L : kDMGraphicIdxFloorPitD0L, frameFloorPitD0L);
- case kDMElementTypeStairsSide:
- if (squareAspect[kDMSquareAspectStairsUp])
- drawFloorPitOrStairsBitmap(_stairsNativeBitmapIndexSideD0L, frameStairsSideD0L);
- break;
- default:
- break;
+ case kDMElementTypeWall:
+ drawWallSetBitmap(bitmapWallSetWallD0L, _frameWalls163[kDMViewSquareD0L]);
+ return;
}
drawCeilingPit(kDMGraphicIdxCeilingPitD0L, &frameCeilingPitD0L, posX, posY, false);
@@ -2200,6 +2198,7 @@ void DisplayMan::drawSquareD0R(Direction dir, int16 posX, int16 posY) {
case kDMElementTypePit:
drawFloorPitOrStairsBitmapFlippedHorizontally(squareAspect[kDMSquareAspectPitInvisible] ? kDMGraphicIdxFloorPitInvisibleD0L
: kDMGraphicIdxFloorPitD0L, frameFloorPitD0R);
+ // fall through
case kDMElementTypeCorridor:
case kDMElementTypeDoorSide:
case kDMElementTypeTeleporter:
diff --git a/engines/dm/group.cpp b/engines/dm/group.cpp
index dfdcdc017f..f36a8ddc31 100644
--- a/engines/dm/group.cpp
+++ b/engines/dm/group.cpp
@@ -1518,6 +1518,7 @@ bool GroupMan::isCreatureAttacking(Group *group, int16 mapX, int16 mapY, uint16
projectileThing = _vm->_thingExplPoisonCloud;
break;
}
+ // fall through
case kDMCreatureTypeDemon:
case kDMCreatureTypeRedDragon:
projectileThing = _vm->_thingExplFireBall;
diff --git a/engines/dm/loadsave.cpp b/engines/dm/loadsave.cpp
index 3d8f76c33f..864a726367 100644
--- a/engines/dm/loadsave.cpp
+++ b/engines/dm/loadsave.cpp
@@ -70,7 +70,10 @@ LoadgameResult DMEngine::loadgame(int16 slot) {
file = saveFileManager->openForLoading(fileName);
SaveGameHeader header;
- readSaveGameHeader(file, &header);
+ if (!readSaveGameHeader(file, &header)) {
+ delete file;
+ return kDMLoadgameFailure;
+ }
warning("MISSING CODE: missing check for matching format and platform in save in f435_loadgame");
@@ -397,7 +400,7 @@ bool DMEngine::writeCompleteSaveFile(int16 saveSlot, Common::String& saveDescrip
return true;
}
-bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader *header) {
+WARN_UNUSED_RESULT bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader *header, bool skipThumbnail) {
uint32 id = in->readUint32BE();
// Check if it's a valid ScummVM savegame
@@ -419,7 +422,11 @@ bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader *header) {
header->_descr.setDescription(saveName);
// Get the thumbnail
- header->_descr.setThumbnail(Graphics::loadThumbnail(*in));
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*in, thumbnail, skipThumbnail)) {
+ return false;
+ }
+ header->_descr.setThumbnail(thumbnail);
uint32 saveDate = in->readUint32BE();
uint16 saveTime = in->readUint16BE();
diff --git a/engines/dm/menus.cpp b/engines/dm/menus.cpp
index 1600f589e9..f547bbe934 100644
--- a/engines/dm/menus.cpp
+++ b/engines/dm/menus.cpp
@@ -733,9 +733,9 @@ Spell *MenuMan::getSpellFromSymbols(byte *symbols) {
if (*(symbols + 1)) {
int16 bitShiftCount = 24;
int32 curSymbols = 0;
- do
+ do {
curSymbols |= (long)*symbols++ << bitShiftCount;
- while (*symbols && ((bitShiftCount -= 8) >= 0));
+ } while (*symbols && ((bitShiftCount -= 8) >= 0));
Spell *curSpell = SpellsArray;
int16 spellIndex = 25;
while (spellIndex--) {
@@ -1136,6 +1136,7 @@ bool MenuMan::isActionPerformed(uint16 champIndex, int16 actionIndex) {
_vm->_sound->requestPlay(kDMSoundIndexWoodenThudAttackTrolinAntmanStoneGolem, dungeon._partyMapX, dungeon._partyMapY, kDMSoundModePlayOneTickLater);
break;
}
+ // fall through
case kDMActionDisrupt:
case kDMActionJab:
case kDMActionParry:
diff --git a/engines/dm/projexpl.cpp b/engines/dm/projexpl.cpp
index e8b0f4a143..0738cf64ba 100644
--- a/engines/dm/projexpl.cpp
+++ b/engines/dm/projexpl.cpp
@@ -503,10 +503,10 @@ void ProjExpl::processEvent25(TimelineEvent *event) {
case 0xFF82:
if (!(attack >>= 1))
break;
+ // fall through
case 0xFF80:
if (curSquareType == kDMElementTypeDoor)
_vm->_groupMan->groupIsDoorDestoryedByAttack(mapX, mapY, attack, true, 0);
-
break;
case 0xFF83:
if ((groupThing != _vm->_thingEndOfList) && getFlag(creatureInfo->_attributes, kDMCreatureMaskNonMaterial)) {
diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp
index 65427bd8cd..9a76e3890c 100644
--- a/engines/draci/detection.cpp
+++ b/engines/draci/detection.cpp
@@ -132,10 +132,6 @@ SaveStateList DraciMetaEngine::listSaves(const char *target) const {
Draci::DraciSavegameHeader header;
if (Draci::readSavegameHeader(in, header)) {
saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
- if (header.thumbnail) {
- header.thumbnail->free();
- delete header.thumbnail;
- }
}
delete in;
}
@@ -157,7 +153,11 @@ SaveStateDescriptor DraciMetaEngine::querySaveMetaInfos(const char *target, int
if (f) {
Draci::DraciSavegameHeader header;
- Draci::readSavegameHeader(f, header);
+ if (!Draci::readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
+
delete f;
// Create the return descriptor
diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp
index 4fbf2d31ea..af57b1eb37 100644
--- a/engines/draci/game.cpp
+++ b/engines/draci/game.cpp
@@ -1594,7 +1594,7 @@ Game::~Game() {
delete[] _items;
}
-void Game::DoSync(Common::Serializer &s, uint8 saveVersion) {
+void Game::synchronize(Common::Serializer &s, uint8 saveVersion) {
s.syncAsUint16LE(_currentRoom._roomNum);
for (uint i = 0; i < _info._numObjects; ++i) {
diff --git a/engines/draci/game.h b/engines/draci/game.h
index 53a472a552..1e3cca9b9d 100644
--- a/engines/draci/game.h
+++ b/engines/draci/game.h
@@ -330,7 +330,7 @@ public:
void setEnableSpeedText(bool value) { _enableSpeedText = value; }
bool getEnableSpeedText() const { return _enableSpeedText; }
- void DoSync(Common::Serializer &s, uint8 saveVersion);
+ void synchronize(Common::Serializer &s, uint8 saveVersion);
private:
void updateOrdinaryCursor();
diff --git a/engines/draci/saveload.cpp b/engines/draci/saveload.cpp
index 3e7f8651c1..83c64b5725 100644
--- a/engines/draci/saveload.cpp
+++ b/engines/draci/saveload.cpp
@@ -35,9 +35,8 @@ namespace Draci {
static const char *const draciIdentString = "DRACI";
-bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header) {
+WARN_UNUSED_RESULT bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[6];
- header.thumbnail = NULL;
// Validate the header Id
in->read(saveIdentBuffer, 6);
@@ -59,9 +58,9 @@ bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header) {
header.playtime = in->readUint32LE();
// Get the thumbnail
- header.thumbnail = Graphics::loadThumbnail(*in);
- if (!header.thumbnail)
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
return false;
+ }
return true;
}
@@ -107,7 +106,7 @@ Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName,
} else {
// Create the remainder of the savegame
Common::Serializer s(NULL, f);
- vm._game->DoSync(s, header.version);
+ vm._game->synchronize(s, header.version);
f->finalize();
delete f;
@@ -130,10 +129,6 @@ Common::Error loadSavegameData(int saveGameIdx, DraciEngine *vm) {
if (!readSavegameHeader(f, header)) {
return Common::kNoGameDataFoundError;
}
- if (header.thumbnail) {
- header.thumbnail->free();
- delete header.thumbnail;
- }
// Pre-processing
vm->_game->rememberRoomNumAsPrevious();
@@ -141,7 +136,7 @@ Common::Error loadSavegameData(int saveGameIdx, DraciEngine *vm) {
// Synchronise the remaining data of the savegame
Common::Serializer s(f, NULL);
- vm->_game->DoSync(s, header.version);
+ vm->_game->synchronize(s, header.version);
delete f;
// Post-processing
diff --git a/engines/draci/saveload.h b/engines/draci/saveload.h
index 6f951a3409..bceaebb468 100644
--- a/engines/draci/saveload.h
+++ b/engines/draci/saveload.h
@@ -42,7 +42,7 @@ struct DraciSavegameHeader {
class DraciEngine;
-bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header);
+WARN_UNUSED_RESULT bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header, bool skipThumbnail = true);
void writeSavegameHeader(Common::OutSaveFile *out, const DraciSavegameHeader &header);
Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, DraciEngine &vm);
Common::Error loadSavegameData(int saveGameIdx, DraciEngine *vm);
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
index 5f453839e7..a1f2f3e117 100644
--- a/engines/drascula/detection.cpp
+++ b/engines/drascula/detection.cpp
@@ -430,7 +430,11 @@ SaveStateDescriptor DrasculaMetaEngine::querySaveMetaInfos(const char *target, i
return SaveStateDescriptor();
}
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*in, thumbnail)) {
+ delete in;
+ return SaveStateDescriptor();
+ }
desc.setThumbnail(thumbnail);
delete in;
diff --git a/engines/dreamweb/detection.cpp b/engines/dreamweb/detection.cpp
index 11966047b0..36af0c3811 100644
--- a/engines/dreamweb/detection.cpp
+++ b/engines/dreamweb/detection.cpp
@@ -198,7 +198,12 @@ SaveStateDescriptor DreamWebMetaEngine::querySaveMetaInfos(const char *target, i
uint32 saveDate = in->readUint32LE();
uint32 saveTime = in->readUint32LE();
uint32 playTime = in->readUint32LE();
- Graphics::Surface *thumbnail = Graphics::loadThumbnail(*in);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*in, thumbnail)) {
+ warning("Missing or broken thumbnail - skipping");
+ delete in;
+ return desc;
+ }
int day = (saveDate >> 24) & 0xFF;
int month = (saveDate >> 16) & 0xFF;
diff --git a/engines/fullpipe/detection.cpp b/engines/fullpipe/detection.cpp
index 9dd1d6beb4..3144a0ebff 100644
--- a/engines/fullpipe/detection.cpp
+++ b/engines/fullpipe/detection.cpp
@@ -184,7 +184,9 @@ SaveStateList FullpipeMetaEngine::listSaves(const char *target) const {
Common::ScopedPtr<Common::InSaveFile> in(saveFileMan->openForLoading(*file));
if (in) {
Fullpipe::FullpipeSavegameHeader header;
- Fullpipe::readSavegameHeader(in.get(), header);
+ if (!Fullpipe::readSavegameHeader(in.get(), header)) {
+ continue;
+ }
SaveStateDescriptor desc;
@@ -212,7 +214,9 @@ SaveStateDescriptor FullpipeMetaEngine::querySaveMetaInfos(const char *target, i
if (f) {
Fullpipe::FullpipeSavegameHeader header;
- Fullpipe::readSavegameHeader(f.get(), header);
+ if (!Fullpipe::readSavegameHeader(f.get(), header, false)) {
+ return SaveStateDescriptor();
+ }
// Create the return descriptor
SaveStateDescriptor desc;
diff --git a/engines/fullpipe/gameloader.h b/engines/fullpipe/gameloader.h
index 03c3093086..eb5957c78e 100644
--- a/engines/fullpipe/gameloader.h
+++ b/engines/fullpipe/gameloader.h
@@ -84,7 +84,7 @@ struct FullpipeSavegameHeader {
uint32 date;
uint16 time;
uint32 playtime;
- Common::SharedPtr<Graphics::Surface> thumbnail;
+ Graphics::Surface *thumbnail;
};
struct SaveHeader {
@@ -142,7 +142,7 @@ class GameLoader : public CObject {
};
const char *getSavegameFile(int saveGameIdx);
-bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header);
+WARN_UNUSED_RESULT bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header, bool skipThumbnail = true);
void parseSavegameHeader(Fullpipe::FullpipeSavegameHeader &header, SaveStateDescriptor &desc);
Inventory2 *getGameLoaderInventory();
diff --git a/engines/fullpipe/interaction.h b/engines/fullpipe/interaction.h
index 9ffcdccc91..7ea58e60b4 100644
--- a/engines/fullpipe/interaction.h
+++ b/engines/fullpipe/interaction.h
@@ -70,11 +70,10 @@ public:
private:
InteractionList _interactions;
- int16 _field_20;
static bool compareInteractions(const Interaction *i1, const Interaction *i2);
public:
- InteractionController() : _field_20(0), _flag24(true) {}
+ InteractionController() : _flag24(true) {}
virtual ~InteractionController();
virtual bool load(MfcArchive &file);
diff --git a/engines/fullpipe/modal.cpp b/engines/fullpipe/modal.cpp
index be1e73ff70..3fdb6636ec 100644
--- a/engines/fullpipe/modal.cpp
+++ b/engines/fullpipe/modal.cpp
@@ -21,23 +21,21 @@
*/
#include "fullpipe/fullpipe.h"
-#include "fullpipe/messages.h"
+
#include "fullpipe/constants.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/messages.h"
+#include "fullpipe/modal.h"
#include "fullpipe/motion.h"
+#include "fullpipe/objectnames.h"
#include "fullpipe/scenes.h"
-#include "fullpipe/gameloader.h"
#include "fullpipe/statics.h"
-#include "fullpipe/modal.h"
-#include "fullpipe/constants.h"
-#include "fullpipe/objectnames.h"
+#include "engines/savestate.h"
#include "graphics/palette.h"
#include "graphics/surface.h"
-#include "engines/savestate.h"
-#include "engines/advancedDetector.h"
-
namespace Fullpipe {
ModalIntro::ModalIntro() {
@@ -2142,7 +2140,8 @@ bool ModalSaveGame::getFileInfo(int slot, FileInfo *fileinfo) {
return false;
Fullpipe::FullpipeSavegameHeader header;
- Fullpipe::readSavegameHeader(f.get(), header);
+ if (!Fullpipe::readSavegameHeader(f.get(), header))
+ return false;
// Create the return descriptor
SaveStateDescriptor desc(slot, header.saveName);
@@ -2396,7 +2395,7 @@ bool ModalDemo::init(int counterDiff) {
if (_clickedQuit == -1)
return true;
- g_system->openUrl("http://www.amazon.de/EuroVideo-Bildprogramm-GmbH-Full-Pipe/dp/B003TO51YE/ref=sr_1_1?ie=UTF8&s=videogames&qid=1279207213&sr=8-1");
+ g_system->openUrl("http://www.amazon.de/EuroVideo-Bildprogramm-GmbH-Full-Pipe/dp/B003TO51YE/ref=sr_1_1");
g_fp->_gameContinue = false;
diff --git a/engines/fullpipe/scenes/scene22.cpp b/engines/fullpipe/scenes/scene22.cpp
index 5b9b091f36..f71460576f 100644
--- a/engines/fullpipe/scenes/scene22.cpp
+++ b/engines/fullpipe/scenes/scene22.cpp
@@ -218,7 +218,7 @@ void sceneHandler22_stoolLogic(ExCommand *cmd) {
ani = g_fp->_currentScene->getStaticANIObject1ById(ANI_TABURETTE, -1);
if (ani && (ani->_flags & 4)) {
int x = g_fp->_aniMan->_ox;
- int y = g_fp->_aniMan->_ox;
+ int y = g_fp->_aniMan->_oy;
if (sqrt((double)((841 - x) * (841 - x) + (449 - y) * (449 - y)))
< sqrt((double)((1075 - x) * (1075 - x) + (449 - y) * (449 - y)))) {
diff --git a/engines/fullpipe/stateloader.cpp b/engines/fullpipe/stateloader.cpp
index 703190be0b..5b89b6b0e2 100644
--- a/engines/fullpipe/stateloader.cpp
+++ b/engines/fullpipe/stateloader.cpp
@@ -22,6 +22,13 @@
#include "fullpipe/fullpipe.h"
+#include "fullpipe/constants.h"
+#include "fullpipe/gameloader.h"
+#include "fullpipe/interaction.h"
+#include "fullpipe/objects.h"
+#include "fullpipe/scene.h"
+#include "fullpipe/statics.h"
+
#include "common/file.h"
#include "common/array.h"
#include "common/list.h"
@@ -29,15 +36,6 @@
#include "graphics/thumbnail.h"
-#include "fullpipe/objects.h"
-#include "fullpipe/gameloader.h"
-#include "fullpipe/scene.h"
-#include "fullpipe/statics.h"
-#include "fullpipe/interaction.h"
-#include "fullpipe/gameloader.h"
-
-#include "fullpipe/constants.h"
-
namespace Fullpipe {
bool GameLoader::readSavegame(const char *fname) {
@@ -69,6 +67,11 @@ bool GameLoader::readSavegame(const char *fname) {
Common::Array<byte> map(800);
saveFile->read(map.data(), 800);
+ FullpipeSavegameHeader header2;
+ if (Fullpipe::readSavegameHeader(saveFile.get(), header2)) {
+ g_fp->setTotalPlayTime(header2.playtime * 1000);
+ }
+
{
Common::MemoryReadStream tempStream(map.data(), 800, DisposeAfterUse::NO);
MfcArchive temp(&tempStream);
@@ -185,10 +188,10 @@ void fillDummyHeader(Fullpipe::FullpipeSavegameHeader &header) {
// This is wrong header, perhaps it is original savegame. Thus fill out dummy values
header.date = (20 << 24) | (9 << 16) | 2016;
header.time = (9 << 8) | 56;
- header.playtime = 1000;
+ header.playtime = 0;
}
-bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header) {
+WARN_UNUSED_RESULT bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header, bool skipThumbnail) {
uint oldPos = in->pos();
in->seek(-4, SEEK_END);
@@ -232,13 +235,13 @@ bool readSavegameHeader(Common::InSaveFile *in, FullpipeSavegameHeader &header)
header.description = header.saveName;
// Get the thumbnail
- header.thumbnail = Common::SharedPtr<Graphics::Surface>(Graphics::loadThumbnail(*in), Graphics::SurfaceDeleter());
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
+ in->seek(oldPos, SEEK_SET); // Rewind the file
+ return false;
+ }
in->seek(oldPos, SEEK_SET); // Rewind the file
- if (!header.thumbnail)
- return false;
-
return true;
}
diff --git a/engines/fullpipe/utils.cpp b/engines/fullpipe/utils.cpp
index c1cf912de6..3b60e962c6 100644
--- a/engines/fullpipe/utils.cpp
+++ b/engines/fullpipe/utils.cpp
@@ -49,7 +49,7 @@ bool ObArray::load(MfcArchive &file) {
debugC(5, kDebugLoading, "ObArray::load()");
int count = file.readCount();
- resize(count);
+ reserve(count);
for (int i = 0; i < count; i++) {
CObject *t = file.readClass<CObject>();
@@ -66,7 +66,7 @@ bool DWordArray::load(MfcArchive &file) {
debugC(9, kDebugLoading, "DWordArray::count: %d", count);
- resize(count);
+ reserve(count);
for (int i = 0; i < count; i++) {
int32 t = file.readSint32LE();
diff --git a/engines/game.cpp b/engines/game.cpp
index 7ff51a99cc..ee14acf7c8 100644
--- a/engines/game.cpp
+++ b/engines/game.cpp
@@ -22,6 +22,7 @@
#include "engines/game.h"
#include "common/gui_options.h"
+#include "common/translation.h"
const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list) {
@@ -34,93 +35,182 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla
return 0;
}
-GameDescriptor::GameDescriptor() {
- setVal("gameid", "");
- setVal("description", "");
+PlainGameDescriptor PlainGameDescriptor::empty() {
+ PlainGameDescriptor pgd;
+ pgd.gameId = nullptr;
+ pgd.description = nullptr;
+ return pgd;
}
-GameDescriptor::GameDescriptor(const PlainGameDescriptor &pgd, Common::String guioptions) {
- setVal("gameid", pgd.gameId);
- setVal("description", pgd.description);
+PlainGameDescriptor PlainGameDescriptor::of(const char *gameId, const char *description) {
+ PlainGameDescriptor pgd;
+ pgd.gameId = gameId;
+ pgd.description = description;
+ return pgd;
+}
- if (!guioptions.empty())
- setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions));
+DetectedGame::DetectedGame() :
+ engineName(nullptr),
+ hasUnknownFiles(false),
+ canBeAdded(true),
+ language(Common::UNK_LANG),
+ platform(Common::kPlatformUnknown),
+ gameSupportLevel(kStableGame) {
}
-GameDescriptor::GameDescriptor(const Common::String &g, const Common::String &d, Common::Language l, Common::Platform p, Common::String guioptions, GameSupportLevel gsl) {
- setVal("gameid", g);
- setVal("description", d);
- if (l != Common::UNK_LANG)
- setVal("language", Common::getLanguageCode(l));
- if (p != Common::kPlatformUnknown)
- setVal("platform", Common::getPlatformCode(p));
- if (!guioptions.empty())
- setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions));
-
- setSupportLevel(gsl);
+DetectedGame::DetectedGame(const PlainGameDescriptor &pgd) :
+ engineName(nullptr),
+ hasUnknownFiles(false),
+ canBeAdded(true),
+ language(Common::UNK_LANG),
+ platform(Common::kPlatformUnknown),
+ gameSupportLevel(kStableGame) {
+
+ gameId = pgd.gameId;
+ preferredTarget = pgd.gameId;
+ description = pgd.description;
}
-void GameDescriptor::setGUIOptions(Common::String guioptions) {
- if (!guioptions.empty())
- setVal("guioptions", Common::getGameGUIOptionsDescription(guioptions));
- else
- erase("guioptions");
+DetectedGame::DetectedGame(const Common::String &id, const Common::String &d, Common::Language l, Common::Platform p, const Common::String &ex) :
+ engineName(nullptr),
+ hasUnknownFiles(false),
+ canBeAdded(true),
+ gameSupportLevel(kStableGame) {
+
+ gameId = id;
+ preferredTarget = id;
+ description = d;
+ language = l;
+ platform = p;
+ extra = ex;
+
+ // Append additional information, if set, to the description.
+ description += updateDesc();
}
-void GameDescriptor::appendGUIOptions(const Common::String &str) {
- setVal("guioptions", getVal("guioptions", "") + " " + str);
+void DetectedGame::setGUIOptions(const Common::String &guioptions) {
+ _guiOptions = Common::getGameGUIOptionsDescription(guioptions);
}
-void GameDescriptor::updateDesc(const char *extra) {
- const bool hasCustomLanguage = (language() != Common::UNK_LANG);
- const bool hasCustomPlatform = (platform() != Common::kPlatformUnknown);
- const bool hasExtraDesc = (extra && extra[0]);
+void DetectedGame::appendGUIOptions(const Common::String &str) {
+ if (!_guiOptions.empty())
+ _guiOptions += " ";
+
+ _guiOptions += str;
+}
+
+Common::String DetectedGame::updateDesc() const {
+ const bool hasCustomLanguage = (language != Common::UNK_LANG);
+ const bool hasCustomPlatform = (platform != Common::kPlatformUnknown);
+ const bool hasExtraDesc = !extra.empty();
// Adapt the description string if custom platform/language is set.
- if (hasCustomLanguage || hasCustomPlatform || hasExtraDesc) {
- Common::String descr = description();
+ Common::String descr;
+ if (!hasCustomLanguage && !hasCustomPlatform && !hasExtraDesc)
+ return descr;
- descr += " (";
+ descr += " (";
+
+ if (hasExtraDesc)
+ descr += extra;
+ if (hasCustomPlatform) {
if (hasExtraDesc)
- descr += extra;
- if (hasCustomPlatform) {
- if (hasExtraDesc)
- descr += "/";
- descr += Common::getPlatformDescription(platform());
- }
- if (hasCustomLanguage) {
- if (hasExtraDesc || hasCustomPlatform)
- descr += "/";
- descr += Common::getLanguageDescription(language());
+ descr += "/";
+ descr += Common::getPlatformDescription(platform);
+ }
+ if (hasCustomLanguage) {
+ if (hasExtraDesc || hasCustomPlatform)
+ descr += "/";
+ descr += Common::getLanguageDescription(language);
+ }
+
+ descr += ")";
+
+ return descr;
+}
+
+DetectionResults::DetectionResults(const DetectedGames &detectedGames) :
+ _detectedGames(detectedGames) {
+}
+
+bool DetectionResults::foundUnknownGames() const {
+ for (uint i = 0; i < _detectedGames.size(); i++) {
+ if (_detectedGames[i].hasUnknownFiles) {
+ return true;
}
- descr += ")";
- setVal("description", descr);
}
+ return false;
}
-GameSupportLevel GameDescriptor::getSupportLevel() {
- GameSupportLevel gsl = kStableGame;
- if (contains("gsl")) {
- Common::String gslString = getVal("gsl");
- if (gslString.equals("unstable"))
- gsl = kUnstableGame;
- else if (gslString.equals("testing"))
- gsl = kTestingGame;
+DetectedGames DetectionResults::listRecognizedGames() {
+ DetectedGames candidates;
+ for (uint i = 0; i < _detectedGames.size(); i++) {
+ if (_detectedGames[i].canBeAdded) {
+ candidates.push_back(_detectedGames[i]);
+ }
}
- return gsl;
+ return candidates;
}
-void GameDescriptor::setSupportLevel(GameSupportLevel gsl) {
- switch (gsl) {
- case kUnstableGame:
- setVal("gsl", "unstable");
- break;
- case kTestingGame:
- setVal("gsl", "testing");
- break;
- case kStableGame:
- // Fall Through intended
- default:
- erase("gsl");
+Common::String DetectionResults::generateUnknownGameReport(bool translate, uint32 wordwrapAt) const {
+ assert(!_detectedGames.empty());
+
+ const char *reportStart = _s("The game in '%s' seems to be an unknown game variant.\n\n"
+ "Please report the following data to the ScummVM team at %s "
+ "along with the name of the game you tried to add and "
+ "its version, language, etc.:");
+ const char *reportEngineHeader = _s("Matched game IDs for the %s engine:");
+
+ Common::String report = Common::String::format(
+ translate ? _(reportStart) : reportStart, _detectedGames[0].path.c_str(),
+ "https://bugs.scummvm.org/"
+ );
+ report += "\n";
+
+ FilePropertiesMap matchedFiles;
+
+ const char *currentEngineName = nullptr;
+ for (uint i = 0; i < _detectedGames.size(); i++) {
+ const DetectedGame &game = _detectedGames[i];
+
+ if (!game.hasUnknownFiles) continue;
+
+ if (!currentEngineName || strcmp(currentEngineName, game.engineName) != 0) {
+ currentEngineName = game.engineName;
+
+ // If the engine is not the same as for the previous entry, print an engine line header
+ report += "\n";
+ report += Common::String::format(
+ translate ? _(reportEngineHeader) : reportEngineHeader,
+ game.engineName
+ );
+ report += " ";
+
+ } else {
+ report += ", ";
+ }
+
+ // Add the gameId to the list of matched games for the engine
+ // TODO: Use the gameId here instead of the preferred target.
+ // This is currently impossible due to the AD singleId feature losing the information.
+ report += game.preferredTarget;
+
+ // Consolidate matched files across all engines and detection entries
+ for (FilePropertiesMap::const_iterator it = game.matchedFiles.begin(); it != game.matchedFiles.end(); it++) {
+ matchedFiles.setVal(it->_key, it->_value);
+ }
+ }
+
+ if (wordwrapAt) {
+ report.wordWrap(wordwrapAt);
}
+
+ report += "\n\n";
+
+ for (FilePropertiesMap::const_iterator file = matchedFiles.begin(); file != matchedFiles.end(); ++file)
+ report += Common::String::format(" {\"%s\", 0, \"%s\", %d},\n", file->_key.c_str(), file->_value.md5.c_str(), file->_value.size);
+
+ report += "\n";
+
+ return report;
}
diff --git a/engines/game.h b/engines/game.h
index e01e5c6885..14f9962ce6 100644
--- a/engines/game.h
+++ b/engines/game.h
@@ -38,6 +38,9 @@
struct PlainGameDescriptor {
const char *gameId;
const char *description;
+
+ static PlainGameDescriptor empty();
+ static PlainGameDescriptor of(const char *gameId, const char *description);
};
/**
@@ -47,6 +50,18 @@ struct PlainGameDescriptor {
*/
const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list);
+class PlainGameList : public Common::Array<PlainGameDescriptor> {
+public:
+ PlainGameList() {}
+ PlainGameList(const PlainGameList &list) : Common::Array<PlainGameDescriptor>(list) {}
+ PlainGameList(const PlainGameDescriptor *g) {
+ while (g->gameId) {
+ push_back(*g);
+ g++;
+ }
+ }
+};
+
/**
* Ths is an enum to describe how done a game is. This also indicates what level of support is expected.
*/
@@ -56,63 +71,138 @@ enum GameSupportLevel {
kUnstableGame // the game is not even ready for public testing yet
};
+
/**
- * A hashmap describing details about a given game. In a sense this is a refined
- * version of PlainGameDescriptor, as it also contains a gameid and a description string.
- * But in addition, platform and language settings, as well as arbitrary other settings,
- * can be contained in a GameDescriptor.
- * This is an essential part of the glue between the game engines and the launcher code.
+ * A record describing the properties of a file. Used on the existing
+ * files while detecting a game.
*/
-class GameDescriptor : public Common::StringMap {
-public:
- GameDescriptor();
- GameDescriptor(const PlainGameDescriptor &pgd, Common::String guioptions = Common::String());
- GameDescriptor(const Common::String &gameid,
- const Common::String &description,
- Common::Language language = Common::UNK_LANG,
- Common::Platform platform = Common::kPlatformUnknown,
- Common::String guioptions = Common::String(),
- GameSupportLevel gsl = kStableGame);
+struct FileProperties {
+ int32 size;
+ Common::String md5;
+
+ FileProperties() : size(-1) {}
+};
+
+/**
+ * A map of all relevant existing files while detecting.
+ */
+typedef Common::HashMap<Common::String, FileProperties, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FilePropertiesMap;
+
+/**
+ * Details about a given game.
+ *
+ * While PlainGameDescriptor refers to a game supported by an engine, this refers to a game copy
+ * that has been detected by an engine's detector.
+ * It contains all the necessary data to add the game to the configuration manager and / or to launch it.
+ */
+struct DetectedGame {
+ DetectedGame();
+ explicit DetectedGame(const PlainGameDescriptor &pgd);
+ DetectedGame(const Common::String &id,
+ const Common::String &description,
+ Common::Language language = Common::UNK_LANG,
+ Common::Platform platform = Common::kPlatformUnknown,
+ const Common::String &extra = Common::String());
+
+ void setGUIOptions(const Common::String &options);
+ void appendGUIOptions(const Common::String &str);
+ Common::String getGUIOptions() const { return _guiOptions; }
/**
- * Update the description string by appending (EXTRA/PLATFORM/LANG) to it.
- * Values that are missing are omitted, so e.g. (EXTRA/LANG) would be
- * added if no platform has been specified but a language and an extra string.
+ * The name of the engine supporting the detected game
*/
- void updateDesc(const char *extra = 0);
+ const char *engineName;
- void setGUIOptions(Common::String options);
- void appendGUIOptions(const Common::String &str);
+ /**
+ * A game was detected, but some files were not recognized
+ *
+ * This can happen when the md5 or size of the detected files did not match the engine's detection tables.
+ * When this is true, the list of matched files below contains detail about the unknown files.
+ *
+ * @see matchedFiles
+ */
+ bool hasUnknownFiles;
+
+ /**
+ * An optional list of the files that were used to match the game with the engine's detection tables
+ */
+ FilePropertiesMap matchedFiles;
+
+ /**
+ * This detection entry contains enough data to add the game to the configuration manager and launch it
+ *
+ * @see matchedGame
+ */
+ bool canBeAdded;
+
+ Common::String gameId;
+ Common::String preferredTarget;
+ Common::String description;
+ Common::Language language;
+ Common::Platform platform;
+ Common::String path;
+ Common::String extra;
/**
* What level of support is expected of this game
*/
- GameSupportLevel getSupportLevel();
- void setSupportLevel(GameSupportLevel gsl);
-
- Common::String &gameid() { return getVal("gameid"); }
- Common::String &description() { return getVal("description"); }
- const Common::String &gameid() const { return getVal("gameid"); }
- const Common::String &description() const { return getVal("description"); }
- Common::Language language() const { return contains("language") ? Common::parseLanguage(getVal("language")) : Common::UNK_LANG; }
- Common::Platform platform() const { return contains("platform") ? Common::parsePlatform(getVal("platform")) : Common::kPlatformUnknown; }
-
- const Common::String &preferredtarget() const {
- return contains("preferredtarget") ? getVal("preferredtarget") : getVal("gameid");
- }
+ GameSupportLevel gameSupportLevel;
+
+private:
+ /**
+ * Update the description string by appending (EXTRA/PLATFORM/LANG) to it.
+ * Values that are missing are omitted, so e.g. (EXTRA/LANG) would be
+ * added if no platform has been specified but a language and an extra string.
+ */
+ Common::String updateDesc() const;
+
+ Common::String _guiOptions;
};
/** List of games. */
-class GameList : public Common::Array<GameDescriptor> {
+typedef Common::Array<DetectedGame> DetectedGames;
+
+/**
+ * Contains a list of games found by the engines' detectors.
+ *
+ * Each detected game can either:
+ * - be fully recognized (e.g. an exact match was found in the detection tables of an engine)
+ * - be an unknown variant (e.g. a game using files with the same name was found in the detection tables)
+ * - be recognized with unknown files (e.g. the game was exactly not found in the detection tables,
+ * but the detector was able to gather enough data to allow launching the game)
+ *
+ * Practically, this means a detected game can be in both the recognized game list and in the unknown game
+ * report handled by this class.
+ */
+class DetectionResults {
public:
- GameList() {}
- GameList(const GameList &list) : Common::Array<GameDescriptor>(list) {}
- GameList(const PlainGameDescriptor *g) {
- while (g->gameId) {
- push_back(GameDescriptor(*g));
- g++;
- }
- }
+ explicit DetectionResults(const DetectedGames &detectedGames);
+
+ /**
+ * List all the games that were recognized by the engines
+ *
+ * Recognized games can be added to the configuration manager and then launched.
+ */
+ DetectedGames listRecognizedGames();
+
+ /**
+ * Were unknown game variants found by the engines?
+ *
+ * When unknown game variants are found, an unknown game report can be generated.
+ */
+ bool foundUnknownGames() const;
+
+ /**
+ * Generate a report that we found an unknown game variant, together with the file
+ * names, sizes and MD5 sums.
+ *
+ * @param translate translate the report to the currently active GUI language
+ * @param wordwrapAt word wrap the text part of the report after a number of characters
+ */
+ Common::String generateUnknownGameReport(bool translate, uint32 wordwrapAt = 0) const;
+
+private:
+ DetectedGames _detectedGames;
};
#endif
diff --git a/engines/gnap/detection.cpp b/engines/gnap/detection.cpp
index d19d420ff8..97c9128002 100644
--- a/engines/gnap/detection.cpp
+++ b/engines/gnap/detection.cpp
@@ -141,13 +141,8 @@ SaveStateList GnapMetaEngine::listSaves(const char *target) const {
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
- Gnap::GnapEngine::readSavegameHeader(in, header);
- saveList.push_back(SaveStateDescriptor(slot, header._saveName));
-
- if (header._thumbnail) {
- header._thumbnail->free();
- delete header._thumbnail;
- }
+ if (Gnap::GnapEngine::readSavegameHeader(in, header))
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
delete in;
}
}
@@ -179,7 +174,11 @@ SaveStateDescriptor GnapMetaEngine::querySaveMetaInfos(const char *target, int s
SaveStateDescriptor desc(slot, saveName);
if (version != 1) {
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*file);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*file, thumbnail)) {
+ delete file;
+ return SaveStateDescriptor();
+ }
desc.setThumbnail(thumbnail);
}
diff --git a/engines/gnap/gnap.cpp b/engines/gnap/gnap.cpp
index cf8710c64d..9b0015e646 100644
--- a/engines/gnap/gnap.cpp
+++ b/engines/gnap/gnap.cpp
@@ -979,7 +979,7 @@ int GnapEngine::playSoundC() {
if (!_timers[_soundTimerIndexC]) {
_timers[_soundTimerIndexC] = getRandom(50) + 150;
- soundId = kSoundIdsC[getRandom(7)] ;
+ soundId = kSoundIdsC[getRandom(7)];
playSound(soundId | 0x10000, false);
}
return soundId;
diff --git a/engines/gnap/gnap.h b/engines/gnap/gnap.h
index dbefa31795..dd653304e7 100644
--- a/engines/gnap/gnap.h
+++ b/engines/gnap/gnap.h
@@ -319,7 +319,7 @@ public:
Common::String generateSaveName(int slot);
void synchronize(Common::Serializer &s);
void writeSavegameHeader(Common::OutSaveFile *out, GnapSavegameHeader &header);
- static bool readSavegameHeader(Common::InSaveFile *in, GnapSavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, GnapSavegameHeader &header, bool skipThumbnail = true);
void delayTicks(int val, int idx, bool updateCursor);
void delayTicksA(int val, int idx);
diff --git a/engines/gnap/menu.cpp b/engines/gnap/menu.cpp
index 9606273b4c..34b5f18473 100644
--- a/engines/gnap/menu.cpp
+++ b/engines/gnap/menu.cpp
@@ -589,9 +589,8 @@ void GnapEngine::writeSavegameHeader(Common::OutSaveFile *out, GnapSavegameHeade
out->writeSint16LE(td.tm_min);
}
-bool GnapEngine::readSavegameHeader(Common::InSaveFile *in, GnapSavegameHeader &header) {
+WARN_UNUSED_RESULT bool GnapEngine::readSavegameHeader(Common::InSaveFile *in, GnapSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
- header._thumbnail = nullptr;
// Validate the header Id
in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
@@ -612,9 +611,9 @@ bool GnapEngine::readSavegameHeader(Common::InSaveFile *in, GnapSavegameHeader &
if (header._version == 1)
header._thumbnail = nullptr;
else {
- header._thumbnail = Graphics::loadThumbnail(*in);
- if (!header._thumbnail)
+ if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) {
return false;
+ }
}
// Read in save date/time
diff --git a/engines/gob/detection/detection.cpp b/engines/gob/detection/detection.cpp
index e204ced1e8..864a701aa6 100644
--- a/engines/gob/detection/detection.cpp
+++ b/engines/gob/detection/detection.cpp
@@ -33,9 +33,9 @@ class GobMetaEngine : public AdvancedMetaEngine {
public:
GobMetaEngine();
- virtual GameDescriptor findGame(const char *gameId) const;
+ PlainGameDescriptor findGame(const char *gameId) const override;
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
virtual const char *getName() const;
virtual const char *getOriginalCopyright() const;
@@ -59,29 +59,26 @@ GobMetaEngine::GobMetaEngine() :
_guiOptions = GUIO1(GUIO_NOLAUNCHLOAD);
}
-GameDescriptor GobMetaEngine::findGame(const char *gameId) const {
+PlainGameDescriptor GobMetaEngine::findGame(const char *gameId) const {
return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
}
-const ADGameDescription *GobMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- ADFilePropertiesMap filesProps;
+ADDetectedGame GobMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADDetectedGame detectedGame = detectGameFilebased(allFiles, fslist, Gob::fileBased);
+ if (!detectedGame.desc) {
+ return ADDetectedGame();
+ }
- const Gob::GOBGameDescription *game;
- game = (const Gob::GOBGameDescription *)detectGameFilebased(allFiles, fslist, Gob::fileBased, &filesProps);
- if (!game)
- return 0;
+ const Gob::GOBGameDescription *game = (const Gob::GOBGameDescription *)detectedGame.desc;
if (game->gameType == Gob::kGameTypeOnceUponATime) {
game = detectOnceUponATime(fslist);
- if (!game)
- return 0;
+ if (game) {
+ detectedGame.desc = &game->desc;
+ }
}
- ADGameIdList gameIds;
- gameIds.push_back(game->desc.gameId);
-
- reportUnknown(fslist.begin()->getParent(), filesProps, gameIds);
- return (const ADGameDescription *)game;
+ return detectedGame;
}
const Gob::GOBGameDescription *GobMetaEngine::detectOnceUponATime(const Common::FSList &fslist) {
diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp
index 16977e0cb8..aff3c914f6 100644
--- a/engines/hopkins/computer.cpp
+++ b/engines/hopkins/computer.cpp
@@ -918,9 +918,9 @@ void ComputerManager::getScoreName() {
char score[16];
sprintf(score, "%d", _breakoutScore);
int scoreLen = 0;
- do
+ do {
++scoreLen;
- while (score[scoreLen]);
+ } while (score[scoreLen]);
for (int i = scoreLen - 1, scorePos = 8; i >= 0; i--) {
_score[scoreLine]._score.setChar(score[i], scorePos--);
diff --git a/engines/hopkins/detection.cpp b/engines/hopkins/detection.cpp
index 041afecaa8..ebefee6278 100644
--- a/engines/hopkins/detection.cpp
+++ b/engines/hopkins/detection.cpp
@@ -168,9 +168,6 @@ SaveStateList HopkinsMetaEngine::listSaves(const char *target) const {
if (in) {
if (Hopkins::SaveLoadManager::readSavegameHeader(in, header)) {
saveList.push_back(SaveStateDescriptor(slot, header._saveName));
-
- header._thumbnail->free();
- delete header._thumbnail;
}
delete in;
@@ -198,7 +195,11 @@ SaveStateDescriptor HopkinsMetaEngine::querySaveMetaInfos(const char *target, in
if (f) {
Hopkins::hopkinsSavegameHeader header;
- Hopkins::SaveLoadManager::readSavegameHeader(f, header);
+ if (!Hopkins::SaveLoadManager::readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
+
delete f;
// Create the return descriptor
diff --git a/engines/hopkins/dialogs.cpp b/engines/hopkins/dialogs.cpp
index fc613f892d..cabdc9e9ea 100644
--- a/engines/hopkins/dialogs.cpp
+++ b/engines/hopkins/dialogs.cpp
@@ -448,9 +448,9 @@ void DialogsManager::showInventory() {
_vm->_script->_tempObjectFl = false;
if (_vm->_soundMan->_voiceOffFl) {
- do
+ do {
_vm->_events->refreshScreenAndEvents();
- while (!_vm->_globals->_exitId && _vm->_events->getMouseButton() != 1);
+ } while (!_vm->_globals->_exitId && _vm->_events->getMouseButton() != 1);
_vm->_fontMan->hideText(9);
}
if (_vm->_globals->_exitId) {
@@ -692,7 +692,7 @@ void DialogsManager::showSaveLoad(SaveLoadMode mode) {
for (int slotNumber = 1; slotNumber <= 6; ++slotNumber) {
hopkinsSavegameHeader header;
- if (_vm->_saveLoad->readSavegameHeader(slotNumber, header)) {
+ if (_vm->_saveLoad->readSavegameHeader(slotNumber, header, false)) {
Graphics::Surface thumb8;
_vm->_saveLoad->convertThumb16To8(header._thumbnail, &thumb8);
diff --git a/engines/hopkins/font.cpp b/engines/hopkins/font.cpp
index 7d57f564a9..9d11c5a940 100644
--- a/engines/hopkins/font.cpp
+++ b/engines/hopkins/font.cpp
@@ -281,9 +281,9 @@ void FontManager::box(int idx, int messageId, const Common::String &filename, in
int ptrb = _boxWidth - 4;
for (;;) {
lineSize = curLineSize;
- do
+ do {
curChar = _tempText[tempTextIdx + curLineSize++];
- while (curChar != ' ' && curChar != '%');
+ } while (curChar != ' ' && curChar != '%');
if (curLineSize >= ptrb / _fontFixedWidth) {
if (curChar == '%')
curChar = ' ';
diff --git a/engines/hopkins/hopkins.cpp b/engines/hopkins/hopkins.cpp
index f28de39827..dd64c0cc71 100644
--- a/engines/hopkins/hopkins.cpp
+++ b/engines/hopkins/hopkins.cpp
@@ -314,9 +314,9 @@ bool HopkinsEngine::runWin95Demo() {
_graphicsMan->loadImage("ENDUK");
_graphicsMan->fadeInLong();
_events->mouseOn();
- do
+ do {
_events->refreshScreenAndEvents();
- while (_events->getMouseButton() != 1);
+ } while (_events->getMouseButton() != 1);
_graphicsMan->fadeOutLong();
restoreSystem();
} else
@@ -2047,9 +2047,9 @@ void HopkinsEngine::playUnderwaterBaseCutscene() {
_graphicsMan->fadeInLong();
_objectsMan->enableHidingBehavior();
- do
+ do {
_events->refreshScreenAndEvents();
- while (!shouldQuit() && _objectsMan->getBobAnimDataIdx(8) != 22);
+ } while (!shouldQuit() && _objectsMan->getBobAnimDataIdx(8) != 22);
if (!shouldQuit()) {
_graphicsMan->fadeOutLong();
@@ -2092,9 +2092,9 @@ void HopkinsEngine::playEnding() {
_graphicsMan->fadeInLong();
_globals->_eventMode = EVENTMODE_IGNORE;
- do
+ do {
_events->refreshScreenAndEvents();
- while (_objectsMan->getBobAnimDataIdx(6) != 54);
+ } while (_objectsMan->getBobAnimDataIdx(6) != 54);
_globals->_introSpeechOffFl = true;
_talkMan->startAnimatedCharacterDialogue("GM4.PE2");
@@ -2104,38 +2104,38 @@ void HopkinsEngine::playEnding() {
_objectsMan->setBobAnimation(9);
_objectsMan->setBobAnimation(7);
- do
+ do {
_events->refreshScreenAndEvents();
- while (_objectsMan->getBobAnimDataIdx(7) != 54);
+ } while (_objectsMan->getBobAnimDataIdx(7) != 54);
_soundMan->playSample(1);
- do
+ do {
_events->refreshScreenAndEvents();
- while (_objectsMan->getBobAnimDataIdx(7) != 65);
+ } while (_objectsMan->getBobAnimDataIdx(7) != 65);
_globals->_introSpeechOffFl = true;
_talkMan->startAnimatedCharacterDialogue("DUELB4.PE2");
_events->mouseOff();
_globals->_disableInventFl = true;
- do
+ do {
_events->refreshScreenAndEvents();
- while (_objectsMan->getBobAnimDataIdx(7) != 72);
+ } while (_objectsMan->getBobAnimDataIdx(7) != 72);
_globals->_introSpeechOffFl = true;
_talkMan->startAnimatedCharacterDialogue("DUELH1.PE2");
- do
+ do {
_events->refreshScreenAndEvents();
- while (_objectsMan->getBobAnimDataIdx(7) != 81);
+ } while (_objectsMan->getBobAnimDataIdx(7) != 81);
_globals->_introSpeechOffFl = true;
_talkMan->startAnimatedCharacterDialogue("DUELB5.PE2");
- do
+ do {
_events->refreshScreenAndEvents();
- while (_objectsMan->getBobAnimDataIdx(7) != 120);
+ } while (_objectsMan->getBobAnimDataIdx(7) != 120);
_objectsMan->stopBobAnimation(7);
if (_globals->_saveData->_data[svGameWonFl] == 1) {
@@ -2150,9 +2150,9 @@ void HopkinsEngine::playEnding() {
_events->_rateCounter = 0;
if (!_events->_escKeyFl) {
- do
+ do {
_events->refreshEvents();
- while (_events->_rateCounter < 2000 / _globals->_speed && !_events->_escKeyFl);
+ } while (_events->_rateCounter < 2000 / _globals->_speed && !_events->_escKeyFl);
}
_events->_escKeyFl = false;
_graphicsMan->fadeOutLong();
@@ -2184,15 +2184,15 @@ void HopkinsEngine::playEnding() {
_talkMan->startAnimatedCharacterDialogue("GM5.PE2");
_globals->_disableInventFl = true;
- do
+ do {
_events->refreshScreenAndEvents();
- while (_objectsMan->getBobAnimDataIdx(8) != 5);
+ } while (_objectsMan->getBobAnimDataIdx(8) != 5);
_soundMan->directPlayWav("SOUND41.WAV");
- do
+ do {
_events->refreshScreenAndEvents();
- while (_objectsMan->getBobAnimDataIdx(8) != 21);
+ } while (_objectsMan->getBobAnimDataIdx(8) != 21);
_graphicsMan->fadeOutLong();
_graphicsMan->endDisplayBob();
diff --git a/engines/hopkins/objects.cpp b/engines/hopkins/objects.cpp
index b54b21bbc9..d67cd7b60c 100644
--- a/engines/hopkins/objects.cpp
+++ b/engines/hopkins/objects.cpp
@@ -2761,9 +2761,9 @@ void ObjectsManager::handleSpecialGames() {
break;
_vm->_globals->_disableInventFl = true;
- do
+ do {
_vm->_events->refreshScreenAndEvents();
- while (getBobAnimDataIdx(8) != 3);
+ } while (getBobAnimDataIdx(8) != 3);
_vm->_globals->_introSpeechOffFl = true;
_vm->_talkMan->startAnimatedCharacterDialogue("GM3.PE2");
stopBobAnimation(8);
diff --git a/engines/hopkins/saveload.cpp b/engines/hopkins/saveload.cpp
index 05c7fb8119..35a80458ff 100644
--- a/engines/hopkins/saveload.cpp
+++ b/engines/hopkins/saveload.cpp
@@ -77,9 +77,8 @@ void SaveLoadManager::load(const Common::String &file, byte *buf) {
delete savefile;
}
-bool SaveLoadManager::readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header) {
+WARN_UNUSED_RESULT bool SaveLoadManager::readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
- header._thumbnail = NULL;
// Validate the header Id
in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
@@ -96,9 +95,9 @@ bool SaveLoadManager::readSavegameHeader(Common::InSaveFile *in, hopkinsSavegame
while ((ch = (char)in->readByte()) != '\0') header._saveName += ch;
// Get the thumbnail
- header._thumbnail = Graphics::loadThumbnail(*in);
- if (!header._thumbnail)
+ if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
header._year = in->readSint16LE();
@@ -186,10 +185,10 @@ Common::Error SaveLoadManager::loadGame(int slot) {
// Read in the savegame header
hopkinsSavegameHeader header;
- readSavegameHeader(savefile, header);
- if (header._thumbnail)
- header._thumbnail->free();
- delete header._thumbnail;
+ if (!readSavegameHeader(savefile, header)) {
+ delete savefile;
+ return Common::kReadingFailed;
+ }
// Read in the savegame data
syncSavegameData(serializer, header._version);
@@ -212,14 +211,14 @@ Common::Error SaveLoadManager::loadGame(int slot) {
return Common::kNoError;
}
-bool SaveLoadManager::readSavegameHeader(int slot, hopkinsSavegameHeader &header) {
+WARN_UNUSED_RESULT bool SaveLoadManager::readSavegameHeader(int slot, hopkinsSavegameHeader &header, bool skipThumbnail) {
// Try and open the save file for reading
Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(
_vm->generateSaveName(slot));
if (!savefile)
return false;
- bool result = readSavegameHeader(savefile, header);
+ bool result = readSavegameHeader(savefile, header, skipThumbnail);
delete savefile;
return result;
}
diff --git a/engines/hopkins/saveload.h b/engines/hopkins/saveload.h
index 7b4ec307f5..33234f49fa 100644
--- a/engines/hopkins/saveload.h
+++ b/engines/hopkins/saveload.h
@@ -61,9 +61,9 @@ public:
bool saveFile(const Common::String &file, const void *buf, size_t n);
void load(const Common::String &file, byte *buf);
- static bool readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, hopkinsSavegameHeader &header, bool skipThumbnail = true);
void writeSavegameHeader(Common::OutSaveFile *out, hopkinsSavegameHeader &header);
- bool readSavegameHeader(int slot, hopkinsSavegameHeader &header);
+ WARN_UNUSED_RESULT bool readSavegameHeader(int slot, hopkinsSavegameHeader &header, bool skipThumbnail = true);
Common::Error saveGame(int slot, const Common::String &saveName);
Common::Error loadGame(int slot);
diff --git a/engines/hopkins/talk.cpp b/engines/hopkins/talk.cpp
index 00c4ab0332..f3cd6bd026 100644
--- a/engines/hopkins/talk.cpp
+++ b/engines/hopkins/talk.cpp
@@ -120,9 +120,9 @@ void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename)
if (_vm->_globals->_introSpeechOffFl) {
int idx = 1;
int answer;
- do
+ do {
answer = dialogAnswer(idx++, false);
- while (answer != -1);
+ } while (answer != -1);
}
clearCharacterAnim();
_vm->_globals->_introSpeechOffFl = false;
@@ -208,9 +208,9 @@ void TalkManager::startStaticCharacterDialogue(const Common::String &filename) {
if (_vm->_globals->_introSpeechOffFl) {
int idx = 1;
int answer;
- do
+ do {
answer = dialogAnswer(idx++, true);
- while (answer != -1);
+ } while (answer != -1);
}
_characterBuffer = _vm->_globals->freeMemory(_characterBuffer);
@@ -879,9 +879,9 @@ void TalkManager::handleForestAnswser(int zone, int verb) {
_vm->_objectsMan->setBobAnimation(6);
_vm->_soundMan->playSample(1);
_vm->_objectsMan->showSpecialActionAnimation(_vm->_objectsMan->_forestSprite, "13,14,15,14,13,12,13,14,15,16,-1,", 4);
- do
+ do {
_vm->_events->refreshScreenAndEvents();
- while (_vm->_objectsMan->getBobAnimDataIdx(6) < 12);
+ } while (_vm->_objectsMan->getBobAnimDataIdx(6) < 12);
_vm->_objectsMan->stopBobAnimation(6);
_vm->_objectsMan->setBobAnimation(8);
@@ -927,9 +927,9 @@ void TalkManager::handleForestAnswser(int zone, int verb) {
_vm->_objectsMan->setBobAnimation(5);
_vm->_soundMan->playSample(1);
_vm->_objectsMan->showSpecialActionAnimation(_vm->_objectsMan->_forestSprite, "13,14,15,14,13,12,13,14,15,16,-1,", 4);
- do
+ do {
_vm->_events->refreshScreenAndEvents();
- while (_vm->_objectsMan->getBobAnimDataIdx(5) < 12);
+ } while (_vm->_objectsMan->getBobAnimDataIdx(5) < 12);
_vm->_objectsMan->stopBobAnimation(5);
_vm->_objectsMan->setBobAnimation(7);
switch (_vm->_globals->_screenId) {
diff --git a/engines/hugo/detection.cpp b/engines/hugo/detection.cpp
index 4e4746c002..6d2fec5421 100644
--- a/engines/hugo/detection.cpp
+++ b/engines/hugo/detection.cpp
@@ -241,7 +241,12 @@ SaveStateDescriptor HugoMetaEngine::querySaveMetaInfos(const char *target, int s
SaveStateDescriptor desc(slot, saveName);
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*file);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*file, thumbnail)) {
+ warning("Missing or broken savegame thumbnail");
+ delete file;
+ return SaveStateDescriptor();
+ }
desc.setThumbnail(thumbnail);
uint32 saveDate = file->readUint32BE();
diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp
index 5f6892bd20..ed82c04d7d 100644
--- a/engines/hugo/hugo.cpp
+++ b/engines/hugo/hugo.cpp
@@ -638,7 +638,6 @@ void HugoEngine::initialize() {
calcMaxScore(); // Initialize maxscore
_rnd = new Common::RandomSource("hugo");
- _rnd->setSeed(42); // Kick random number generator
switch (_gameVariant) {
case kGameVariantH1Dos:
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 70c7e7c93c..79e1d9f494 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -256,7 +256,7 @@ SaveStateList KyraMetaEngine::listSaves(const char *target) const {
if (slotNum >= 0 && slotNum <= 999) {
Common::InSaveFile *in = saveFileMan->openForLoading(*file);
if (in) {
- if (Kyra::KyraEngine_v1::readSaveHeader(in, false, header) == Kyra::KyraEngine_v1::kRSHENoError) {
+ if (Kyra::KyraEngine_v1::readSaveHeader(in, header) == Kyra::KyraEngine_v1::kRSHENoError) {
// WORKAROUND: Old savegames are using 'German' as description for kyra3 restart game save (slot 0),
// since that looks odd we replace it by "New Game".
if (slotNum == 0 && header.gameID == Kyra::GI_KYRA3)
@@ -298,7 +298,7 @@ SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int s
Kyra::KyraEngine_v1::SaveHeader header;
Kyra::KyraEngine_v1::ReadSaveHeaderError error;
- error = Kyra::KyraEngine_v1::readSaveHeader(in, true, header);
+ error = Kyra::KyraEngine_v1::readSaveHeader(in, header, false);
delete in;
if (error == Kyra::KyraEngine_v1::kRSHENoError) {
diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h
index 1401d59dae..d214da0944 100644
--- a/engines/kyra/eobcommon.h
+++ b/engines/kyra/eobcommon.h
@@ -885,7 +885,7 @@ protected:
void inflictMonsterDamage(EoBMonsterInPlay *m, int damage, bool giveExperience);
void calcAndInflictMonsterDamage(EoBMonsterInPlay *m, int times, int pips, int offs, int flags, int savingThrowType, int savingThrowEffect);
void calcAndInflictCharacterDamage(int charIndex, int times, int itemOrPips, int useStrModifierOrBase, int flags, int savingThrowType, int savingThrowEffect);
- int calcCharacterDamage(int charIndex, int times, int itemOrPips, int useStrModifierOrBase, int flags, int savingThrowType, int damageType) ;
+ int calcCharacterDamage(int charIndex, int times, int itemOrPips, int useStrModifierOrBase, int flags, int savingThrowType, int damageType);
void inflictCharacterDamage(int charIndex, int damage);
bool characterAttackHitTest(int charIndex, int monsterIndex, int item, int attackType);
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index 4de7494510..bbbd59a4b8 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -416,7 +416,7 @@ protected:
kRSHEIoError = 3
};
- static ReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, bool loadThumbnail, SaveHeader &header);
+ WARN_UNUSED_RESULT static ReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *file, SaveHeader &header, bool skipThumbnail = true);
void loadGameStateCheck(int slot);
virtual Common::Error loadGameState(int slot) = 0;
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index b44850f5c9..c306d6cb5d 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -37,12 +37,11 @@
namespace Kyra {
-KyraEngine_v1::ReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) {
+WARN_UNUSED_RESULT KyraEngine_v1::ReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail) {
uint32 type = in->readUint32BE();
header.originalSave = false;
header.oldHeader = false;
header.flags = 0;
- header.thumbnail = 0;
if (type == MKTAG('K', 'Y', 'R', 'A') || type == MKTAG('A', 'R', 'Y', 'K')) { // old Kyra1 header ID
header.gameID = GI_KYRA1;
@@ -125,10 +124,8 @@ KyraEngine_v1::ReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekabl
header.flags = in->readUint32BE();
if (header.version >= 14) {
- if (loadThumbnail) {
- header.thumbnail = Graphics::loadThumbnail(*in);
- } else {
- Graphics::skipThumbnail(*in);
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
+ return kRSHEIoError;
}
}
@@ -140,7 +137,7 @@ Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filena
if (!(in = _saveFileMan->openForLoading(filename)))
return 0;
- ReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, false, header);
+ ReadSaveHeaderError errorCode = KyraEngine_v1::readSaveHeader(in, header);
if (errorCode != kRSHENoError) {
if (errorCode == kRSHEInvalidType)
warning("No ScummVM Kyra engine savefile header");
diff --git a/engines/kyra/screen_eob.cpp b/engines/kyra/screen_eob.cpp
index 6c1bd572e1..3a9a647fa5 100644
--- a/engines/kyra/screen_eob.cpp
+++ b/engines/kyra/screen_eob.cpp
@@ -499,7 +499,7 @@ void Screen_EoB::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y,
int16 dX = x - (_dsX1 << 3);
int16 dY = y;
int16 dW = _dsX2 - _dsX1;
- uint8 pixelsPerByte = *src++ ;
+ uint8 pixelsPerByte = *src++;
uint16 dH = *src++;
uint16 width = (*src++) << 3;
@@ -1211,7 +1211,7 @@ void Screen_EoB::createFadeTable(uint8 *palData, uint8 *dst, uint8 rootColor, ui
if (t <= v && (ii == rootColor || ii != i)) {
v = t;
- col = ii ;
+ col = ii;
}
}
*dst++ = col;
diff --git a/engines/kyra/sequences_darkmoon.cpp b/engines/kyra/sequences_darkmoon.cpp
index 53a30d0079..68d6f752e0 100644
--- a/engines/kyra/sequences_darkmoon.cpp
+++ b/engines/kyra/sequences_darkmoon.cpp
@@ -876,7 +876,7 @@ void DarkMoonEngine::seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *da
const uint8 *shp = sq->_shapes[(*++posOld) - 1];
items[i + 1].data = shp;
items[i + 1].size = shp[1];
- items[i + 1].x = (dm->w - shp[2]) << 2 ;
+ items[i + 1].x = (dm->w - shp[2]) << 2;
items[i + 1].dataType = 1;
delete[] items[i + 1].str;
items[i + 1].str = 0;
diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp
index 942cf16502..7ee1ad7e4b 100644
--- a/engines/kyra/sequences_hof.cpp
+++ b/engines/kyra/sequences_hof.cpp
@@ -3378,7 +3378,7 @@ void KyraEngine_HoF::seq_showStarcraftLogo() {
int KyraEngine_HoF::seq_playIntro() {
bool startupSaveLoadable = saveFileLoadable(0);
- return SeqPlayer_HOF(this, _screen, _system, startupSaveLoadable).play(kSequenceVirgin, startupSaveLoadable? kSequenceTitle : kSequenceNoLooping);
+ return SeqPlayer_HOF(this, _screen, _system, startupSaveLoadable).play(kSequenceVirgin, startupSaveLoadable ? kSequenceTitle : kSequenceNoLooping);
}
int KyraEngine_HoF::seq_playOutro() {
diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp
index 58484c2fd9..a8091c9d41 100644
--- a/engines/kyra/sequences_lok.cpp
+++ b/engines/kyra/sequences_lok.cpp
@@ -785,6 +785,8 @@ void KyraEngine_LoK::seq_dispelMagicAnimation() {
return;
}
_screen->hideMouse();
+ // TODO
+ // This condition is always false. Is this a typo or a bug in the original?
if (_currentCharacter->sceneId == 210 && _currentCharacter->sceneId < 160)
_currentCharacter->facing = 3;
if (_malcolmFlag == 7 && _beadStateVar == 3) {
diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp
index a1600f6464..551d79cc55 100644
--- a/engines/kyra/sound_digital.cpp
+++ b/engines/kyra/sound_digital.cpp
@@ -30,6 +30,8 @@
#include "audio/decoders/vorbis.h"
#include "audio/decoders/flac.h"
+#include "common/util.h"
+
namespace Kyra {
class KyraAudioStream : public Audio::SeekableAudioStream {
@@ -203,11 +205,7 @@ int AUDStream::readBuffer(int16 *buffer, const int numSamples) {
}
inline int16 clip8BitSample(int16 sample) {
- if (sample > 255)
- return 255;
- if (sample < 0)
- return 0;
- return sample;
+ return CLIP<int16>(sample, 0, 255);
}
int AUDStream::readChunk(int16 *buffer, const int maxSamples) {
diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h
index 4b77bf1351..3559133cb1 100644
--- a/engines/kyra/sound_intern.h
+++ b/engines/kyra/sound_intern.h
@@ -169,24 +169,24 @@ public:
SoundPC98(KyraEngine_v1 *vm, Audio::Mixer *mixer);
virtual ~SoundPC98();
- virtual kType getMusicType() const { return kPC98; }
+ virtual kType getMusicType() const override { return kPC98; }
- virtual bool init();
+ virtual bool init() override;
- virtual void initAudioResourceInfo(int set, void *info);
- virtual void selectAudioResourceSet(int set);
- virtual bool hasSoundFile(uint file) const;
- virtual void loadSoundFile(uint file);
- virtual void loadSoundFile(Common::String file);
+ virtual void initAudioResourceInfo(int set, void *info) override;
+ virtual void selectAudioResourceSet(int set) override;
+ virtual bool hasSoundFile(uint file) const override;
+ virtual void loadSoundFile(uint file) override;
+ virtual void loadSoundFile(Common::String file) override;
- virtual void playTrack(uint8 track);
- virtual void haltTrack();
- virtual void beginFadeOut();
+ virtual void playTrack(uint8 track) override;
+ virtual void haltTrack() override;
+ virtual void beginFadeOut() override;
virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) override { return -1; }
- virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF);
+ virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF) override;
- virtual void updateVolumeSettings();
+ virtual void updateVolumeSettings() override;
private:
int _lastTrack;
@@ -204,25 +204,25 @@ public:
SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer);
virtual ~SoundTownsPC98_v2();
- virtual kType getMusicType() const { return _vm->gameFlags().platform == Common::kPlatformFMTowns ? kTowns : kPC98; }
+ virtual kType getMusicType() const override { return _vm->gameFlags().platform == Common::kPlatformFMTowns ? kTowns : kPC98; }
- virtual bool init();
- virtual void process();
+ virtual bool init() override;
+ virtual void process() override;
- virtual void initAudioResourceInfo(int set, void *info);
- virtual void selectAudioResourceSet(int set);
- virtual bool hasSoundFile(uint file) const;
- virtual void loadSoundFile(uint file) {}
- virtual void loadSoundFile(Common::String file);
+ virtual void initAudioResourceInfo(int set, void *info) override;
+ virtual void selectAudioResourceSet(int set) override;
+ virtual bool hasSoundFile(uint file) const override;
+ virtual void loadSoundFile(uint file) override {}
+ virtual void loadSoundFile(Common::String file) override;
- virtual void playTrack(uint8 track);
- virtual void haltTrack();
- virtual void beginFadeOut();
+ virtual void playTrack(uint8 track) override;
+ virtual void haltTrack() override;
+ virtual void beginFadeOut() override;
virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume = 255, uint8 priority = 255, bool isSfx = true) override;
- virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF);
+ virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF) override;
- virtual void updateVolumeSettings();
+ virtual void updateVolumeSettings() override;
private:
Audio::AudioStream *_currentSFX;
@@ -320,22 +320,22 @@ public:
SoundAmiga(KyraEngine_v1 *vm, Audio::Mixer *mixer);
virtual ~SoundAmiga();
- virtual kType getMusicType() const { return kAmiga; } //FIXME
+ virtual kType getMusicType() const override { return kAmiga; } //FIXME
- virtual bool init();
+ virtual bool init() override;
- virtual void initAudioResourceInfo(int set, void *info);
- virtual void selectAudioResourceSet(int set);
- virtual bool hasSoundFile(uint file) const;
- virtual void loadSoundFile(uint file);
- virtual void loadSoundFile(Common::String) {}
+ virtual void initAudioResourceInfo(int set, void *info) override;
+ virtual void selectAudioResourceSet(int set) override;
+ virtual bool hasSoundFile(uint file) const override;
+ virtual void loadSoundFile(uint file) override;
+ virtual void loadSoundFile(Common::String) override {}
- virtual void playTrack(uint8 track);
- virtual void haltTrack();
- virtual void beginFadeOut();
+ virtual void playTrack(uint8 track) override;
+ virtual void haltTrack() override;
+ virtual void beginFadeOut() override;
virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) override { return -1; }
- virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF);
+ virtual void playSoundEffect(uint8 track, uint8 volume = 0xFF) override;
protected:
Audio::MaxTrax *_driver;
diff --git a/engines/lab/lab.h b/engines/lab/lab.h
index 2a1e527098..aedf0181ec 100644
--- a/engines/lab/lab.h
+++ b/engines/lab/lab.h
@@ -502,7 +502,7 @@ private:
void handleTrialWarning();
};
-bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header);
+WARN_UNUSED_RESULT bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header, bool skipThumbnail = true);
} // End of namespace Lab
diff --git a/engines/lab/map.cpp b/engines/lab/map.cpp
index 057cac3589..a856b76885 100644
--- a/engines/lab/map.cpp
+++ b/engines/lab/map.cpp
@@ -367,13 +367,11 @@ void LabEngine::drawMap(uint16 curRoom, uint16 curMsg, uint16 floorNum, bool fad
_imgHugeMaze->drawImage(_utils->mapScaleX(524), _utils->mapScaleY(97));
} else if (floorNum == kFloorSurMaze) {
Common::Rect textRect = Common::Rect(_utils->mapScaleX(360), 0, _utils->mapScaleX(660), _utils->mapScaleY(450));
- const char *textPtr = _resource->getStaticText(kTextSurmazeMessage).c_str();
- _graphics->flowText(_msgFont, 0, 7, 0, true, true, true, true, textRect, textPtr);
+ _graphics->flowText(_msgFont, 0, 7, 0, true, true, true, true, textRect, _resource->getStaticText(kTextSurmazeMessage).c_str());
}
if ((floorNum >= kFloorLower) && (floorNum <= kFloorCarnival)) {
- const char *textPrt = _resource->getStaticText(floorNum - 1).c_str();
- _graphics->flowText(_msgFont, 0, 5, 3, true, true, true, true, _utils->vgaRectScale(14, 75, 134, 97), textPrt);
+ _graphics->flowText(_msgFont, 0, 5, 3, true, true, true, true, _utils->vgaRectScale(14, 75, 134, 97), _resource->getStaticText(floorNum - 1).c_str());
}
if (!_rooms[curMsg]._roomMsg.empty())
diff --git a/engines/lab/savegame.cpp b/engines/lab/savegame.cpp
index 656595e3e5..46ef1486f0 100644
--- a/engines/lab/savegame.cpp
+++ b/engines/lab/savegame.cpp
@@ -76,7 +76,7 @@ void LabEngine::writeSaveGameHeader(Common::OutSaveFile *out, const Common::Stri
out->writeUint32BE(playTime);
}
-bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) {
+WARN_UNUSED_RESULT bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header, bool skipThumbnail) {
uint32 id = in->readUint32BE();
// Check if it's a valid ScummVM savegame
@@ -98,7 +98,11 @@ bool readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) {
header._descr.setDescription(saveName);
// Get the thumbnail
- header._descr.setThumbnail(Graphics::loadThumbnail(*in));
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*in, thumbnail, skipThumbnail)) {
+ return false;
+ }
+ header._descr.setThumbnail(thumbnail);
uint32 saveDate = in->readUint32BE();
uint16 saveTime = in->readUint16BE();
@@ -174,7 +178,11 @@ bool LabEngine::loadGame(int slot) {
return false;
SaveGameHeader header;
- readSaveGameHeader(file, header);
+ if (!readSaveGameHeader(file, header)) {
+ delete file;
+ return false;
+ }
+
_roomNum = file->readUint16LE();
_music->checkRoomMusic(1, _roomNum);
_direction = file->readUint16LE();
diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp
index cbd2a4a819..3a17cec6df 100644
--- a/engines/lastexpress/menu/menu.cpp
+++ b/engines/lastexpress/menu/menu.cpp
@@ -434,7 +434,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
case kMenuCase4:
if (clicked)
_index = 0;
- // fall down to kMenuContinue
+ // fall through
//////////////////////////////////////////////////////////////////////////
case kMenuContinue: {
diff --git a/engines/lilliput/configure.engine b/engines/lilliput/configure.engine
new file mode 100644
index 0000000000..0b912f7dc8
--- /dev/null
+++ b/engines/lilliput/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 lilliput "Lilliput" no
diff --git a/engines/lilliput/console.cpp b/engines/lilliput/console.cpp
new file mode 100644
index 0000000000..e7746a01bb
--- /dev/null
+++ b/engines/lilliput/console.cpp
@@ -0,0 +1,34 @@
+/* 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 "lilliput/console.h"
+#include "lilliput/lilliput.h"
+
+namespace Lilliput {
+
+LilliputConsole::LilliputConsole(LilliputEngine *vm) : GUI::Debugger(), _vm(vm) {
+}
+
+LilliputConsole::~LilliputConsole() {
+}
+
+} // End of namespace Lilliput
diff --git a/engines/lilliput/console.h b/engines/lilliput/console.h
new file mode 100644
index 0000000000..cd7edb3f42
--- /dev/null
+++ b/engines/lilliput/console.h
@@ -0,0 +1,49 @@
+/* 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 LILLIPUT_CONSOLE_H
+#define LILLIPUT_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace Lilliput {
+
+class LilliputEngine;
+
+class LilliputConsole : public GUI::Debugger {
+public:
+ LilliputConsole(LilliputEngine *vm);
+ virtual ~LilliputConsole(void);
+
+private:
+ LilliputEngine *_vm;
+ bool Cmd_listScreens(int argc, const char **argv);
+ bool Cmd_listObjects(int argc, const char **argv);
+ bool Cmd_getObject(int argc, const char **argv);
+ bool Cmd_getAllObjects(int argc, const char **argv);
+ bool Cmd_gotoScreen(int argc, const char **argv);
+ bool Cmd_boundaries(int argc, const char **argv);
+};
+
+} // End of namespace Lilliput
+
+#endif
diff --git a/engines/lilliput/detection.cpp b/engines/lilliput/detection.cpp
new file mode 100644
index 0000000000..eb65ad2d64
--- /dev/null
+++ b/engines/lilliput/detection.cpp
@@ -0,0 +1,292 @@
+/* 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 "engines/advancedDetector.h"
+#include "common/system.h"
+#include "common/savefile.h"
+#include "common/textconsole.h"
+#include "graphics/thumbnail.h"
+#include "graphics/surface.h"
+
+#include "lilliput/lilliput.h"
+
+namespace Lilliput {
+
+struct LilliputGameDescription {
+ ADGameDescription desc;
+ GameType gameType;
+};
+
+uint32 LilliputEngine::getFeatures() const {
+ return _gameDescription->desc.flags;
+}
+
+const char *LilliputEngine::getGameId() const {
+ return _gameDescription->desc.gameId;
+}
+
+
+static const PlainGameDescriptor lilliputGames[] = {
+ // Games
+ {"robin", "Adventures of Robin Hood"},
+ {"rome", "Rome: Pathway to Power"},
+ {0, 0}
+};
+
+static const LilliputGameDescription gameDescriptions[] = {
+
+ // Robin Hood English
+ {
+ {
+ "robin", 0,
+ {
+ {"erules.prg", 0, "92aaf84693a8948497ad57864fa31c2a", 71010},
+ {"isomap.dta", 0, "bad97eae03a4db3e99565e39b0b3c06a", 16384},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ kGameTypeRobin
+ },
+ // Robin Hood French
+ {
+ {
+ "robin", 0,
+ {
+ {"frules.prg", 0, "cf076c5ebfe8b3571e74a6a46d79426f", 76660},
+ {"isomap.dta", 0, "bad97eae03a4db3e99565e39b0b3c06a", 16384},
+ AD_LISTEND
+ },
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ kGameTypeRobin
+ },
+ // Robin Hood German
+ {
+ {
+ "robin", 0,
+ {
+ {"grules.prg", 0, "b53b7353dc1e841b206a64851e7bc58c", 78050},
+ {"isomap.dta", 0, "bad97eae03a4db3e99565e39b0b3c06a", 16384},
+ AD_LISTEND
+ },
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ kGameTypeRobin
+ },
+ // Robin Hood Italian
+ {
+ {
+ "robin", 0,
+ {
+ {"irules.prg", 0, "4d69ed3cda1e1d73585905517ea705d1", 75654},
+ {"isomap.dta", 0, "bad97eae03a4db3e99565e39b0b3c06a", 16384},
+ AD_LISTEND
+ },
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ kGameTypeRobin
+ },
+ {AD_TABLE_END_MARKER, kGameTypeNone}
+};
+
+class LilliputMetaEngine : public AdvancedMetaEngine {
+public:
+ LilliputMetaEngine() : AdvancedMetaEngine(gameDescriptions, sizeof(LilliputGameDescription), lilliputGames) {
+ }
+
+ const char *getName() const {
+ return "Lilliput";
+ }
+
+ const char *getOriginalCopyright() const {
+ return "Lilliput Engine copyright S.L.Grand, Brainware, 1991-1992";
+ }
+
+ bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const;
+ bool hasFeature(MetaEngineFeature f) const;
+
+ int getMaximumSaveSlot() const;
+ SaveStateList listSaves(const char *target) const;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+ void removeSaveState(const char *target, int slot) const;
+};
+
+bool LilliputMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const {
+ if (gd) {
+ *engine = new LilliputEngine(syst, (const LilliputGameDescription *)gd);
+ ((LilliputEngine *)*engine)->initGame((const LilliputGameDescription *)gd);
+ }
+ return gd != 0;
+}
+
+bool LilliputMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves) ||
+ (f == kSupportsLoadingDuringStartup) ||
+ (f == kSupportsDeleteSave) ||
+ (f == kSavesSupportMetaInfo) ||
+ (f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate);
+}
+
+int LilliputMetaEngine::getMaximumSaveSlot() const {
+ return 99;
+}
+
+SaveStateList LilliputMetaEngine::listSaves(const char *target) const {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String pattern = target;
+ pattern += "-##.SAV";
+
+ filenames = saveFileMan->listSavefiles(pattern);
+
+ SaveStateList saveList;
+ char slot[3];
+ int slotNum = 0;
+ for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
+ slot[0] = filename->c_str()[filename->size() - 6];
+ slot[1] = filename->c_str()[filename->size() - 5];
+ slot[2] = '\0';
+ // Obtain the last 2 digits of the filename (without extension), since they correspond to the save slot
+ slotNum = atoi(slot);
+ if (slotNum >= 0 && slotNum <= getMaximumSaveSlot()) {
+ Common::InSaveFile *file = saveFileMan->openForLoading(*filename);
+ if (file) {
+ int saveVersion = file->readByte();
+
+ if (saveVersion != kSavegameVersion) {
+ warning("Savegame of incompatible version");
+ delete file;
+ continue;
+ }
+
+ // read name
+ uint16 nameSize = file->readUint16BE();
+ if (nameSize >= 255) {
+ delete file;
+ continue;
+ }
+ char name[256];
+ file->read(name, nameSize);
+ name[nameSize] = 0;
+
+ saveList.push_back(SaveStateDescriptor(slotNum, name));
+ delete file;
+ }
+ }
+ }
+
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
+ return saveList;
+}
+
+SaveStateDescriptor LilliputMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s-%02d.SAV", target, slot);
+ Common::InSaveFile *file = g_system->getSavefileManager()->openForLoading(fileName);
+
+ if (file) {
+ int saveVersion = file->readByte();
+
+ if (saveVersion != kSavegameVersion) {
+ warning("Savegame of incompatible version");
+ delete file;
+ return SaveStateDescriptor();
+ }
+
+ uint32 saveNameLength = file->readUint16BE();
+ Common::String saveName;
+ for (uint32 i = 0; i < saveNameLength; ++i) {
+ char curChr = file->readByte();
+ saveName += curChr;
+ }
+
+ SaveStateDescriptor desc(slot, saveName);
+
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*file, thumbnail)) {
+ delete file;
+ return SaveStateDescriptor();
+ }
+ desc.setThumbnail(thumbnail);
+
+ desc.setDeletableFlag(true);
+ desc.setWriteProtectedFlag(false);
+
+ uint32 saveDate = file->readUint32BE();
+ uint16 saveTime = file->readUint16BE();
+
+ int day = (saveDate >> 24) & 0xFF;
+ int month = (saveDate >> 16) & 0xFF;
+ int year = saveDate & 0xFFFF;
+
+ desc.setSaveDate(year, month, day);
+
+ int hour = (saveTime >> 8) & 0xFF;
+ int minutes = saveTime & 0xFF;
+
+ desc.setSaveTime(hour, minutes);
+
+ // Slot 0 is used for the 'restart game' save in all Robin games, thus
+ // we prevent it from being deleted.
+ desc.setDeletableFlag(slot != 0);
+ desc.setWriteProtectedFlag(slot == 0);
+
+ delete file;
+ return desc;
+ }
+ return SaveStateDescriptor();
+}
+
+void LilliputMetaEngine::removeSaveState(const char *target, int slot) const {
+ Common::String fileName = Common::String::format("%s-%02d.SAV", target, slot);
+ g_system->getSavefileManager()->removeSavefile(fileName);
+}
+} // End of namespace Lilliput
+
+#if PLUGIN_ENABLED_DYNAMIC(LILLIPUT)
+REGISTER_PLUGIN_DYNAMIC(LILLIPUT, PLUGIN_TYPE_ENGINE, Lilliput::LilliputMetaEngine);
+#else
+REGISTER_PLUGIN_STATIC(LILLIPUT, PLUGIN_TYPE_ENGINE, Lilliput::LilliputMetaEngine);
+#endif
+
+namespace Lilliput {
+
+void LilliputEngine::initGame(const LilliputGameDescription *gd) {
+ _gameType = gd->gameType;
+ _platform = gd->desc.platform;
+}
+
+} // End of namespace Lilliput
diff --git a/engines/lilliput/lilliput.cpp b/engines/lilliput/lilliput.cpp
new file mode 100644
index 0000000000..e41ec36067
--- /dev/null
+++ b/engines/lilliput/lilliput.cpp
@@ -0,0 +1,2856 @@
+/* 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/random.h"
+#include "common/error.h"
+#include "common/debug-channels.h"
+#include "common/config-manager.h"
+#include "common/textconsole.h"
+#include "common/memstream.h"
+#include "common/events.h"
+#include "engines/util.h"
+#include "graphics/cursorman.h"
+
+#include "lilliput/lilliput.h"
+#include "engines/util.h"
+#include "lilliput/script.h"
+#include "lilliput/sound.h"
+
+namespace Lilliput {
+
+LilliputEngine *LilliputEngine::s_Engine = 0;
+
+static const byte _basisPalette[768] = {
+ 0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42,
+ 42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42,
+ 21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
+ 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
+ 63, 63, 63, 59, 59, 59, 54, 54, 54, 50, 50, 50,
+ 46, 46, 46, 42, 42, 42, 38, 38, 38, 33, 33, 33,
+ 29, 29, 29, 25, 25, 25, 21, 21, 21, 17, 17, 17,
+ 13, 13, 13, 8, 8, 8, 4, 4, 4, 0, 0, 0,
+ 63, 54, 54, 63, 46, 46, 63, 39, 39, 63, 31, 31,
+ 63, 23, 23, 63, 16, 16, 63, 8, 8, 63, 0, 0,
+ 57, 0, 0, 51, 0, 0, 45, 0, 0, 39, 0, 0,
+ 33, 0, 0, 28, 0, 0, 22, 0, 0, 16, 0, 0,
+ 63, 58, 54, 63, 54, 46, 63, 50, 39, 63, 46, 31,
+ 63, 42, 23, 63, 38, 16, 63, 34, 8, 63, 30, 0,
+ 57, 27, 0, 51, 24, 0, 45, 21, 0, 39, 19, 0,
+ 33, 16, 0, 28, 14, 0, 22, 11, 0, 16, 8, 0,
+ 63, 63, 54, 63, 63, 46, 63, 63, 39, 63, 63, 31,
+ 63, 62, 23, 63, 61, 16, 63, 61, 8, 63, 61, 0,
+ 57, 54, 0, 51, 49, 0, 45, 43, 0, 39, 39, 0,
+ 33, 33, 0, 28, 27, 0, 22, 21, 0, 16, 16, 0,
+ 62, 63, 54, 59, 61, 47, 56, 59, 42, 53, 58, 36,
+ 50, 56, 32, 47, 54, 26, 44, 52, 22, 41, 50, 17,
+ 36, 46, 14, 32, 42, 11, 28, 37, 8, 24, 33, 6,
+ 20, 29, 4, 16, 25, 2, 13, 20, 1, 10, 16, 0,
+ 54, 63, 54, 48, 61, 48, 43, 59, 43, 38, 58, 38,
+ 33, 56, 33, 29, 54, 29, 25, 52, 24, 21, 50, 20,
+ 16, 46, 16, 14, 42, 13, 10, 37, 9, 8, 33, 7,
+ 6, 29, 4, 4, 25, 2, 2, 20, 1, 1, 16, 0,
+ 59, 63, 63, 53, 63, 63, 47, 62, 63, 41, 61, 62,
+ 35, 60, 62, 30, 59, 62, 24, 57, 62, 18, 55, 62,
+ 20, 52, 56, 15, 47, 50, 11, 42, 45, 8, 37, 39,
+ 5, 32, 33, 3, 27, 27, 1, 22, 22, 0, 16, 16,
+ 54, 59, 63, 46, 56, 63, 39, 53, 63, 31, 50, 63,
+ 23, 47, 63, 16, 44, 63, 8, 42, 63, 0, 39, 63,
+ 0, 35, 57, 0, 31, 51, 0, 27, 45, 0, 23, 39,
+ 0, 19, 33, 0, 16, 28, 0, 12, 22, 0, 9, 16,
+ 54, 54, 63, 46, 47, 63, 39, 39, 63, 31, 32, 63,
+ 23, 24, 63, 16, 16, 63, 8, 9, 63, 0, 1, 63,
+ 0, 1, 57, 0, 1, 51, 0, 0, 45, 0, 0, 39,
+ 0, 0, 33, 0, 0, 28, 0, 0, 22, 0, 0, 16,
+ 54, 63, 54, 47, 63, 46, 39, 63, 39, 32, 63, 31,
+ 24, 63, 23, 16, 63, 16, 8, 63, 8, 0, 63, 0,
+ 0, 56, 0, 0, 49, 0, 0, 43, 0, 0, 36, 0,
+ 0, 30, 0, 0, 23, 0, 0, 16, 0, 0, 10, 0,
+ 63, 54, 63, 63, 46, 63, 63, 39, 63, 63, 31, 63,
+ 63, 23, 63, 63, 16, 63, 63, 8, 63, 63, 0, 63,
+ 56, 0, 57, 50, 0, 51, 45, 0, 45, 39, 0, 39,
+ 33, 0, 33, 27, 0, 28, 22, 0, 22, 16, 0, 16,
+ 63, 58, 55, 63, 56, 52, 63, 54, 49, 63, 53, 47,
+ 63, 51, 44, 63, 49, 41, 63, 47, 39, 63, 46, 36,
+ 63, 44, 32, 63, 41, 28, 63, 39, 24, 60, 37, 23,
+ 58, 35, 22, 55, 34, 21, 52, 32, 20, 50, 31, 19,
+ 47, 30, 18, 45, 28, 17, 42, 26, 16, 40, 25, 15,
+ 39, 24, 14, 36, 23, 13, 34, 22, 12, 32, 20, 11,
+ 29, 19, 10, 27, 18, 9, 23, 16, 8, 21, 15, 7,
+ 18, 14, 6, 16, 12, 6, 14, 11, 5, 10, 8, 3,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63
+};
+
+
+LilliputEngine::LilliputEngine(OSystem *syst, const LilliputGameDescription *gd) : Engine(syst), _gameDescription(gd) {
+ _system = syst;
+ DebugMan.addDebugChannel(kDebugEngine, "Engine", "Engine debug level");
+ DebugMan.addDebugChannel(kDebugScript, "Script", "Script debug level");
+ DebugMan.addDebugChannel(kDebugSound, "Sound", "Sound debug level");
+ DebugMan.addDebugChannel(kDebugEngineTBC, "EngineTBC", "Engine debug level");
+ DebugMan.addDebugChannel(kDebugScriptTBC, "ScriptTBC", "Script debug level");
+
+ _console = new LilliputConsole(this);
+ _rnd = 0;
+ _mousePos = Common::Point(0, 0);
+ _oldMousePos = Common::Point(0, 0);
+ _mouseDisplayPos = Common::Point(0, 0);
+ _mouseButton = 0;
+ _mouseClicked = false;
+ _savedMousePosDivided = Common::Point(-1, -1);
+ _mousePreviousEventType = Common::EVENT_INVALID;
+ _skipDisplayFlag1 = 1;
+ _skipDisplayFlag2 = 0;
+ _displayMap = false;
+ _debugFlag = 0;
+ _debugFlag2 = 0;
+
+ _scriptHandler = new LilliputScript(this);
+ _soundHandler = new LilliputSound(this);
+
+ _handleOpcodeReturnCode = 0;
+ _delayedReactivationAction = false;
+ _selectedCharacterId = -1;
+ _numCharactersToDisplay = 0;
+ _nextDisplayCharacterPos = Common::Point(0, 0);
+ _animationTick = 0;
+ _byte12A05 = 10; // Used to trigger sound and animations in int8, 1 time out of 10
+ _refreshScreenFlag = false;
+ _byte16552 = 0;
+ _lastInterfaceHotspotIndex = -1;
+ _lastInterfaceHotspotButton = 0;
+ _lastAnimationTick = 0;
+
+ _currentScriptCharacter = 0;
+ _currentScriptCharacterPos = Common::Point(0, 0);
+ _host = 0;
+ _nextCharacterIndex = 0;
+ _waitingSignal = -1;
+ _waitingSignalCharacterId = -1;
+ _newModesEvaluatedNumber = 0;
+ _savedSurfaceUnderMousePos = Common::Point(0, 0);
+ _displayGreenHand = false;
+ _isCursorGreenHand = false;
+ _displayStringIndex = 0;
+ _signalTimer = 0;
+ _numCharacters = 0;
+
+ _saveFlag = true;
+ _actionType = kActionNone;
+
+ _doorEntranceMask[0] = _doorExitMask[3] = 1;
+ _doorEntranceMask[1] = _doorExitMask[2] = 2;
+ _doorEntranceMask[2] = _doorExitMask[1] = 4;
+ _doorEntranceMask[3] = _doorExitMask[0] = 8;
+
+ for (int i = 0; i < 3; i++)
+ _codeEntered[i] = 0;
+
+ for (int i = 0; i < 4; i++)
+ _homeInDirLikelyhood[i] = 0;
+
+ for (int i = 0; i < 40; i++) {
+ _characterTargetPos[i] = Common::Point(0, 0);
+ _charactersToDisplay[i] = 0;
+ _characterRelativePos[i] = Common::Point(-1, -1);
+ _characterDisplay[i] = Common::Point(0, 0);
+ _characterMagicPuffFrame[i] = -1;
+ _characterSubTargetPos[i] = Common::Point(-1, -1);
+ _specialCubes[i] = 0;
+
+ _characterSignals[i] = -1;
+ _characterPos[i] = Common::Point(-1, -1);
+ _characterPosAltitude[i] = 0;
+ _characterFrameArray[i] = 0;
+ _characterCarried[i] = -1;
+ _characterBehindDist[i] = 4;
+ _characterAboveDist[i] = 0;
+ _spriteSizeArray[i] = 20;
+ _characterDirectionArray[i] = 0;
+ _characterMobility[i] = 0;
+ _characterTypes[i] = 0;
+ _characterBehaviour[i] = 0;
+ _characterHomePos[i] = Common::Point(0, 0);
+ _signalArr[i] = -1;
+ }
+
+ for (int i = 0; i < 30; i++)
+ _signalArray[i] = -1;
+
+ for (int i = 0; i < 256; i++)
+ _savedSurfaceUnderMouse[i] = 0;
+
+ for (int i = 0; i < 160; i++)
+ _displayStringBuf[i] = 0;
+
+ for (int i = 0; i < 1400 + 3120; i++) {
+ _characterVariables[i] = 0;
+ }
+
+ _currentCharacterAttributes = NULL;
+ _bufferIdeogram = NULL;
+ _bufferMen = NULL;
+ _bufferMen2 = NULL;
+ _bufferIsoChars = NULL;
+ _bufferIsoMap = NULL;
+ _bufferCubegfx = NULL;
+
+ _sequencesArr = nullptr;
+ _packedStringIndex = nullptr;
+ _packedStringNumb = 0;
+ _packedStrings = nullptr;
+ _initScript = nullptr;
+ _initScriptSize = 0;
+ _menuScript = nullptr;
+ _menuScriptSize = 0;
+ _arrayGameScriptIndex = nullptr;
+ _gameScriptIndexSize = 0;
+ _arrayGameScripts = nullptr;
+ _listNumb = 0;
+ _listIndex = nullptr;
+ _listArr = nullptr;
+ _rectNumb = 0;
+ for (int i = 0; i < 40; ++i)
+ _enclosureRect[i] = Common::Rect(0, 0, 0, 0);
+
+ _interfaceHotspotNumb = 0;
+ for (int i = 0; i < 20; ++i)
+ _keyboardMapping[i] = Common::KEYCODE_DOLLAR;
+
+ _mainSurface = nullptr;
+ _smallAnimsFrameIndex = 0;
+ _keyDelay = 0;
+ _int8Timer = 0;
+ _keyboard_nextIndex = 0;
+ _keyboard_oldIndex = 0;
+ _normalCursor = nullptr;
+ _greenCursor = nullptr;
+ _word10800_ERULES = 0;
+ _currentDisplayCharacter = 0;
+
+ _shouldQuit = false;
+ _eventMan = nullptr;
+ _lastTime = 0;
+ _gameType = kGameTypeNone;
+ _platform = Common::kPlatformUnknown;
+}
+
+LilliputEngine::~LilliputEngine() {
+ DebugMan.clearAllDebugChannels();
+ delete _console;
+ delete _soundHandler;
+ delete _scriptHandler;
+ delete _rnd;
+}
+
+GUI::Debugger *LilliputEngine::getDebugger() {
+ return _console;
+}
+
+void LilliputEngine::update() {
+ // update every 20 ms.
+ int currentTime = _system->getMillis();
+ if (currentTime - _lastTime > 20) {
+ _lastTime += ((currentTime - _lastTime) / 20) * 20;
+ newInt8();
+ pollEvent();
+ if (_displayGreenHand == true && _isCursorGreenHand == false) {
+ _isCursorGreenHand = true;
+ CursorMan.pushCursor(_greenCursor, 16, 16, 0, 0, 0);
+ } else if (_displayGreenHand == false && _isCursorGreenHand == true) {
+ _isCursorGreenHand = false;
+ CursorMan.popCursor();
+ }
+
+ _system->copyRectToScreen((byte *)_mainSurface->getPixels(), 320, 0, 0, 320, 200);
+ _system->updateScreen();
+ }
+}
+
+void LilliputEngine::newInt8() {
+ _soundHandler->refresh();
+
+ if (_byte12A05 != 0)
+ --_byte12A05;
+ else {
+ _byte12A05 = 10;
+ if (_int8Timer != 0)
+ --_int8Timer;
+
+ _animationTick ^= 1;
+ if (!_refreshScreenFlag)
+ displayRefreshScreen();
+ }
+}
+
+bool LilliputEngine::hasFeature(EngineFeature f) const {
+ return (f == kSupportsRTL) || (f == kSupportsLoadingDuringRuntime) || (f == kSupportsSavingDuringRuntime);
+}
+
+const char *LilliputEngine::getCopyrightString() const {
+ return "copyright S.L.Grand, Brainware, 1991 - 1992";
+}
+
+GameType LilliputEngine::getGameType() const {
+ return _gameType;
+}
+
+Common::Platform LilliputEngine::getPlatform() const {
+ return _platform;
+}
+
+void LilliputEngine::displayCharacter(int index, Common::Point pos, int flags) {
+ debugC(2, kDebugEngine, "displayCharacter(%d, %d - %d, %d)", index, pos.x, pos.y, flags);
+
+ byte *buf = _savedSurfaceGameArea1 + (pos.y * 256) + pos.x;
+
+ byte *src = _bufferMen;
+ if (index < 0) {
+ src = _bufferIdeogram;
+ index = -index;
+ } else if (index >= 0xF0) {
+ src = _bufferMen2;
+ index -= 0xF0;
+ }
+
+ src += (index * 256);
+
+ if ((flags & 2) == 0) {
+ for (int y = 0; y < 16; y++) {
+ for (int x = 0; x < 16; x++) {
+ if (src[x] != 0)
+ buf[x] = src[x];
+ }
+ src += 16;
+ buf += 256;
+ }
+ } else {
+ // Sprite mirror
+ for (int y = 0; y < 16; y++) {
+ for (int x = 0; x < 16; x++) {
+ // May need a hack of 1 pixel
+ if (src[15 - x] != 0)
+ buf[x] = src[15 - x];
+ }
+ src += 16;
+ buf += 256;
+ }
+ }
+}
+
+void LilliputEngine::display16x16IndexedBuf(byte *buf, int index, Common::Point pos, bool transparent, bool updateScreen) {
+ debugC(2, kDebugEngine, "display16x16IndexedBuf(buf, %d, %d - %d)", index, pos.x, pos.y);
+
+ int index1 = index * 16 * 16;
+ byte *newBuf = &buf[index1];
+
+ int vgaIndex = pos.x + (pos.y * 320);
+
+ for (int i = 0; i < 16; i++) {
+ // clip on y
+ if (pos.y + i < 200) {
+ for (int j = 0; j < 16; j++) {
+ // clip on x
+ if ((newBuf[j] != 0 || !transparent) && (pos.x + j < 320))
+ ((byte *)_mainSurface->getPixels())[vgaIndex + j] = newBuf[j];
+ }
+ }
+ vgaIndex += 320;
+ newBuf += 16;
+ }
+
+ if (updateScreen) {
+ _system->copyRectToScreen((byte *)_mainSurface->getPixels(), 320, 0, 0, 320, 200);
+ _system->updateScreen();
+ }
+}
+
+void LilliputEngine::display16x16Buf(byte *buf, Common::Point pos, bool transparent, bool updateScreen) {
+ debugC(2, kDebugEngine, "display16x16Buf(buf, %d, %d)", pos.x, pos.y);
+
+ display16x16IndexedBuf(buf, 0, pos, transparent, updateScreen);
+}
+
+void LilliputEngine::fill16x16Rect(byte col, Common::Point pos) {
+ debugC(2, kDebugEngineTBC, "fill16x16Rect(%d, %d - %d)", col, pos.x, pos.y);
+
+ int index = pos.x + (pos.y * 320);
+ for (int i = 0; i < 16; i++) {
+ for (int j = 0; j < 16; j++) {
+ ((byte *)_mainSurface->getPixels())[index + j] = col;
+ }
+ index += 320;
+ }
+}
+
+void LilliputEngine::saveSurfaceGameArea() {
+ debugC(2, kDebugEngine, "saveSurfaceGameArea()");
+
+ int index = (16 * 320) + 64; // 5184
+ for (int i = 0; i < 176; i++) {
+ for (int j = 0; j < 256; j++)
+ _savedSurfaceGameArea3[(i * 256) + j] = ((byte *)_mainSurface->getPixels())[index + j];
+ index += 320;
+ }
+}
+
+void LilliputEngine::saveSurfaceSpeech() {
+ debugC(2, kDebugEngine, "saveSurfaceSpeech()");
+
+ int index = 66;
+ for (int i = 0; i < 16; i++) {
+ for (int j = 0; j < 252; j++)
+ _savedSurfaceSpeech[(i * 252) + j] = ((byte *)_mainSurface->getPixels())[index + j];
+ index += 320;
+ }
+}
+
+void LilliputEngine::restoreSurfaceSpeech() {
+ debugC(2, kDebugEngine, "restoreSurfaceSpeech()");
+
+ int index = 66;
+ for (int i = 0; i < 16; i++) {
+ for (int j = 0; j < 252; j++)
+ ((byte *)_mainSurface->getPixels())[index + j] = _savedSurfaceSpeech[(i * 252) + j];
+ index += 320;
+ }
+}
+
+
+void LilliputEngine::displayInterfaceHotspots() {
+ debugC(2, kDebugEngine, "displayInterfaceHotspots()");
+
+ if (_displayMap)
+ return;
+
+ for (int index = 0; index < _interfaceHotspotNumb; index++) {
+ int tmpVal = _scriptHandler->_interfaceHotspotStatus[index] * 20;
+ display16x16IndexedBuf(_bufferIdeogram, tmpVal + index, _interfaceHotspots[index]);
+ }
+}
+
+void LilliputEngine::displayLandscape() {
+ debugC(2, kDebugEngine, "displayLandscape()");
+
+ memcpy(_savedSurfaceGameArea2, _savedSurfaceGameArea3, 176 * 256); // 45056
+
+ int index = (_scriptHandler->_viewportPos.y * 64 + _scriptHandler->_viewportPos.x) * 4;
+
+ for (int posY = 0; posY < 8; posY++) {
+ for (int posX = 0; posX < 8 ; posX++) {
+ assert (index < 16384);
+ displayIsometricBlock(_savedSurfaceGameArea2, _bufferIsoMap[index], posX, posY, 0);
+ index += 4;
+ }
+ index += 224;
+ }
+}
+
+// Display dialog bubble
+void LilliputEngine::displaySpeechBubble() {
+ debugC(2, kDebugEngine, "displaySpeechBubble()");
+ static const byte _array15976[16] = {244, 248, 250, 250, 252, 252, 252, 252, 252, 252, 252, 252, 250, 250, 248, 244};
+
+ int index = 192;
+
+ for (int i = 0; i < 16; i++) {
+ int var3 = _array15976[i];
+ int tmpIndex = index - (var3 / 2);
+ var3 &= 0xFE;
+ for (int j = 0; j < var3; j++) {
+ ((byte *)_mainSurface->getPixels())[tmpIndex + j] = 17;
+ }
+ index += 320;
+ }
+}
+
+void LilliputEngine::displaySpeechLine(int vgaIndex, byte *srcBuf, int &bufIndex) {
+ debugC(2, kDebugEngine, "displaySpeechLine()");
+
+ int var3 = 0;
+ int var1;
+ int bckIndex = bufIndex;
+
+ for (;;) {
+ var1 = srcBuf[bufIndex];
+ if ((var1 == 0) || (var1 == '|'))
+ break;
+
+ ++bufIndex;
+ ++var3;
+ }
+
+ var1 = (0x3D - var3) * 2;
+ vgaIndex += var1;
+
+ bufIndex = bckIndex;
+ for (;;) {
+ var1 = srcBuf[bufIndex];
+ ++bufIndex;
+ if ((var1 == 0) || (var1 == '|'))
+ break;
+
+ displayChar(vgaIndex, var1);
+ vgaIndex += 4;
+ }
+}
+
+void LilliputEngine::displaySpeech(byte *buf) {
+ debugC(2, kDebugEngine, "displaySpeech(%s)", buf);
+
+ int vgaIndex = 70;
+ int bufIndex = 0;
+
+ bool multiLineFlag = false;
+ byte var1;
+
+ for (;;) {
+ var1 = buf[bufIndex];
+ ++bufIndex;
+ if (var1 == 0) {
+ vgaIndex += (4 * 320);
+ break;
+ } else if (var1 == '|') {
+ multiLineFlag = true;
+ break;
+ }
+ }
+
+ bufIndex = 0;
+ displaySpeechLine(vgaIndex, buf, bufIndex);
+ if (multiLineFlag) {
+ vgaIndex += (8 * 320);
+ displaySpeechLine(vgaIndex, buf, bufIndex);
+ }
+}
+
+void LilliputEngine::initGameAreaDisplay() {
+ debugC(1, kDebugEngine, "initGameAreaDisplay()");
+
+ // display background
+ byte *tmpBuf = loadVGA("SCREEN.GFX", 320 * 200, true);
+ memcpy(_mainSurface->getPixels(), tmpBuf, 320 * 200);
+ _system->copyRectToScreen((byte *)_mainSurface->getPixels(), 320, 0, 0, 320, 200);
+ _system->updateScreen();
+
+ // display game area on top of background
+ saveSurfaceGameArea();
+ saveSurfaceSpeech();
+ displayInterfaceHotspots();
+ displayLandscape();
+ prepareGameArea();
+ displayGameArea();
+
+ free(tmpBuf);
+}
+
+void LilliputEngine::displayIsometricBlock(byte *buf, int var1, int posX, int posY, int var3) {
+ debugC(1, kDebugEngine, "displayIsometricBlock(buf, %d, %d - %d, %d)", var1, posX, posY, var3);
+
+ byte tmpByte1 = ((7 + posX - posY) << 4) & 0xFF;
+ byte tmpByte2 = ((4 + posX + posY - (var3 >> 7)) << 3) & 0xFF;
+
+ int index = (tmpByte2 << 8) + tmpByte1;
+ int index2 = var1 << 10;
+
+ for (int i = 0; i < 32; i++) {
+ for (int j = 0; j < 32; j++) {
+ if (_bufferCubegfx[index2 + j] != 0)
+ buf[index + j] = _bufferCubegfx[index2 + j];
+ }
+ index2 += 32;
+ index += 256;
+ }
+}
+
+void LilliputEngine::displayGameArea() {
+ debugC(2, kDebugEngine, "displayGameArea()");
+
+ if (_displayMap)
+ return;
+
+ int index = (16 * 320) + 64; // 5184
+ for (int i = 0; i < 176; i++) {
+ for (int j = 0; j < 256; j++)
+ ((byte *)_mainSurface->getPixels())[index + j] = _savedSurfaceGameArea1[(i * 256) + j];
+ index += 320;
+ }
+
+ _system->copyRectToScreen((byte *)_mainSurface->getPixels(), 320, 0, 0, 320, 200);
+ _system->updateScreen();
+}
+
+void LilliputEngine::restoreMapPoints() {
+ debugC(2, kDebugEngine, "restoreMapPoints()");
+
+ byte *buf = (byte *)_mainSurface->getPixels();
+ for (byte index = 0; index < _numCharacters; index++) {
+ buf[_mapSavedPixelIndex[index]] = _mapSavedPixel[index];
+ }
+}
+
+void LilliputEngine::displayCharactersOnMap() {
+ debugC(2, kDebugEngineTBC, "displayCharactersOnMap()");
+
+ moveCharacters();
+
+ byte *buf = (byte *)_mainSurface->getPixels();
+ for (int index = _numCharacters - 1; index >= 0; index--) {
+ if (((_characterTypes[index] & 2) == 0) && (_scriptHandler->_characterTilePos[index].y != -1)) {
+ // FIXME: This is still wrong, but less. The values in both arrays should be verified now!
+ int pixIndex = 320 + ((15 * _scriptHandler->_characterTilePos[index].y) / 4) + (_scriptHandler->_characterTilePos[index].x * 4) + 1;
+
+ _mapSavedPixelIndex[index] = pixIndex;
+ _mapSavedPixel[index] = buf[pixIndex];
+ buf[pixIndex] = _scriptHandler->_characterMapPixelColor[index];
+ }
+ }
+}
+
+void LilliputEngine::moveCharacters() {
+ debugC(2, kDebugEngine, "moveCharacters()");
+
+ _numCharactersToDisplay = 0;
+ byte index = _numCharacters - 1;
+ Common::Point pos16213 = Common::Point(_scriptHandler->_viewportPos.x << 3, _scriptHandler->_viewportPos.y << 3);
+
+ for (int i = index; i >= 0; i--) {
+ if (_characterCarried[i] != -1) {
+ int index2 = _characterCarried[i];
+ _characterPosAltitude[i] = _characterPosAltitude[index2] + _characterAboveDist[i];
+ int8 behindDist = _characterBehindDist[i];
+ _characterDirectionArray[i] = _characterDirectionArray[index2];
+ int nextPosX = _characterPos[index2].x;
+ int nextPosY = _characterPos[index2].y;
+
+ switch (_characterDirectionArray[i]) {
+ case 0:
+ nextPosX -= behindDist;
+ break;
+ case 1:
+ nextPosY += behindDist;
+ break;
+ case 2:
+ nextPosY -= behindDist;
+ break;
+ default:
+ nextPosX += behindDist;
+ break;
+ }
+
+ _characterPos[i] = Common::Point(nextPosX, nextPosY);
+ }
+
+ _scriptHandler->_characterTilePos[i] = Common::Point(_characterPos[i].x >> 3, _characterPos[i].y >> 3);
+ _characterRelativePos[i] = Common::Point(-1, -1);
+ _characterDisplay[i] = Common::Point(-1, -1);
+
+ int tileX = (_characterPos[i].x >> 3) - _scriptHandler->_viewportPos.x;
+ int tileY = (_characterPos[i].y >> 3) - _scriptHandler->_viewportPos.y;
+ if ((tileX >= 0) && (tileX <= 7) && (tileY >= 0) && (tileY <= 7)) {
+ _characterRelativePos[i] = Common::Point(tileX, tileY);
+ int tempX = _characterPos[i].x - pos16213.x;
+ int tempY = _characterPos[i].y - pos16213.y;
+ _characterDisplay[i].x = ((60 + tempX - tempY) * 2) & 0xFF;
+ _characterDisplay[i].y = (20 + tempX + tempY - _characterPosAltitude[i]) & 0xFF;
+ _charactersToDisplay[_numCharactersToDisplay] = i;
+ ++_numCharactersToDisplay;
+ }
+ }
+
+ sortCharacters();
+}
+
+void LilliputEngine::setNextDisplayCharacter(int var1) {
+ debugC(2, kDebugEngine, "setNextDisplayCharacter(%d)", var1);
+
+ byte charNum = var1 & 0xFF;
+ if (charNum < _numCharactersToDisplay) {
+ int index = _charactersToDisplay[charNum];
+ _nextDisplayCharacterPos = _characterRelativePos[index];
+ } else
+ _nextDisplayCharacterPos = Common::Point(-1, -1);
+}
+
+void LilliputEngine::prepareGameArea() {
+ debugC(2, kDebugEngine, "prepareGameArea()");
+
+ moveCharacters();
+ _currentDisplayCharacter = 0;
+ setNextDisplayCharacter(0);
+
+ memcpy(_savedSurfaceGameArea1, _savedSurfaceGameArea2, 176 * 256); // 45056;
+
+ int index1 = (_scriptHandler->_viewportPos.y * 64 + _scriptHandler->_viewportPos.x) * 4;
+ assert(index1 < 16384);
+ byte *map = &_bufferIsoMap[index1];
+
+ for (int posY = 0; posY < 8; posY++) {
+ for (int posX = 0; posX < 8; posX++) {
+ if (map[1] != 0xFF) {
+ int var1 = map[1];
+ if ((_cubeFlags[var1] & 128) != 0)
+ var1 += _animationTick;
+ displayIsometricBlock(_savedSurfaceGameArea1, var1, posX, posY, 1 << 8);
+ }
+ renderCharacters(map, Common::Point(posX, posY));
+
+ if (map[2] != 0xFF) {
+ int var1 = map[2];
+ if ((_cubeFlags[var1] & 128) != 0)
+ var1 += _animationTick;
+ displayIsometricBlock(_savedSurfaceGameArea1, var1, posX, posY, 2 << 8);
+ }
+ map += 4;
+ }
+ map += 224;
+ }
+}
+
+void LilliputEngine::displayRefreshScreen() {
+ debugC(2, kDebugEngine, "displayRefreshScreen()");
+
+ if (_displayMap) {
+ bool forceReturnFl = false;
+ checkMapClosing(forceReturnFl);
+ if (forceReturnFl)
+ return;
+
+ restoreMapPoints();
+ updateCharPosSequence();
+ handleCharacterTimers();
+ checkInteractions();
+ checkSpecialCubes();
+ handleSignals();
+ displayCharactersOnMap();
+ } else {
+ scrollToViewportCharacterTarget();
+ checkSpeechClosing();
+ prepareGameArea();
+ displayGameArea();
+ updateCharPosSequence();
+ handleCharacterTimers();
+ checkInteractions();
+ checkSpecialCubes();
+ handleSignals();
+ handleGameMouseClick();
+ checkInterfaceActivationDelay();
+ displayHeroismIndicator();
+ }
+}
+
+void LilliputEngine::resetSmallAnims() {
+ debugC(2, kDebugEngine, "resetSmallAnims()");
+
+ _smallAnims[0]._active = false;
+ _smallAnims[1]._active = false;
+ _smallAnims[2]._active = false;
+ _smallAnims[3]._active = false;
+ _smallAnimsFrameIndex = 0;
+}
+
+void LilliputEngine::displaySmallIndexedAnim(byte index, byte subIndex) {
+ debugC(2, kDebugEngine, "displaySmallIndexedAnim(%d, %d)", index, subIndex);
+
+ if (!_smallAnims[index]._active)
+ return;
+
+ display16x16IndexedBuf(_bufferIdeogram, _smallAnims[index]._frameIndex[subIndex], _smallAnims[index]._pos, false);
+}
+
+void LilliputEngine::displaySmallAnims() {
+ debugC(2, kDebugEngine, "displaySmallAnims()");
+
+ if (_animationTick == _lastAnimationTick)
+ return;
+
+ _lastAnimationTick = _animationTick;
+
+ assert(_smallAnimsFrameIndex < 8);
+ int subIndex = _smallAnimsFrameIndex;
+ displaySmallIndexedAnim(0, subIndex);
+ displaySmallIndexedAnim(1, subIndex);
+ displaySmallIndexedAnim(2, subIndex);
+ displaySmallIndexedAnim(3, subIndex);
+
+ ++subIndex;
+ if (subIndex == 8)
+ subIndex = 0;
+
+ _smallAnimsFrameIndex = subIndex;
+}
+
+void LilliputEngine::paletteFadeOut() {
+ debugC(2, kDebugEngine, "paletteFadeOut()");
+
+ resetSmallAnims();
+ byte palette[768];
+ for (int fade = 256; fade >= 0; fade -= 8) {
+ for (int i = 0; i < 768; i++) {
+ palette[i] = (_curPalette[i] * fade) >> 8;
+ }
+ _system->getPaletteManager()->setPalette(palette, 0, 256);
+ _system->updateScreen();
+ _system->delayMillis(20);
+ pollEvent();
+ }
+}
+
+void LilliputEngine::paletteFadeIn() {
+ debugC(2, kDebugEngine, "paletteFadeIn()");
+
+ byte palette[768];
+ for (int fade = 8; fade <= 256; fade += 8) {
+ for (int i = 0; i < 768; i++) {
+ palette[i] = (_curPalette[i] * fade) >> 8;
+ }
+ _system->getPaletteManager()->setPalette(palette, 0, 256);
+ _system->updateScreen();
+ _system->delayMillis(20);
+ pollEvent();
+ }
+}
+
+int16 LilliputEngine::checkObstacle(int x1, int y1, int x2, int y2) {
+ debugC(2, kDebugEngine, "checkObstacle(%d, %d, %d, %d)", x1, y1, x2, y2);
+
+ int index = ((y1 * 64) + x1) * 4;
+ assert((index > 0) && (index <= 16380));
+ byte *isoMap = &_bufferIsoMap[index + 1];
+
+ int16 dx = x2 - x1;
+ int16 dy = y2 - y1;
+
+ int16 tmpMapMoveX = 0;
+ int16 tmpMapMoveY = 0;
+ int16 mapMoveY = 0;
+ int16 mapMoveX = 0;
+
+ int16 nonDiagdelta = 0;
+ int16 diagDelta = 0;
+
+ if (dx < 0) {
+ dx = -dx;
+ tmpMapMoveX = -4;
+ } else {
+ tmpMapMoveX = 4;
+ }
+
+ if (dy < 0) {
+ dy = -dy;
+ tmpMapMoveY = -256;
+ } else {
+ tmpMapMoveY = 256;
+ }
+
+ if (dx >= dy) {
+ mapMoveY = 0;
+ mapMoveX = tmpMapMoveX;
+ } else {
+ int16 tmp = dy;
+ dy = dx;
+ dx = tmp;
+ mapMoveX = 0;
+ mapMoveY = tmpMapMoveY;
+ }
+
+ nonDiagdelta = dy * 2;
+ int16 var1 = nonDiagdelta - dx;
+ diagDelta = nonDiagdelta - (dx * 2);
+
+ mapMoveX += mapMoveY;
+ tmpMapMoveX += tmpMapMoveY;
+
+ int count = 0;
+
+ while (*isoMap == 0xFF) {
+ if (var1 >= 0) {
+ isoMap += tmpMapMoveX;
+ var1 += diagDelta;
+ } else {
+ isoMap += mapMoveX;
+ var1 += nonDiagdelta;
+ }
+
+ count++;
+ if (count > dx) {
+ return 0;
+ }
+ }
+ return tmpMapMoveY;
+}
+
+void LilliputEngine::startNavigateFromMap() {
+ debugC(2, kDebugEngine, "startNavigateFromMap()");
+
+ _selectedCharacterId = -1;
+ _savedMousePosDivided = Common::Point(-1, -1);
+ byte newX = _mousePos.x / 4;
+ byte newY = _mousePos.y / 3;
+
+ if ((newX >= 64) || (newY >= 64))
+ return;
+
+ _savedMousePosDivided = Common::Point(newX, newY);
+ _actionType = kCubeSelected;
+}
+
+void LilliputEngine::unselectInterfaceHotspots() {
+ debugC(2, kDebugEngine, "unselectInterfaceHotspots()");
+
+ for (int index = 0; index < _interfaceHotspotNumb; index++) {
+ if (_scriptHandler->_interfaceHotspotStatus[index] == kHotspotSelected)
+ _scriptHandler->_interfaceHotspotStatus[index] = kHotspotEnabled;
+ }
+}
+
+void LilliputEngine::checkMapClosing(bool &forceReturnFl) {
+ debugC(2, kDebugEngineTBC, "checkMapClosing()");
+
+ forceReturnFl = false;
+ if (!_displayMap)
+ return;
+
+ pollEvent();
+ if (!_keyboard_checkKeyboard()) {
+ _keyboard_getch();
+ } else {
+ if (_mouseButton != 1)
+ return;
+
+ _mouseButton = 0;
+ startNavigateFromMap();
+ }
+
+ _displayMap = false;
+ paletteFadeOut();
+ _displayGreenHand = false;
+ unselectInterfaceHotspots();
+ initGameAreaDisplay();
+ _scriptHandler->_heroismLevel = 0;
+ moveCharacters();
+ paletteFadeIn();
+ forceReturnFl = true;
+}
+
+void LilliputEngine::checkInteractions() {
+ debugC(2, kDebugEngine, "checkInteractions()");
+
+ for (int index = _numCharacters - 1; index >= 0; index--) {
+ if (_characterTypes[index] & 1)
+ continue;
+
+ int c1 = _scriptHandler->_characterTilePos[index].x;
+ int c2 = _scriptHandler->_characterTilePos[index].y;
+
+ // Hack: Skip if disabled (c2 negative)
+ if (c2 == -1)
+ continue;
+
+ for (int index2 = _numCharacters - 1; index2 >= 0; index2--) {
+ byte _newStatus = 0;
+ if ((index != index2) &&
+ (_characterCarried[index] != index2) &&
+ (_characterCarried[index2] != index) &&
+ (_characterTypes[index2] & 2) == 0) {
+ int d1 = _scriptHandler->_characterTilePos[index2].x;
+ int d2 = _scriptHandler->_characterTilePos[index2].y;
+
+ if (d1 != -1) {
+ int x = c1 - d1;
+ if ((x > -6) && (x < 6)) {
+ int y = c2 - d2;
+ if ((y > -6) && (y < 6)) {
+ _newStatus = 1;
+
+ if ((c1 == d1) && (c2 == d2)) {
+ _newStatus = 4;
+ } else if ((_characterTypes[index] & 4) != 0) {
+ _newStatus = 0;
+ } else {
+ switch (_characterDirectionArray[index]) {
+ case 0:
+ if (d1 > c1) {
+ _newStatus = 2;
+
+ if (d2 == c2)
+ _newStatus = 3;
+
+ if (checkObstacle(c1, c2, d1, d2) != 0)
+ _newStatus = 1;
+ }
+ break;
+ case 1:
+ if (d2 < c2) {
+ _newStatus = 2;
+
+ if (d1 == c1)
+ _newStatus = 3;
+
+ if (checkObstacle(c1, c2, d1, d2) != 0)
+ _newStatus = 1;
+ }
+ break;
+ case 2:
+ if (d2 > c2) {
+ _newStatus = 2;
+
+ if (d1 == c1)
+ _newStatus = 3;
+
+ if (checkObstacle(c1, c2, d1, d2) != 0)
+ _newStatus = 1;
+ }
+ break;
+ default:
+ if (d1 < c1) {
+ _newStatus = 2;
+
+ if (d2 == c2)
+ _newStatus = 3;
+
+ if (checkObstacle(c1, c2, d1, d2) != 0)
+ _newStatus = 1;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ int8 v2 = _scriptHandler->_interactions[index2 + (index * 40)] & 0xFF;
+ int8 v1 = v2;
+
+ if (v2 != _newStatus) {
+ _scriptHandler->_characterScriptEnabled[index] = 1;
+ v2 = _newStatus;
+ }
+ _scriptHandler->_interactions[index2 + (index * 40)] = (v1 << 8) + v2;
+ }
+ }
+}
+
+void LilliputEngine::displayCharacterStatBar(int8 type, int16 averagePosX, int8 score, int16 posY) {
+ debugC(2, kDebugEngine, "displayCharacterStatBar(%d, %d, %d, %d)", type, averagePosX, score, posY);
+
+ int16 posX = averagePosX;
+
+ // If var equals 45 ('-'), score bar from -x to +x. If not (usually 43 '+'), score bar from 0 to x.
+ if (type == 45) {
+ posX += 35;
+ score -= 35;
+
+ if (score < 0) {
+ posX += score;
+ score = -score;
+ }
+ }
+
+ byte *vgaBuf = (byte *)_mainSurface->getPixels();
+ int vgaIndex = posX + (320 * posY);
+
+ if (score == 0)
+ ++score;
+
+ // Draw bar, color green, high = 4, width = score
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < score; j++) {
+ vgaBuf[vgaIndex + j] = 2;
+ }
+ vgaIndex += 320;
+ }
+}
+
+void LilliputEngine::displayString(byte *buf, Common::Point pos) {
+ debugC(2, kDebugEngine, "displayString(%s, %d - %d)", buf, pos.x, pos.y);
+
+ int index = (pos.y * 320) + pos.x;
+
+ int i = 0;
+ while (buf[i] != 0) {
+ displayChar(index, buf[i]);
+ ++i;
+ index += 4;
+ }
+}
+
+void LilliputEngine::displayChar(int index, int var1) {
+ debugC(2, kDebugEngine, "displayChar(%d, %d)", index, var1);
+
+ int indexVga = index;
+ int indexChar = var1 << 5;
+
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 4; j++)
+ ((byte *)_mainSurface->getPixels())[indexVga + j] = _bufferIsoChars[indexChar + j];
+ indexVga += 320;
+ indexChar += 4;
+ }
+
+}
+
+void LilliputEngine::sortCharacters() {
+ debugC(2, kDebugEngine, "sortCharacters()");
+
+ if (_numCharactersToDisplay <= 1)
+ return;
+
+ for (int var4 = _numCharactersToDisplay - 1; var4 > 0; var4--) {
+ bool found = false;
+
+ for (int var2 = 0; var2 < var4; var2++) {
+ int index1 = _charactersToDisplay[var2];
+ int index2 = _charactersToDisplay[var2 + 1];
+
+ if (_characterRelativePos[index1].y < _characterRelativePos[index2].y)
+ continue;
+
+ if (_characterRelativePos[index1].y == _characterRelativePos[index2].y) {
+ if (_characterRelativePos[index1].x < _characterRelativePos[index2].x)
+ continue;
+
+ if (_characterRelativePos[index1].x == _characterRelativePos[index2].x) {
+ if (_characterPosAltitude[index1] < _characterPosAltitude[index2])
+ continue;
+
+ if (_characterPosAltitude[index1] == _characterPosAltitude[index2]) {
+ if (_characterDisplay[index1].y < _characterDisplay[index2].y)
+ continue;
+ }
+ }
+ }
+
+ byte tmpVal = _charactersToDisplay[var2];
+ _charactersToDisplay[var2] = _charactersToDisplay[var2 + 1];
+ _charactersToDisplay[var2 + 1] = tmpVal;
+ found = true;
+ }
+
+ if (!found)
+ return;
+ }
+}
+
+void LilliputEngine::scrollToViewportCharacterTarget() {
+ debugC(2, kDebugEngine, "scrollToViewportCharacterTarget()");
+
+ if (_scriptHandler->_viewportCharacterTarget == -1)
+ return;
+
+ int tileX = (_characterPos[_scriptHandler->_viewportCharacterTarget].x >> 3) - _scriptHandler->_viewportPos.x;
+ int tileY = (_characterPos[_scriptHandler->_viewportCharacterTarget].y >> 3) - _scriptHandler->_viewportPos.y;
+ Common::Point newPos = _scriptHandler->_viewportPos;
+
+ if (tileX >= 1) {
+ if (tileX > 6){
+ newPos.x += 4;
+ if (newPos.x > 56)
+ newPos.x = 56;
+ }
+ } else {
+ newPos.x -= 4;
+ if (newPos.x < 0)
+ newPos.x = 0;
+ }
+
+ if ((tileY < 1) && (newPos.y < 4))
+ newPos.y = 0;
+ else {
+ if (tileY < 1)
+ newPos.y -= 4;
+
+ if (tileY > 6) {
+ newPos.y += 4;
+ if (newPos.y >= 56)
+ newPos.y = 56;
+ }
+ }
+ viewportScrollTo(newPos);
+}
+
+void LilliputEngine::viewportScrollTo(Common::Point goalPos) {
+ debugC(2, kDebugEngine, "viewportScrollTo(%d, %d)", goalPos.x, goalPos.y);
+
+ if (goalPos == _scriptHandler->_viewportPos)
+ return;
+
+ int16 dx = 0;
+ if (goalPos.x != _scriptHandler->_viewportPos.x) {
+ if (goalPos.x < _scriptHandler->_viewportPos.x)
+ --dx;
+ else
+ ++dx;
+ }
+
+ int16 dy = 0;
+ if (goalPos.y != _scriptHandler->_viewportPos.y) {
+ if (goalPos.y < _scriptHandler->_viewportPos.y)
+ --dy;
+ else
+ ++dy;
+ }
+
+ do {
+ _scriptHandler->_viewportPos.x += dx;
+ _scriptHandler->_viewportPos.y += dy;
+
+ displayLandscape();
+ prepareGameArea();
+ displayGameArea();
+
+ if (goalPos.x == _scriptHandler->_viewportPos.x)
+ dx = 0;
+
+ if (goalPos.y == _scriptHandler->_viewportPos.y)
+ dy = 0;
+ } while ((dx != 0) || (dy != 0));
+
+ _soundHandler->update();
+}
+
+void LilliputEngine::renderCharacters(byte *buf, Common::Point pos) {
+ debugC(2, kDebugEngine, "renderCharacters(buf, %d - %d)", pos.x, pos.y);
+
+ if (_nextDisplayCharacterPos != pos)
+ return;
+
+ _byte16552 = 0;
+
+ if (buf[1] != 0xFF) {
+ int tmpIndex = buf[1];
+ if ((_cubeFlags[tmpIndex] & 16) == 0)
+ ++_byte16552;
+ }
+
+ int index = _charactersToDisplay[_currentDisplayCharacter];
+ Common::Point characterPos = _characterDisplay[index];
+
+ if (index == _scriptHandler->_talkingCharacter)
+ displaySpeechBubbleTail(characterPos);
+
+ if (_byte16552 != 1) {
+ byte flag = _characterDirectionArray[index];
+ int16 frame = _characterFrameArray[index];
+
+ if (frame != -1) {
+ frame += _scriptHandler->_characterPose[index];
+ if ((flag & 1) == 1)
+ frame += _spriteSizeArray[index];
+
+ if (_characterMagicPuffFrame[index] != -1) {
+ frame = _characterMagicPuffFrame[index] + 82;
+ --_characterMagicPuffFrame[index];
+ frame = -frame;
+ }
+
+ displayCharacter(frame, characterPos, flag);
+ }
+ }
+
+ ++_currentDisplayCharacter;
+ setNextDisplayCharacter(_currentDisplayCharacter);
+
+ renderCharacters(buf, pos);
+}
+
+void LilliputEngine::displaySpeechBubbleTail(Common::Point displayPos) {
+ debugC(2, kDebugEngine, "displaySpeechBubbleTail(%d, %d)", displayPos.x, displayPos.y);
+
+ int orgX = displayPos.x + 8;
+ int orgY = displayPos.y;
+ int var2 = 0;
+
+ int x = orgX;
+ int y = orgY;
+ do {
+ displaySpeechBubbleTailLine(Common::Point(x, y), var2);
+ --x;
+ y /= 2;
+ } while (y != 0);
+
+ x = orgX + 1;
+ y = orgY / 2;
+
+ while (y != 0) {
+ displaySpeechBubbleTailLine(Common::Point(x, y), var2);
+ ++x;
+ y /= 2;
+ }
+}
+
+void LilliputEngine::displaySpeechBubbleTailLine(Common::Point pos, int var2) {
+ debugC(2, kDebugEngine, "displaySpeechBubbleTailLine(%d - %d, %d)", pos.x, pos.y, var2);
+
+ int index = pos.x + (var2 * 256);
+ for (int i = 1 + pos.y - var2; i > 0; i--) {
+ _savedSurfaceGameArea1[index] = 17;
+ index += 256;
+ }
+}
+
+void LilliputEngine::checkSpeechClosing() {
+ debugC(2, kDebugEngine, "checkSpeechClosing()");
+
+ if (_scriptHandler->_speechTimer != 0) {
+ --_scriptHandler->_speechTimer;
+ if (_scriptHandler->_speechTimer == 0) {
+ restoreSurfaceSpeech();
+ _scriptHandler->_talkingCharacter = -1;
+ }
+ }
+}
+
+byte LilliputEngine::getDirection(Common::Point param1, Common::Point param2) {
+ debugC(2, kDebugEngine, "getDirection(%d - %d, %d - %d)", param1.x, param1.y, param2.x, param2.y);
+
+ static const byte _directionsArray[8] = {0, 2, 0, 1, 3, 2, 3, 1};
+
+ Common::Point var1 = param2;
+ Common::Point var2 = param1;
+
+ int8 var1h = var1.x - var2.x;
+ int8 var1l = var1.y - var2.y;
+ int8 var2l = 0;
+
+ if (var1h < 0) {
+ var2l |= 4;
+ var1h = -var1h;
+ }
+
+ if (var1l < 0) {
+ var2l |= 2;
+ var1l = -var1l;
+ }
+
+ if (var1h < var1l)
+ var2l |= 1;
+
+ return _directionsArray[var2l];
+}
+
+byte LilliputEngine::sequenceCharacterHomeIn(int index, Common::Point param1) {
+ debugC(2, kDebugEngine, "sequenceCharacterHomeIn(%d, %d - %d)", index, param1.x, param1.y);
+
+ Common::Point target = _characterSubTargetPos[index];
+
+ if (target.x != -1) {
+ if (target != _scriptHandler->_characterTilePos[index]) {
+ homeInChooseDirection(index);
+ _scriptHandler->_characterNextSequence[index] -= (param1.x & 0x0F);
+ return kSeqNoInc | kSeqRepeat;
+ }
+
+ if (target == _characterTargetPos[index])
+ return kSeqRepeat;
+ }
+
+ homeInPathFinding(index);
+
+ Common::Point pos1 = _scriptHandler->_characterTilePos[index];
+ Common::Point pos2 = _characterSubTargetPos[index];
+
+ _characterDirectionArray[index] = getDirection(pos1, pos2);
+
+ homeInChooseDirection(index);
+ _scriptHandler->_characterNextSequence[index] -= (param1.x & 0x0F);
+ return kSeqNoInc | kSeqRepeat;
+}
+
+void LilliputEngine::homeInPathFinding(int index) {
+ debugC(2, kDebugEngine, "homeInPathFinding(%d)", index);
+
+ int16 enclosureSrc = checkEnclosure(_scriptHandler->_characterTilePos[index]);
+ int16 enclosureDst = checkEnclosure(_characterTargetPos[index]);
+
+ if (enclosureSrc == enclosureDst) {
+ _characterSubTargetPos[index] = _characterTargetPos[index];
+ return;
+ }
+
+ if (enclosureSrc == -1) {
+ int tmpVal = checkOuterEnclosure(_characterTargetPos[index]);
+ if (tmpVal == -1)
+ warning("homeInPathFinding: Unexpected negative index");
+ else
+ _characterSubTargetPos[index] = _portalPos[tmpVal];
+ return;
+ }
+
+ if ((enclosureDst != -1) &&
+ (_characterTargetPos[index].x >= _enclosureRect[enclosureSrc].left) &&
+ (_characterTargetPos[index].x <= _enclosureRect[enclosureSrc].right) &&
+ (_characterTargetPos[index].y >= _enclosureRect[enclosureSrc].top) &&
+ (_characterTargetPos[index].y <= _enclosureRect[enclosureSrc].bottom)) {
+ _characterSubTargetPos[index] = _portalPos[enclosureDst];
+ return;
+ }
+
+ _characterSubTargetPos[index] = _portalPos[enclosureSrc];
+
+ if (_enclosureRect[enclosureSrc].left != _enclosureRect[enclosureSrc].right) {
+ if (_portalPos[enclosureSrc].x == _enclosureRect[enclosureSrc].left) {
+ _characterSubTargetPos[index] = Common::Point(_portalPos[enclosureSrc].x - 1, _portalPos[enclosureSrc].y);
+ return;
+ }
+
+ if (_portalPos[enclosureSrc].x == _enclosureRect[enclosureSrc].right) {
+ _characterSubTargetPos[index] = Common::Point(_portalPos[enclosureSrc].x + 1, _portalPos[enclosureSrc].y);
+ return;
+ }
+
+ if (_enclosureRect[enclosureSrc].bottom != _enclosureRect[enclosureSrc].top) {
+ if (_portalPos[enclosureSrc].y == _enclosureRect[enclosureSrc].top)
+ _characterSubTargetPos[index] = Common::Point(_portalPos[enclosureSrc].x, _portalPos[enclosureSrc].y - 1);
+ else // CHECKME: Should be a check on y == bottom
+ _characterSubTargetPos[index] = Common::Point(_portalPos[enclosureSrc].x, _portalPos[enclosureSrc].y + 1);
+
+ return;
+ }
+ }
+
+ int mapIndex = (_portalPos[enclosureSrc].y * 64 + _portalPos[enclosureSrc].x) * 4;
+ assert(mapIndex < 16384);
+
+ int tmpVal = _bufferIsoMap[mapIndex + 3];
+ if ((tmpVal & 8) != 0)
+ _characterSubTargetPos[index] = Common::Point(_portalPos[enclosureSrc].x + 1, _portalPos[enclosureSrc].y);
+ else if ((tmpVal & 4) != 0)
+ _characterSubTargetPos[index] = Common::Point(_portalPos[enclosureSrc].x, _portalPos[enclosureSrc].y - 1);
+ else if ((tmpVal & 2) != 0)
+ _characterSubTargetPos[index] = Common::Point(_portalPos[enclosureSrc].x, _portalPos[enclosureSrc].y + 1);
+ else
+ _characterSubTargetPos[index] = Common::Point(_portalPos[enclosureSrc].x - 1, _portalPos[enclosureSrc].y);
+
+ return;
+}
+
+void LilliputEngine::homeInChooseDirection(int index) {
+ debugC(2, kDebugEngine, "homeInChooseDirection(%d)", index);
+
+ static const int16 mapArrayMove[4] = {4, -256, 256, -4};
+
+ _curCharacterTilePos = _scriptHandler->_characterTilePos[index];
+
+ evaluateDirections(index);
+ int direction = (_characterDirectionArray[index] ^ 3);
+
+ _homeInDirLikelyhood[direction] -= 8;
+ byte closeWallFl = 0;
+
+ int mapIndex = ((_curCharacterTilePos.y * 64) + _curCharacterTilePos.x) * 4;
+ int retVal = 0;
+ for (int i = 3; i >= 0; i--) {
+ int mapIndexDiff = mapArrayMove[i];
+ assert(mapIndex + mapIndexDiff + 3 < 16384);
+ if (((_bufferIsoMap[mapIndex + mapIndexDiff + 3] & _doorEntranceMask[i]) != 0) && ((_bufferIsoMap[mapIndex + 3] & _doorExitMask[i]) != 0)) {
+ if ((_bufferIsoMap[mapIndex + mapIndexDiff + 3] & 0x80) != 0 && (homeInAvoidDeadEnds(i, index) != 0)) {
+ _homeInDirLikelyhood[i] -= 20;
+ }
+
+ int tmpVal = ((_characterMobility[index] & 7) ^ 7);
+ retVal = _cubeFlags[_bufferIsoMap[mapIndex + mapIndexDiff]];
+ tmpVal &= retVal;
+ if (tmpVal == 0)
+ continue;
+ }
+ _homeInDirLikelyhood[i] = -98;
+ ++closeWallFl;
+ }
+
+ if (closeWallFl != 0)
+ _homeInDirLikelyhood[_characterDirectionArray[index]] += 3;
+
+ int tmpVal = -99;
+ for (int i = 3; i >= 0; i--) {
+ if (tmpVal < _homeInDirLikelyhood[i]) {
+ retVal = i;
+ tmpVal = _homeInDirLikelyhood[i];
+ }
+ }
+
+ _characterDirectionArray[index] = retVal;
+}
+
+byte LilliputEngine::homeInAvoidDeadEnds(int indexb, int indexs) {
+ debugC(2, kDebugEngine, "homeInAvoidDeadEnds(%d, %d)", indexb, indexs);
+
+ static const int8 constDirX[4] = {1, 0, 0, -1};
+ static const int8 constDirY[4] = {0, -1, 1, 0};
+
+ Common::Point tmpPos = Common::Point(_curCharacterTilePos.x + constDirX[indexb], _curCharacterTilePos.y + constDirY[indexb]);
+
+ int16 idx = checkEnclosure(tmpPos);
+ if (idx == -1)
+ return 1;
+
+ if ((tmpPos.x >= _enclosureRect[idx].left) && (tmpPos.x <= _enclosureRect[idx].right) && (tmpPos.y >= _enclosureRect[idx].top) && (tmpPos.y <= _enclosureRect[idx].bottom))
+ return 0;
+
+ if ((tmpPos.x >= _enclosureRect[idx].left) && (tmpPos.x <= _enclosureRect[idx].right) && (tmpPos.y >= _enclosureRect[idx].top) && (tmpPos.y <= _enclosureRect[idx].bottom))
+ return 0;
+
+ return 1;
+}
+
+int16 LilliputEngine::checkEnclosure(Common::Point pos) {
+ debugC(2, kDebugEngine, "checkEnclosure(%d, %d)", pos.x, pos.y);
+
+ for (int i = 0; i < _rectNumb; ++i) {
+ if ((pos.x >= _enclosureRect[i].left) && (pos.x <= _enclosureRect[i].right) && (pos.y >= _enclosureRect[i].top) && (pos.y <= _enclosureRect[i].bottom))
+ return i;
+ }
+ return -1;
+}
+
+int16 LilliputEngine::checkOuterEnclosure(Common::Point pos) {
+ debugC(2, kDebugEngine, "checkOuterEnclosure(%d, %d)", pos.x, pos.y);
+
+ for (int i = _rectNumb - 1; i >= 0 ; --i) {
+ if ((pos.x >= _enclosureRect[i].left) && (pos.x <= _enclosureRect[i].right) && (pos.y >= _enclosureRect[i].top) && (pos.y <= _enclosureRect[i].bottom))
+ return i;
+ }
+ return -1;
+}
+
+void LilliputEngine::evaluateDirections(int index) {
+ debugC(2, kDebugEngine, "evaluateDirections(%d)", index);
+
+ static const int8 arrayMoveX[4] = {1, 0, 0, -1};
+ static const int8 arrayMoveY[4] = {0, -1, 1, 0};
+
+ int16 arrayDistance[4];
+
+ for (int i = 3; i >= 0; i--) {
+ int16 var1h = _curCharacterTilePos.x + arrayMoveX[i] - _characterSubTargetPos[index].x;
+ int16 var1l = _curCharacterTilePos.y + arrayMoveY[i] - _characterSubTargetPos[index].y;
+ arrayDistance[i] = (var1l * var1l) + (var1h * var1h);
+ }
+
+ for (int i = 0; i < 4; i++)
+ _homeInDirLikelyhood[i] = 0;
+
+ int8 tmpIndex = 0;
+ for (int i = 3; i > 0; i--) {
+ int16 smallestDistance = 0x7FFF;
+ for (int j = 0; j < 4; j++) {
+ if (smallestDistance > arrayDistance[j]) {
+ smallestDistance = arrayDistance[j];
+ tmpIndex = j;
+ }
+ }
+ arrayDistance[tmpIndex] = 0x7FFF;
+ _homeInDirLikelyhood[tmpIndex] = i;
+ }
+}
+
+void LilliputEngine::addCharToBuf(byte character) {
+ debugC(2, kDebugEngine, "addCharToBuf(%c)", character);
+
+ _displayStringBuf[_displayStringIndex] = character;
+ if (_displayStringIndex < 158)
+ ++_displayStringIndex;
+}
+
+void LilliputEngine::numberToString(int param1) {
+ debugC(2, kDebugEngine, "numberToString(%d)", param1);
+
+ static const int exp10[6] = {10000, 1000, 100, 10, 1};
+
+ int var1 = param1;
+ bool hideZeros = true;
+ for (int i = 0; i < 5; i++) {
+ int count = 0;
+ while (var1 >= 0) {
+ ++count;
+ var1 -= exp10[i];
+ }
+ var1 += exp10[i];
+ --count;
+
+ byte tmpVal = count + 0x30;
+
+ if (i == 4)
+ addCharToBuf(tmpVal);
+ else if ((count != 0) || (!hideZeros)) {
+ hideZeros = false;
+ addCharToBuf(tmpVal);
+ }
+ }
+}
+
+void LilliputEngine::updateCharPosSequence() {
+ debugC(2, kDebugEngine, "updateCharPosSequence()");
+
+ int index = _numCharacters - 1;
+ byte result;
+ while (index >= 0) {
+ result = kSeqRepeat;
+ while (result & kSeqRepeat) {
+ if (_scriptHandler->_characterNextSequence[index] == 16)
+ break;
+
+ uint16 index2 = _scriptHandler->_characterNextSequence[index] + (index * 16);
+ Common::Point var1 = _scriptHandler->_sequenceArr[index2];
+
+ // /8, then /2 as the function array is a word array
+ int16 posSeqType = var1.x / 16;
+
+ switch (posSeqType) {
+ case 0: // Move
+ // x stands for moveType, y for poseType
+ result = sequenceMoveCharacter(index, var1.x, var1.y);
+ break;
+ case 1: // Face direction
+ // x stands for the next direction, y for the poseType
+ result = sequenceSetCharacterDirection(index, var1.x, var1.y);
+ break;
+ case 10: // Seek move target
+ result = sequenceSeekMovingCharacter(index, var1);
+ break;
+ case 11: // Sound
+ result = sequenceSound(index, var1);
+ break;
+ case 12: // Home in target
+ result = sequenceCharacterHomeIn(index, var1);
+ break;
+ case 13: // Character mobility
+ result = sequenceSetMobility(index, var1);
+ break;
+ case 14: // Repeat sequence
+ result = sequenceRepeat(index, var1, index2);
+ break;
+ case 15: // End
+ result = sequenceEnd(index);
+ break;
+ default:
+ result = kSeqNone;
+ break;
+ }
+
+ if ((result & kSeqNoInc) == 0) {
+ ++_scriptHandler->_characterNextSequence[index];
+ if (_scriptHandler->_characterNextSequence[index] == 16)
+ _scriptHandler->_characterScriptEnabled[index] = 1;
+ }
+ }
+ --index;
+ }
+}
+
+byte LilliputEngine::sequenceEnd(int index) {
+ debugC(2, kDebugEngine, "sequenceEnd(%d)", index);
+
+ _scriptHandler->_characterNextSequence[index] = 16;
+ _scriptHandler->_characterScriptEnabled[index] = 1;
+
+ return kSeqNoInc;
+}
+
+byte LilliputEngine::sequenceRepeat(int index, Common::Point var1, int tmpVal) {
+ debugC(2, kDebugEngine, "sequenceRepeat(%d, %d - %d, %d)", index, var1.x, var1.y, tmpVal);
+
+ byte counter = var1.y;
+ if (counter != 0) {
+ if ((counter & 0xF0) == 0)
+ counter |= (counter << 4);
+
+ counter -= 16;
+ _scriptHandler->_sequenceArr[tmpVal] = Common::Point(var1.x, counter);
+
+ if ((counter & 0xF0) == 0)
+ return kSeqRepeat;
+ }
+
+ _scriptHandler->_characterNextSequence[index] -= (var1.x & 0x0F);
+ return kSeqNoInc | kSeqRepeat;
+}
+
+byte LilliputEngine::sequenceSetCharacterDirection(int index, int direction, int poseType) {
+ debugC(2, kDebugEngine, "sequenceSetCharacterDirection(%d, %d - %d)", index, direction, poseType);
+
+ char newDir = direction & 3;
+ _characterDirectionArray[index] = newDir;
+ setCharacterPose(index, poseType);
+
+ return kSeqNone;
+}
+
+byte LilliputEngine::sequenceSetMobility(int index, Common::Point var1) {
+ debugC(2, kDebugEngine, "sequenceSetMobility(%d, %d - %d)", index, var1.x, var1.y);
+
+ _characterMobility[index] = var1.y;
+ return kSeqRepeat;
+}
+
+byte LilliputEngine::sequenceSound(int index, Common::Point var1) {
+ debugC(2, kDebugEngine, "sequenceSound(%d, %d - %d)", index, var1.x, var1.y);
+
+ int param4x = ((index | 0xFF00) >> 8);
+ _soundHandler->play(var1.y, _scriptHandler->_viewportPos,
+ _scriptHandler->_characterTilePos[index], Common::Point(param4x, 0));
+ return kSeqRepeat;
+}
+
+byte LilliputEngine::sequenceSeekMovingCharacter(int index, Common::Point var1) {
+ debugC(2, kDebugEngine, "sequenceSeekMovingCharacter(%d, %d - %d)", index, var1.x, var1.y);
+
+ int charIndex = _scriptHandler->_characterSeek[index];
+ Common::Point charPos = _scriptHandler->_characterTilePos[charIndex];
+
+ if ((_characterSubTargetPos[index].x != -1) && (_characterSubTargetPos[index] == _characterTargetPos[index]))
+ _characterSubTargetPos[index] = charPos;
+
+ _characterTargetPos[index] = charPos;
+
+ return sequenceCharacterHomeIn(index, var1);
+}
+
+void LilliputEngine::checkSpecialCubes() {
+ debugC(2, kDebugEngine, "checkSpecialCubes()");
+
+ for (int index1 = _numCharacters - 1; index1 >= 0; index1--) {
+ // Hack: The original doesn't check if it's disabled, which looks wrong
+ if ((_scriptHandler->_characterTilePos[index1].x == -1) || (_scriptHandler->_characterTilePos[index1].y == -1))
+ continue;
+ //
+
+ int mapIndex = 3 + (_scriptHandler->_characterTilePos[index1].y * 64 + _scriptHandler->_characterTilePos[index1].x) * 4;
+ assert((mapIndex >= 0) && (mapIndex < 16384));
+ byte var1 = _bufferIsoMap[mapIndex] & 0x40;
+
+ if (var1 == _specialCubes[index1])
+ continue;
+
+ _specialCubes[index1] = var1;
+ if (var1 != 0)
+ _scriptHandler->_characterScriptEnabled[index1] = 1;
+ }
+}
+
+void LilliputEngine::handleCharacterTimers() {
+ debugC(2, kDebugEngine, "handleCharacterTimers()");
+
+ int index1 = _animationTick + 2;
+
+ for (byte i = 0; i < _numCharacters; i++) {
+ byte *varPtr = getCharacterAttributesPtr(index1);
+ if (varPtr[0] != 0) {
+ if (varPtr[0] == 1) {
+ varPtr[0] = 0;
+ } else {
+ --varPtr[0];
+ if (varPtr[0] == 1)
+ _scriptHandler->_characterScriptEnabled[i] = 1;
+ }
+ }
+
+ index1 += 32;
+ }
+}
+
+void LilliputEngine::keyboard_handleInterfaceShortcuts(bool &forceReturnFl) {
+ debugC(2, kDebugEngine, "keyboard_handleInterfaceShortcuts()");
+
+ forceReturnFl = false;
+
+ if (!_keyboard_checkKeyboard())
+ return;
+
+ Common::Event event = _keyboard_getch();
+
+ int8 index = -1;
+ for (int8 i = 0; i < _interfaceHotspotNumb; i++) {
+ if (event.kbd.keycode == _keyboardMapping[i]) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index != -1) {
+ byte button = 1;
+ if (event.type == Common::EVENT_KEYUP)
+ button = 2;
+ handleInterfaceHotspot(index, button);
+ forceReturnFl = true;
+ }
+}
+
+void LilliputEngine::checkNumericCode() {
+ debugC(2, kDebugEngine, "checkNumericCode()");
+
+ static bool altKeyFl = false;
+ static int16 keyCount = 0;
+
+ if (_keyboard_oldIndex == _keyboard_nextIndex)
+ return;
+
+ Common::Event oldEvent = _keyboard_buffer[_keyboard_oldIndex];
+ if ((oldEvent.kbd.keycode == Common::KEYCODE_LALT) || (oldEvent.kbd.keycode == Common::KEYCODE_RALT)) {
+ if (oldEvent.type == Common::EVENT_KEYDOWN) {
+ altKeyFl = true;
+ keyCount = 0;
+ return;
+ } else if (oldEvent.type == Common::EVENT_KEYUP) {
+ altKeyFl = false;
+ if (keyCount == 3)
+ _actionType = kCodeEntered;
+ return;
+ }
+ }
+
+ if (keyCount >= 3)
+ return;
+
+ if ((altKeyFl) && (oldEvent.type == Common::EVENT_KEYDOWN)) {
+ switch (oldEvent.kbd.keycode) {
+ case Common::KEYCODE_KP0:
+ case Common::KEYCODE_KP1:
+ case Common::KEYCODE_KP2:
+ case Common::KEYCODE_KP3:
+ case Common::KEYCODE_KP4:
+ case Common::KEYCODE_KP5:
+ case Common::KEYCODE_KP6:
+ case Common::KEYCODE_KP7:
+ case Common::KEYCODE_KP8:
+ case Common::KEYCODE_KP9:
+ case Common::KEYCODE_0:
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ case Common::KEYCODE_7:
+ case Common::KEYCODE_8:
+ case Common::KEYCODE_9:
+ _codeEntered[keyCount] = oldEvent.kbd.keycode - Common::KEYCODE_0;
+ ++keyCount;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void LilliputEngine::handleGameMouseClick() {
+ debugC(2, kDebugEngine, "handleGameMouseClick()");
+
+ checkNumericCode();
+
+ bool forceReturnFl = false;
+ keyboard_handleInterfaceShortcuts(forceReturnFl);
+ if (forceReturnFl)
+ return;
+
+ if (_mouseButton == 0) {
+ if (!_mouseClicked)
+ return;
+ _mouseClicked = false;
+ _mouseButton = 2;
+ }
+
+ int button = _mouseButton;
+ _mouseButton = 0;
+
+ if (button == 2) {
+ if (_lastInterfaceHotspotIndex != -1)
+ handleInterfaceHotspot(_lastInterfaceHotspotIndex, button);
+ return;
+ }
+
+ forceReturnFl = false;
+ checkInterfaceHotspots(forceReturnFl);
+ if (forceReturnFl)
+ return;
+
+ Common::Point pos = Common::Point(_mousePos.x - 64, _mousePos.y - 16);
+
+ if ((pos.x < 0) || (pos.x > 255) || (pos.y < 0) || (pos.y > 176))
+ return;
+
+ forceReturnFl = false;
+ checkClickOnCharacter(pos, forceReturnFl);
+ if (forceReturnFl)
+ return;
+
+ checkClickOnGameArea(pos);
+}
+
+void LilliputEngine::checkClickOnGameArea(Common::Point pos) {
+ debugC(2, kDebugEngine, "checkClickOnGameArea(%d, %d)", pos.x, pos.y);
+
+ int x = pos.x - 8;
+ int y = pos.y - 4;
+
+ x = (x / 16) - 7;
+ y = (y / 8) - 4;
+
+ int arrowY = (y - x) >> 1;
+ int arrowX = y - arrowY;
+
+ if ((arrowX >= 0) && (arrowY >= 0) && (arrowX < 8) && (arrowY < 8)) {
+ arrowX += _scriptHandler->_viewportPos.x;
+ arrowY += _scriptHandler->_viewportPos.y;
+ _savedMousePosDivided = Common::Point(arrowX, arrowY);
+ _actionType = kCubeSelected;
+ }
+}
+
+void LilliputEngine::checkClickOnCharacter(Common::Point pos, bool &forceReturnFl) {
+ debugC(2, kDebugEngine, "checkClickOnCharacter(%d, %d)", pos.x, pos.y);
+
+ forceReturnFl = false;
+
+ for (int8 i = 0; i < _numCharacters; i++) {
+ // check if position is over a character
+ if ((pos.x >= _characterDisplay[i].x) && (pos.x <= _characterDisplay[i].x + 17) && (pos.y >= _characterDisplay[i].y) && (pos.y <= _characterDisplay[i].y + 17) && (i != _host)) {
+ _selectedCharacterId = i;
+ _actionType = kActionGoto;
+ if (_delayedReactivationAction)
+ _actionType = kActionTalk;
+
+ forceReturnFl = true;
+ return;
+ }
+ }
+}
+
+void LilliputEngine::checkInterfaceHotspots(bool &forceReturnFl) {
+ debugC(2, kDebugEngine, "checkInterfaceHotspots()");
+
+ forceReturnFl = false;
+ for (int index = _interfaceHotspotNumb - 1; index >= 0; index--) {
+ if (isMouseOverHotspot(_mousePos, _interfaceHotspots[index])) {
+ handleInterfaceHotspot(index, 1);
+ forceReturnFl = true;
+ return;
+ }
+ }
+}
+
+bool LilliputEngine::isMouseOverHotspot(Common::Point mousePos, Common::Point hotspotPos) {
+ debugC(2, kDebugEngine, "isMouseOverHotspot(%d - %d, %d - %d)", mousePos.x, mousePos.y, hotspotPos.x, hotspotPos.y);
+
+ if ((mousePos.x < hotspotPos.x) || (mousePos.y < hotspotPos.y) || (mousePos.x > hotspotPos.x + 16) || (mousePos.y > hotspotPos.y + 16))
+ return false;
+
+ return true;
+}
+
+void LilliputEngine::handleInterfaceHotspot(byte index, byte button) {
+ debugC(2, kDebugEngine, "handleInterfaceHotspot(%d, %d)", index, button);
+
+ if (_scriptHandler->_interfaceHotspotStatus[index] < kHotspotEnabled)
+ return;
+
+ _lastInterfaceHotspotIndex = index;
+ _lastInterfaceHotspotButton = button;
+
+ if (button == 2) {
+ if (!_delayedReactivationAction) {
+ _scriptHandler->_interfaceHotspotStatus[index] = kHotspotEnabled;
+ _actionType = kButtonReleased;
+ displayInterfaceHotspots();
+ }
+ return;
+ }
+
+ if (_delayedReactivationAction) {
+ unselectInterfaceButton();
+ return;
+ }
+
+ unselectInterfaceHotspots();
+ _scriptHandler->_interfaceHotspotStatus[index] = kHotspotSelected;
+ if (_interfaceTwoStepAction[index] == 1) {
+ _delayedReactivationAction = true;
+ _displayGreenHand = true;
+ } else {
+ _actionType = kButtonPressed;
+ }
+
+ displayInterfaceHotspots();
+}
+
+void LilliputEngine::setCharacterPose(int charIdx, int poseIdx) {
+ debugC(2, kDebugEngine, "setCharacterPose(%d, %d)", charIdx, poseIdx);
+
+ // CHECKME: Add an assert on poseIdx to check if it's between 0 and 31?
+ int index = (charIdx * 32) + poseIdx;
+ _scriptHandler->_characterPose[charIdx] = _poseArray[index];
+}
+
+byte LilliputEngine::sequenceMoveCharacter(int idx, int moveType, int poseType) {
+ debugC(2, kDebugEngine, "sequenceMoveCharacter(%d, %d - %d)", idx, moveType, poseType);
+
+ setCharacterPose(idx, poseType);
+
+ int index = idx;
+ switch (moveType) {
+ case 0:
+ // No movement
+ break;
+ case 1:
+ moveCharacterSpeed2(index);
+ break;
+ case 2:
+ moveCharacterSpeed4(index);
+ break;
+ case 3:
+ moveCharacterBack2(index);
+ break;
+ case 4:
+ turnCharacter1(index);
+ break;
+ case 5:
+ turnCharacter2(index);
+ break;
+ case 6:
+ moveCharacterUp1(index);
+ break;
+ case 7:
+ moveCharacterUp2(index);
+ break;
+ case 8:
+ moveCharacterDown1(index);
+ break;
+ case 9:
+ moveCharacterDown2(index);
+ break;
+ case 10:
+ moveCharacterSpeed3(index);
+ break;
+ default:
+ // CHECKME: It's so bad it could be an error()
+ warning("sequenceMoveCharacter - Unexpected value %d", moveType);
+ }
+
+ return kSeqNone;
+}
+
+void LilliputEngine::turnCharacter1(int index) {
+ debugC(2, kDebugEngine, "turnCharacter1(%d)", index);
+
+ static const byte nextDirection[4] = {1, 3, 0, 2};
+ _characterDirectionArray[index] = nextDirection[_characterDirectionArray[index]];
+}
+
+void LilliputEngine::turnCharacter2(int index) {
+ debugC(2, kDebugEngine, "turnCharacter2(%d)", index);
+
+ static const byte nextDirection[4] = {2, 0, 3, 1};
+ _characterDirectionArray[index] = nextDirection[_characterDirectionArray[index]];
+}
+
+void LilliputEngine::moveCharacterUp1(int index) {
+ debugC(2, kDebugEngine, "moveCharacterUp1(%d)", index);
+
+ _characterPosAltitude[index] += 1;
+}
+
+void LilliputEngine::moveCharacterUp2(int index) {
+ debugC(2, kDebugEngine, "moveCharacterUp2(%d)", index);
+
+ _characterPosAltitude[index] += 2;
+}
+
+void LilliputEngine::moveCharacterDown1(int index) {
+ debugC(2, kDebugEngine, "moveCharacterDown1(%d)", index);
+
+ _characterPosAltitude[index] -= 1;
+}
+
+void LilliputEngine::moveCharacterDown2(int index) {
+ debugC(2, kDebugEngine, "moveCharacterDown2(%d)", index);
+
+ _characterPosAltitude[index] -= 2;
+}
+
+void LilliputEngine::moveCharacterSpeed2(int index) {
+ debugC(2, kDebugEngine, "moveCharacterSpeed2(%d)", index);
+
+ moveCharacterForward(index, 2);
+}
+
+void LilliputEngine::moveCharacterSpeed4(int index) {
+ debugC(2, kDebugEngine, "moveCharacterSpeed4(%d)", index);
+
+ moveCharacterForward(index, 4);
+}
+
+void LilliputEngine::moveCharacterBack2(int index) {
+ debugC(2, kDebugEngine, "moveCharacterBack2(%d)", index);
+
+ moveCharacterForward(index, -2);
+}
+
+void LilliputEngine::moveCharacterSpeed3(int index) {
+ debugC(2, kDebugEngine, "moveCharacterSpeed3(%d)", index);
+
+ moveCharacterForward(index, 3);
+}
+
+void LilliputEngine::moveCharacterForward(int index, int16 speed) {
+ debugC(2, kDebugEngine, "moveCharacterForward(%d, %d)", index, speed);
+
+ int16 newX = _characterPos[index].x;
+ int16 newY = _characterPos[index].y;
+ switch (_characterDirectionArray[index]) {
+ case 0:
+ newX += speed;
+ break;
+ case 1:
+ newY -= speed;
+ break;
+ case 2:
+ newY += speed;
+ break;
+ default:
+ newX -= speed;
+ break;
+ }
+ checkCollision(index, Common::Point(newX, newY), _characterDirectionArray[index]);
+}
+
+void LilliputEngine::checkCollision(int index, Common::Point pos, int direction) {
+ debugC(2, kDebugEngine, "checkCollision(%d, %d - %d, %d)", index, pos.x, pos.y, direction);
+
+ int16 diffX = pos.x >> 3;
+ if (((diffX & 0xFF) == _scriptHandler->_characterTilePos[index].x) && ((pos.y >> 3) == _scriptHandler->_characterTilePos[index].y)) {
+ _characterPos[index] = pos;
+ return;
+ }
+
+ if ((pos.x < 0) || (pos.x >= 512) || (pos.y < 0) || (pos.y >= 512))
+ return;
+
+ int mapIndex = (_scriptHandler->_characterTilePos[index].y * 64 + _scriptHandler->_characterTilePos[index].x) * 4;
+ assert(mapIndex < 16384);
+
+ if ((_bufferIsoMap[mapIndex + 3] & _doorExitMask[direction]) == 0)
+ return;
+
+ mapIndex = ((pos.y & 0xFFF8) << 3) + diffX;
+ mapIndex <<= 2;
+
+ if ((_bufferIsoMap[mapIndex + 3] & _doorEntranceMask[direction]) == 0)
+ return;
+
+ byte var1 = _characterMobility[index];
+ var1 &= 7;
+ var1 ^= 7;
+
+ if ((var1 & _cubeFlags[_bufferIsoMap[mapIndex]]) != 0)
+ return;
+
+ _characterPos[index] = pos;
+}
+
+void LilliputEngine::signalDispatcher(byte type, byte index, int var4) {
+ debugC(2, kDebugEngine, "signalDispatcher(%d, %d, %d)", type, index, var4);
+
+ if (type == 0) { // Message sent to one target character
+ sendMessageToCharacter(index, var4);
+ return;
+ }
+
+ if (type == 3) { // Broadcast - Sent to all characters
+ for (int i = _numCharacters - 1; i >= 0; i--)
+ sendMessageToCharacter(i, var4);
+ return;
+ }
+
+ int index2 = var4 & 0xFF;
+ for (byte i = 0; i < _numCharacters; i++) {
+ if ((_scriptHandler->_interactions[index2] & 0xFF) >= type)
+ sendMessageToCharacter(i, var4);
+ index2 += 40;
+ }
+}
+
+void LilliputEngine::sendMessageToCharacter(byte index, int var4) {
+ debugC(2, kDebugEngine, "sendMessageToCharacter(%d, %d)", index, var4);
+
+ if (_characterSignals[index] != -1) {
+ _signalArr[index] = var4;
+ } else {
+ _scriptHandler->_characterScriptEnabled[index] = 1;
+ _characterSignals[index] = var4;
+ }
+}
+
+void LilliputEngine::handleSignals() {
+ debugC(2, kDebugEngine, "handleSignals()");
+
+ for (byte i = 0; i < _numCharacters; i++) {
+ if (_signalArr[i] != -1) {
+ _characterSignals[i] = _signalArr[i];
+ _signalArr[i] = -1;
+ _scriptHandler->_characterScriptEnabled[i] = 1;
+ }
+ }
+
+ ++_signalTimer;
+
+ for (int i = 0; i < 10; i++) {
+ if ((_signalArray[(3 * i) + 1] != -1) && (_signalArray[3 * i] == _signalTimer)) {
+ int16 var1 = _signalArray[(3 * i) + 1];
+ int var4 = _signalArray[(3 * i) + 2];
+ _signalArray[(3 * i) + 1] = -1;
+
+ byte type = var1 >> 8;
+ byte index = var1 & 0xFF;
+
+ signalDispatcher(type, index, var4);
+ }
+ }
+}
+
+void LilliputEngine::checkInterfaceActivationDelay() {
+ debugC(2, kDebugEngine, "checkInterfaceActivationDelay()");
+
+ if (_animationTick != 1)
+ return;
+
+ bool needRedraw = false;
+ for (int i = 0; i < _interfaceHotspotNumb; i++) {
+ if (_scriptHandler->_interfaceButtonActivationDelay[i] != 0) {
+ --_scriptHandler->_interfaceButtonActivationDelay[i];
+ if (_scriptHandler->_interfaceButtonActivationDelay[i] == 0) {
+ _scriptHandler->_interfaceHotspotStatus[i] = kHotspotEnabled;
+ needRedraw = true;
+ }
+ }
+ }
+
+ if (needRedraw)
+ displayInterfaceHotspots();
+}
+
+void LilliputEngine::displayHeroismIndicator() {
+ debugC(2, kDebugEngine, "displayHeroismIndicator()");
+
+ if (_scriptHandler->_barAttrPtr == NULL)
+ return;
+
+ int var1 = (_scriptHandler->_barAttrPtr[0] * 25) >> 8;
+
+ if (var1 == _scriptHandler->_heroismLevel)
+ return;
+
+ int var2 = 1;
+ if (var1 > _scriptHandler->_heroismLevel)
+ var1 = 150;
+ else {
+ var2 = -1;
+ var1 = 40;
+ }
+
+ _scriptHandler->_heroismLevel += var2;
+
+ int index = _scriptHandler->_heroismBarX + (_scriptHandler->_heroismBarBottomY * 320);
+
+ var2 = _scriptHandler->_heroismLevel & 0xFF;
+ if (var2 != 0) {
+ for (int i = 0; i < (var2 << 2); i++) {
+ ((byte *)_mainSurface->getPixels())[index] = var1;
+ ((byte *)_mainSurface->getPixels())[index + 1] = var1;
+ ((byte *)_mainSurface->getPixels())[index + 2] = var1;
+ index -= 320;
+ }
+ }
+
+ if (25 - _scriptHandler->_heroismLevel != 0) {
+ var2 = (25 - _scriptHandler->_heroismLevel) << 2;
+ for (int i = 0; i < var2; i++) {
+ ((byte *)_mainSurface->getPixels())[index] = 23;
+ ((byte *)_mainSurface->getPixels())[index + 1] = 23;
+ ((byte *)_mainSurface->getPixels())[index + 2] = 23;
+ index -= 320;
+ }
+ }
+}
+
+void LilliputEngine::pollEvent() {
+ debugC(2, kDebugEngine, "pollEvent()");
+
+ Common::Event event;
+ while (_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_LBUTTONUP: {
+ Common::Point newMousePos = Common::Point(CLIP<int>(event.mouse.x, 0, 304), CLIP<int>(event.mouse.y, 0, 184));
+
+ if (_mousePreviousEventType != event.type) {
+ _mousePreviousEventType = event.type;
+ if (_mouseButton != 1) {
+ _mouseButton = 2;
+ if (event.type != Common::EVENT_MOUSEMOVE) {
+ _mouseButton = 1;
+ _mousePos = Common::Point(newMousePos.x + 5, newMousePos.y + 1);
+ }
+ } else {
+ _mouseClicked = true;
+ }
+ }
+
+ if (newMousePos != _oldMousePos) {
+ _oldMousePos = newMousePos;
+ _mouseDisplayPos = newMousePos;
+ }
+ _lastEventType = event.type;
+ }
+ break;
+ case Common::EVENT_QUIT:
+ _shouldQuit = true;
+ break;
+ case Common::EVENT_KEYUP:
+ case Common::EVENT_KEYDOWN: {
+ if ((event.type == _lastKeyPressed.type) && (event.kbd == _lastKeyPressed.kbd))
+ break;
+
+ _lastKeyPressed = event;
+ int nextIndex = (_keyboard_nextIndex + 1) % 8;
+ if (_keyboard_oldIndex != nextIndex) {
+ _keyboard_buffer[_keyboard_nextIndex] = event;
+ _keyboard_nextIndex = nextIndex;
+ }
+
+ _lastEventType = event.type;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+byte *LilliputEngine::loadVGA(Common::String filename, int expectedSize, bool loadPal) {
+ debugC(1, kDebugEngine, "loadVGA(%s, %d, %d)", filename.c_str(), expectedSize, (loadPal) ? 1 : 0);
+
+ Common::File f;
+
+ if (!f.open(filename))
+ error("Missing game file %s", filename.c_str());
+
+ int remainingSize = f.size();
+ if (loadPal) {
+ for (int i = 0; i < 768; ++i)
+ _curPalette[i] = f.readByte();
+ remainingSize -= 768;
+
+ fixPaletteEntries(_curPalette, 256);
+ }
+
+ uint8 curByte;
+ byte *decodeBuffer = (byte *)malloc(expectedSize);
+ int size = 0;
+
+ for (; (remainingSize > 0) && (size < expectedSize);) {
+ curByte = f.readByte();
+ --remainingSize;
+
+ if (curByte == 0xFF)
+ break;
+
+ if (curByte & 0x80) {
+ // Compressed
+ int compSize = (curByte & 0x7F);
+ curByte = f.readByte();
+ --remainingSize;
+
+ for (int i = 0; i < compSize; ++i) {
+ decodeBuffer[size] = curByte;
+ ++size;
+ if (size == expectedSize)
+ break;
+ }
+ } else {
+ // Not compressed
+ int rawSize = (curByte & 0xFF);
+ for (int i = 0; i < rawSize; ++i) {
+ decodeBuffer[size] = f.readByte();
+ --remainingSize;
+ ++size;
+ if (size == expectedSize)
+ break;
+ }
+ }
+ }
+ f.close();
+
+ for (int i = size; i < expectedSize; i++)
+ decodeBuffer[i] = 0;
+
+ return decodeBuffer;
+}
+
+byte *LilliputEngine::loadRaw(Common::String filename, int filesize) {
+ debugC(1, kDebugEngine, "loadRaw(%s)", filename.c_str());
+
+ Common::File f;
+
+ if (!f.open(filename))
+ error("Missing game file %s", filename.c_str());
+
+ byte *res = (byte *)malloc(sizeof(byte) * filesize);
+ for (int i = 0; i < filesize; ++i)
+ res[i] = f.readByte();
+
+ f.close();
+ return res;
+}
+
+void LilliputEngine::loadRules() {
+ debugC(1, kDebugEngine, "loadRules()");
+
+ static const Common::KeyCode keybMappingArray[26] = {
+ Common::KEYCODE_a, Common::KEYCODE_b, Common::KEYCODE_c, Common::KEYCODE_d, Common::KEYCODE_e,
+ Common::KEYCODE_f, Common::KEYCODE_g, Common::KEYCODE_h, Common::KEYCODE_i, Common::KEYCODE_j,
+ Common::KEYCODE_k, Common::KEYCODE_l, Common::KEYCODE_m, Common::KEYCODE_n, Common::KEYCODE_o,
+ Common::KEYCODE_p, Common::KEYCODE_q, Common::KEYCODE_r, Common::KEYCODE_s, Common::KEYCODE_t,
+ Common::KEYCODE_u, Common::KEYCODE_v, Common::KEYCODE_w, Common::KEYCODE_x, Common::KEYCODE_y,
+ Common::KEYCODE_z};
+ Common::File f;
+ uint16 curWord;
+
+ Common::String filename = "ERULES.PRG";
+ Common::Language lang = Common::parseLanguage(ConfMan.get("language"));
+
+ switch (lang) {
+ case Common::EN_ANY:
+ break;
+ case Common::FR_FRA:
+ filename = "FRULES.PRG";
+ break;
+ case Common::IT_ITA:
+ filename = "IRULES.PRG";
+ break;
+ case Common::DE_DEU:
+ filename = "GRULES.PRG";
+ break;
+ default:
+ warning("unsupported language, switching back to English");
+ }
+
+ if (!f.open(filename))
+ error("Missing game file %s", filename.c_str());
+
+ _word10800_ERULES = f.readUint16LE();
+
+ // Chunk 1 : Sequences
+ int size = f.readUint16LE();
+ _sequencesArr = (byte *)malloc(sizeof(byte) * size);
+ for (int i = 0; i < size; ++i)
+ _sequencesArr[i] = f.readByte();
+
+ // Chunk 2 : Characters
+ _numCharacters = (f.readUint16LE() & 0xFF);
+ assert(_numCharacters <= 40);
+
+ for (int i = _numCharacters, j = 0; i != 0; i--, j++) {
+ curWord = f.readUint16LE();
+ if (curWord != 0xFFFF)
+ curWord = (curWord << 3) + 4;
+ _characterPos[j].x = curWord;
+
+ curWord = f.readUint16LE();
+ if (curWord != 0xFFFF)
+ curWord = (curWord << 3) + 4;
+ _characterPos[j].y = curWord;
+
+ _characterPosAltitude[j] = (f.readUint16LE() & 0xFF);
+ _characterFrameArray[j] = f.readUint16LE();
+ _characterCarried[j] = (int8)f.readByte();
+ _characterBehindDist[j] = (int8)f.readByte();
+ _characterAboveDist[j] = f.readByte();
+ _spriteSizeArray[j] = f.readByte();
+ _characterDirectionArray[j] = f.readByte();
+ _characterMobility[j] = f.readByte();
+ _characterTypes[j] = f.readByte();
+ _characterBehaviour[j] = f.readByte();
+ _characterHomePos[j].x = f.readByte();
+ _characterHomePos[j].y = f.readByte();
+
+ for (int k = 0; k < 32; k++)
+ _characterVariables[(j * 32) + k] = f.readByte();
+
+ for (int k = 0; k < 32; k++)
+ _poseArray[(j * 32) + k] = f.readByte();
+ }
+
+ // Chunk 3 & 4 : Packed strings & associated indexes
+ _packedStringNumb = f.readSint16LE();
+ curWord = f.readSint16LE();
+
+ _packedStringIndex = (int *)malloc(sizeof(int) * _packedStringNumb);
+ for (int i = 0; i < _packedStringNumb; ++i)
+ _packedStringIndex[i] = f.readUint16LE();
+
+ _packedStrings = (char *)malloc(curWord);
+ for (int i = 0; i < curWord; ++i)
+ _packedStrings[i] = f.readByte();
+
+ // Chunk 5: Scripts
+ // Use byte instead of int, therefore multiply by two the size.
+ // This is for converting it into a memory read stream
+ _initScriptSize = f.readUint16LE() * 2;
+ _initScript = (byte *)malloc(_initScriptSize);
+ for (int i = 0; i < _initScriptSize; ++i)
+ _initScript[i] = f.readByte();
+
+ // Chunk 6: Menu Script
+ _menuScriptSize = f.readUint16LE() * 2;
+ _menuScript = (byte *)malloc(sizeof(byte) * _menuScriptSize);
+ for (int i = 0; i < _menuScriptSize; ++i)
+ _menuScript[i] = f.readByte();
+
+ // Chunk 7 & 8: Game scripts and indexes
+ _gameScriptIndexSize = f.readUint16LE();
+ // Added one position to keep the total size too, as it's useful later
+ _arrayGameScriptIndex = (int *)malloc(sizeof(int) * (_gameScriptIndexSize + 1));
+ for (int i = 0; i < _gameScriptIndexSize; ++i)
+ _arrayGameScriptIndex[i] = f.readUint16LE();
+
+ curWord = f.readUint16LE();
+ _arrayGameScriptIndex[_gameScriptIndexSize] = curWord;
+
+ _arrayGameScripts = (byte *)malloc(sizeof(byte) * curWord);
+ for (int i = 0; i < curWord; ++i)
+ _arrayGameScripts[i] = f.readByte();
+
+ // Chunk 9 : Cube flags
+ for (int i = 0; i < 60; i++)
+ _cubeFlags[i] = f.readByte();
+
+ // Chunk 10 & 11 : Lists
+ _listNumb = f.readByte();
+ assert(_listNumb <= 20);
+
+ if (_listNumb != 0) {
+ _listIndex = (int16 *)malloc(sizeof(int16) * _listNumb);
+ int totalSize = 0;
+ for (int i = 0; i < _listNumb; ++i) {
+ _listIndex[i] = totalSize;
+ totalSize += f.readByte();
+ }
+ if (totalSize != 0) {
+ _listArr = (byte *)malloc(sizeof(byte) * totalSize);
+ for (int i = 0; i < totalSize; i++)
+ _listArr[i] = f.readByte();
+ }
+ }
+
+ // Chunk 12
+ _rectNumb = f.readUint16LE();
+ assert((_rectNumb >= 0) && (_rectNumb <= 40));
+
+ for (int i = 0; i < _rectNumb; i++) {
+ _enclosureRect[i].right = (int16)f.readByte();
+ _enclosureRect[i].left = (int16)f.readByte();
+ _enclosureRect[i].bottom = (int16)f.readByte();
+ _enclosureRect[i].top = (int16)f.readByte();
+
+ int16 tmpValY = (int16)f.readByte();
+ int16 tmpValX = (int16)f.readByte();
+ _keyPos[i] = Common::Point(tmpValX, tmpValY);
+
+ tmpValY = (int16)f.readByte();
+ tmpValX = (int16)f.readByte();
+ _portalPos[i] = Common::Point(tmpValX, tmpValY);
+ }
+
+ // Chunk 13
+ _interfaceHotspotNumb = f.readUint16LE();
+ for (int i = 0 ; i < 20; i++)
+ _interfaceTwoStepAction[i] = f.readByte();
+
+ for (int i = 0 ; i < 20; i++)
+ _interfaceHotspots[i].x = f.readSint16LE();
+
+ for (int i = 0 ; i < 20; i++)
+ _interfaceHotspots[i].y = f.readSint16LE();
+
+ for (int i = 0; i < 20; i++) {
+ byte curByte = f.readByte();
+
+ if (curByte == 0x20)
+ _keyboardMapping[i] = Common::KEYCODE_SPACE;
+ else if (curByte == 0xD)
+ _keyboardMapping[i] = Common::KEYCODE_RETURN;
+ // Hack to avoid xlat out of bounds
+ else if (curByte == 0xFF)
+ _keyboardMapping[i] = Common::KEYCODE_INVALID; // 0x21; ?
+ // Hack to avoid xlat out of bounds
+ else if (curByte == 0x00)
+ _keyboardMapping[i] = Common::KEYCODE_INVALID; // 0xB4; ?
+ else {
+ assert((curByte > 0x40) && (curByte <= 0x41 + 26));
+ _keyboardMapping[i] = keybMappingArray[curByte - 0x41];
+ }
+ }
+ f.close();
+}
+
+void LilliputEngine::displayVGAFile(Common::String fileName) {
+ debugC(1, kDebugEngine, "displayVGAFile(%s)", fileName.c_str());
+
+ byte *buffer = loadVGA(fileName, 64000, true);
+ memcpy(_mainSurface->getPixels(), buffer, 320*200);
+ _system->copyRectToScreen((byte *)_mainSurface->getPixels(), 320, 0, 0, 320, 200);
+ _system->updateScreen();
+}
+
+void LilliputEngine::fixPaletteEntries(uint8 *palette, int num) {
+ debugC(1, kDebugEngine, "fixPaletteEntries(palette, %d)", num);
+ // Color values are coded on 6bits (for old 6bits DAC)
+ for (int32 i = 0; i < num * 3; i++) {
+ int32 col = palette[i];
+ assert(col < 64);
+
+ col = (col << 2) | (col >> 4);
+ if (col > 255)
+ col = 255;
+ palette[i] = col;
+ }
+}
+
+void LilliputEngine::initPalette() {
+ debugC(1, kDebugEngine, "initPalette()");
+
+ for (int i = 0; i < 768; i++)
+ _curPalette[i] = _basisPalette[i];
+
+ fixPaletteEntries(_curPalette, 256);
+ _system->getPaletteManager()->setPalette(_curPalette, 0, 256);
+}
+
+void LilliputEngine::setCurrentCharacter(int index) {
+ debugC(1, kDebugEngine, "setCurrentCharacter(%d)", index);
+
+ assert(index < 40);
+ _currentScriptCharacter = index;
+ _currentScriptCharacterPos = Common::Point(_characterPos[index].x >> 3, _characterPos[index].y >> 3);
+ _currentCharacterAttributes = getCharacterAttributesPtr(_currentScriptCharacter * 32);
+}
+
+void LilliputEngine::unselectInterfaceButton() {
+ debugC(1, kDebugEngine, "unselectInterfaceButton()");
+
+ _delayedReactivationAction = false;
+ _displayGreenHand = false;
+ _lastInterfaceHotspotButton = 0;
+ unselectInterfaceHotspots();
+ displayInterfaceHotspots();
+}
+
+void LilliputEngine::handleMenu() {
+ debugC(1, kDebugEngine, "handleMenu()");
+
+ if (_actionType == kActionNone)
+ return;
+
+ if (_delayedReactivationAction && (_actionType != kActionTalk))
+ return;
+
+ setCurrentCharacter(_host);
+ debugC(1, kDebugScriptTBC, "========================== Menu Script ==============================");
+ _scriptHandler->runMenuScript(ScriptStream(_menuScript, _menuScriptSize));
+ debugC(1, kDebugScriptTBC, "========================== End of Menu Script==============================");
+ _savedMousePosDivided = Common::Point(-1, -1);
+ _selectedCharacterId = -1;
+
+ if (_actionType == kActionTalk)
+ unselectInterfaceButton();
+
+ _actionType = kActionNone;
+}
+
+void LilliputEngine::handleGameScripts() {
+ debugC(1, kDebugEngine, "handleGameScripts()");
+
+ int index = _nextCharacterIndex;
+ int i;
+ for (i = 0; (_scriptHandler->_characterScriptEnabled[index] == 0) && (i < _numCharacters); i++) {
+ ++index;
+ if (index >= _numCharacters)
+ index = 0;
+ }
+
+ if (i > _numCharacters)
+ return;
+
+ _nextCharacterIndex = (index + 1) % _numCharacters;
+
+ _scriptHandler->_characterScriptEnabled[index] = 0;
+ setCurrentCharacter(index);
+
+ _waitingSignal = _characterSignals[index] >> 8;
+ _waitingSignalCharacterId = _characterSignals[index] & 0xFF;
+ _characterSignals[index] = -1;
+ _newModesEvaluatedNumber = 0;
+
+ int tmpVal = _characterBehaviour[index];
+ if (tmpVal == 0xFF)
+ return;
+
+ /* Decompiler follows
+
+ //_scriptHandler->listAllTexts();
+
+ debugC(1, kDebugEngineTBC, "================= Menu Script ==================");
+ ScriptStream script = ScriptStream(_menuScript, _menuScriptSize);
+ _scriptHandler->disasmScript(script);
+ debugC(1, kDebugEngineTBC, "============= End Menu Script ==================");
+
+
+ for (int i = 0; i < _gameScriptIndexSize; i++) {
+ assert(tmpVal < _gameScriptIndexSize);
+ debugC(1, kDebugEngineTBC, "================= Game Script %d ==================", i);
+ ScriptStream script = ScriptStream(&_arrayGameScripts[_arrayGameScriptIndex[i]], _arrayGameScriptIndex[i + 1] - _arrayGameScriptIndex[i]);
+ _scriptHandler->disasmScript(script);
+ debugC(1, kDebugEngineTBC, "============= End Game Script %d ==================", i);
+ }
+
+ while (1);
+ */
+
+ //i = index;
+ //debugC(1, kDebugEngineTBC, "before char %d, pos %d %d, var0 %d, var1 %d, var2 %d var16 %d, script enabled %d", i, _characterPositionX[i], _characterPositionY[i], *getCharacterVariablesPtr(i * 32 + 0), *getCharacterVariablesPtr(i * 32 + 1), *getCharacterVariablesPtr(i * 32 + 2), *getCharacterVariablesPtr(i * 32 + 22), _scriptHandler->_characterScriptEnabled[i]);
+
+ assert(tmpVal < _gameScriptIndexSize);
+ debugC(1, kDebugEngine, "================= Game Script %d for character %d ==================", tmpVal, index);
+ _scriptHandler->runScript(ScriptStream(&_arrayGameScripts[_arrayGameScriptIndex[tmpVal]], _arrayGameScriptIndex[tmpVal + 1] - _arrayGameScriptIndex[tmpVal]));
+ debugC(1, kDebugEngine, "============= End Game Script %d for character %d ==================", tmpVal, index);
+
+ //warning("dump char stat");
+ //debugC(1, kDebugEngineTBC, "after char %d, pos %d %d, var0 %d, var1 %d, var2 %d var16 %d, script enabled %d", i, _characterPositionX[i], _characterPositionY[i], *getCharacterVariablesPtr(i * 32 + 0), *getCharacterVariablesPtr(i * 32 + 1), *getCharacterVariablesPtr(i * 32 + 2), *getCharacterVariablesPtr(i * 32 + 22), _scriptHandler->_characterScriptEnabled[i]);
+}
+
+Common::Error LilliputEngine::run() {
+ debugC(1, kDebugEngine, "run()");
+
+ s_Engine = this;
+ initialize();
+ initGraphics(320, 200);
+ _mainSurface = new Graphics::Surface();
+ _mainSurface->create(320, 200, Graphics::PixelFormat::createFormatCLUT8());
+
+ // Setup mixer
+ syncSoundSettings();
+ _soundHandler->init();
+
+ // Init palette
+ initPalette();
+
+ // Load files. In the original, the size was hardcoded
+ _bufferIdeogram = loadVGA("IDEOGRAM.VGA", 25600, false);
+ _bufferMen = loadVGA("MEN.VGA", 61440, false);
+ _bufferMen2 = loadVGA("MEN2.VGA", 61440, false);
+ _bufferIsoChars = loadVGA("ISOCHARS.VGA", 4096, false);
+ _bufferIsoMap = loadRaw("ISOMAP.DTA", 16384);
+ _normalCursor = &_bufferIdeogram[80 * 16 * 16];
+ _greenCursor = &_bufferIdeogram[81 * 16 * 16];
+
+ CursorMan.replaceCursor(_normalCursor, 16, 16, 0, 0, 0);
+ CursorMan.showMouse(true);
+
+ loadRules();
+
+ _lastTime = _system->getMillis();
+ _scriptHandler->runScript(ScriptStream(_initScript, _initScriptSize));
+
+ while (!_shouldQuit) {
+ handleMenu();
+ handleGameScripts();
+ // To be removed when handled in the previous fonctions
+ update();
+ }
+
+ return Common::kNoError;
+}
+
+void LilliputEngine::initialize() {
+ debugC(1, kDebugEngine, "initialize");
+
+ _rnd = new Common::RandomSource("robin");
+ _rnd->setSeed(42); // Kick random number generator
+ _shouldQuit = false;
+
+ for (int i = 0; i < 4; i++) {
+ _smallAnims[i]._active = false;
+ _smallAnims[i]._pos = Common::Point(0, 0);
+ for (int j = 0; j < 8; j ++)
+ _smallAnims[i]._frameIndex[j] = 0;
+ }
+}
+
+byte *LilliputEngine::getCharacterAttributesPtr(int16 index) {
+ debugC(1, kDebugEngine, "getCharacterVariablesPtr(%d)", index);
+
+ assert((index > -3120) && (index < 1400));
+ if (index >= 0)
+ return &_characterVariables[index];
+ else
+ return &_characterVariables[1400 - index];
+}
+
+void LilliputEngine::syncSoundSettings() {
+ Engine::syncSoundSettings();
+
+// _sound->syncVolume();
+}
+
+Common::String LilliputEngine::getSavegameFilename(int slot) {
+ return _targetName + Common::String::format("-%02d.SAV", slot);
+}
+
+Common::Event LilliputEngine::_keyboard_getch() {
+ warning("getch()");
+ while(_keyboard_nextIndex == _keyboard_oldIndex)
+ pollEvent();
+
+ Common::Event tmpEvent = _keyboard_buffer[_keyboard_oldIndex];
+ _keyboard_oldIndex = (_keyboard_oldIndex + 1) % 8;
+
+ return tmpEvent;
+}
+
+bool LilliputEngine::_keyboard_checkKeyboard() {
+ return (_keyboard_nextIndex != _keyboard_oldIndex);
+}
+
+void LilliputEngine::_keyboard_resetKeyboardBuffer() {
+ _keyboard_nextIndex = _keyboard_oldIndex = 0;
+}
+
+} // End of namespace Lilliput
diff --git a/engines/lilliput/lilliput.h b/engines/lilliput/lilliput.h
new file mode 100644
index 0000000000..cb4e43c3da
--- /dev/null
+++ b/engines/lilliput/lilliput.h
@@ -0,0 +1,384 @@
+/* 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 LILLIPUT_LILLIPUT_H
+#define LILLIPUT_LILLIPUT_H
+
+#include "lilliput/console.h"
+#include "lilliput/script.h"
+#include "lilliput/sound.h"
+#include "lilliput/stream.h"
+
+#include "common/file.h"
+#include "common/rect.h"
+#include "common/events.h"
+
+#include "engines/engine.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+
+namespace Common {
+class RandomSource;
+}
+
+/**
+ * This is the namespace of the Lilliput engine.
+ *
+ * Status of this engine:
+ * - Adventures of Robin Hood is mostly working without sound
+ *
+ * Games using this engine:
+ * - Adventures of Robin Hood
+ * - Rome: Pathway to Rome
+ */
+namespace Lilliput {
+
+static const int kSavegameVersion = 1;
+
+enum GameType {
+ kGameTypeNone = 0,
+ kGameTypeRobin,
+ kGameTypeRome
+};
+
+enum LilliputDebugChannels {
+ kDebugEngine = 1 << 0,
+ kDebugScript = 1 << 1,
+ kDebugSound = 1 << 2,
+ kDebugEngineTBC = 1 << 3,
+ kDebugScriptTBC = 1 << 4
+};
+
+enum InterfaceHotspotStatus {
+ kHotspotOff = 0,
+ kHotspotDisabled = 1,
+ kHotspotEnabled = 2,
+ kHotspotSelected = 3
+};
+
+#define kSeqNone 0
+#define kSeqNoInc 1 << 0
+#define kSeqRepeat 1 << 1
+
+struct LilliputGameDescription;
+
+struct SmallAnim {
+ bool _active;
+ Common::Point _pos;
+ int16 _frameIndex[8];
+};
+
+class LilliputEngine : public Engine {
+public:
+ LilliputEngine(OSystem *syst, const LilliputGameDescription *gd);
+ ~LilliputEngine();
+
+ OSystem *_system;
+
+ GUI::Debugger *getDebugger();
+
+ Common::RandomSource *_rnd;
+ LilliputScript *_scriptHandler;
+ LilliputSound *_soundHandler;
+ Graphics::Surface *_mainSurface;
+
+ SmallAnim _smallAnims[4];
+ int _smallAnimsFrameIndex;
+
+ byte _handleOpcodeReturnCode;
+ byte _keyDelay;
+ byte _lastAnimationTick;
+ byte _animationTick;
+ Common::Point _nextDisplayCharacterPos;
+ byte _int8Timer;
+ Common::Event _lastKeyPressed;
+ Common::EventType _lastEventType;
+ byte _keyboard_nextIndex;
+ byte _keyboard_oldIndex;
+ Common::Event _keyboard_buffer[8];
+ byte _byte12A05;
+ bool _refreshScreenFlag;
+ byte _byte16552;
+ int8 _lastInterfaceHotspotIndex;
+ byte _lastInterfaceHotspotButton; // Unused: set by 2 functions, but never used elsewhere
+ byte _debugFlag; // Mostly useless, as the associated functions are empty
+ byte _debugFlag2; // Unused byte, set by an opcode
+
+ byte _codeEntered[3];
+ char _homeInDirLikelyhood[4];
+ byte *_bufferIsoMap;
+ byte *_bufferCubegfx;
+ byte *_bufferMen;
+ byte *_bufferMen2;
+ byte *_bufferIsoChars;
+ byte *_bufferIdeogram;
+ byte *_normalCursor;
+ byte *_greenCursor;
+ byte _curPalette[768];
+ byte _displayStringBuf[160];
+
+ bool _saveFlag;
+ bool _displayMap;
+
+ int _word10800_ERULES;
+ byte _numCharacters;
+ Common::Point _currentScriptCharacterPos;
+ int _nextCharacterIndex;
+ int8 _waitingSignal;
+ int8 _waitingSignalCharacterId;
+ uint16 _newModesEvaluatedNumber;
+ Common::Point _savedSurfaceUnderMousePos;
+ bool _displayGreenHand;
+ bool _isCursorGreenHand;
+ int _currentDisplayCharacter;
+ int _displayStringIndex;
+ int _signalTimer;
+ Common::Point _curCharacterTilePos;
+
+ int16 _mapSavedPixelIndex[40];
+ byte _mapSavedPixel[40];
+ int16 _characterSignals[40];
+ int16 _signalArr[40];
+ int16 _signalArray[30];
+
+ byte *_sequencesArr;
+ int16 _currentScriptCharacter;
+ Common::Point _characterPos[40];
+ int8 _characterPosAltitude[40];
+ int16 _characterFrameArray[40];
+ int8 _characterCarried[40];
+ int8 _characterBehindDist[40];
+ byte _characterAboveDist[40];
+ byte _spriteSizeArray[40];
+ byte _characterDirectionArray[40];
+ byte _characterMobility[40];
+ byte _characterTypes[40];
+ byte _characterBehaviour[40];
+ Common::Point _characterHomePos[40];
+ byte _characterVariables[1400 + 3120];
+ byte *_currentCharacterAttributes;
+ byte _poseArray[40 * 32];
+ int *_packedStringIndex;
+ int _packedStringNumb;
+ char *_packedStrings;
+ byte *_initScript;
+ int _initScriptSize;
+ byte *_menuScript;
+ int _menuScriptSize;
+ int *_arrayGameScriptIndex;
+ int _gameScriptIndexSize;
+ byte *_arrayGameScripts;
+ byte _cubeFlags[60];
+ byte _listNumb;
+ int16 *_listIndex;
+ byte *_listArr;
+ int16 _rectNumb;
+ Common::Rect _enclosureRect[40];
+ Common::Point _keyPos[40];
+ Common::Point _portalPos[40];
+ int _interfaceHotspotNumb;
+ byte _interfaceTwoStepAction[20];
+ Common::Point _interfaceHotspots[20];
+ Common::KeyCode _keyboardMapping[20];
+ Common::Point _characterTargetPos[40];
+ byte _savedSurfaceUnderMouse[16 * 16];
+ byte _charactersToDisplay[40];
+ Common::Point _characterRelativePos[40];
+ Common::Point _characterDisplay[40];
+ int8 _characterMagicPuffFrame[40];
+ Common::Point _characterSubTargetPos[40];
+ byte _specialCubes[40];
+ byte _doorEntranceMask[4];
+ byte _doorExitMask[4];
+ byte _savedSurfaceGameArea1[176 * 256]; // 45056
+ byte _savedSurfaceGameArea2[176 * 256]; // 45056
+ byte _savedSurfaceGameArea3[176 * 256]; // 45056
+ byte _savedSurfaceSpeech[16 * 252];
+
+ const LilliputGameDescription *_gameDescription;
+ uint32 getFeatures() const;
+ const char *getGameId() const;
+
+ void newInt8();
+ void update();
+
+ void display16x16IndexedBuf(byte *buf, int index, Common::Point pos, bool transparent = true, bool updateScreen = true);
+ void display16x16Buf(byte *buf, Common::Point pos, bool transparent = true, bool updateScreen = true);
+ void fill16x16Rect(byte col, Common::Point pos);
+ void saveSurfaceGameArea();
+ void saveSurfaceSpeech();
+ void displayInterfaceHotspots();
+ void displayLandscape();
+ void displaySpeechBubble();
+ void displaySpeech(byte *buf);
+ void initGameAreaDisplay();
+ void displayIsometricBlock(byte *buf, int var1, int posX, int posY, int var3);
+ void displayGameArea();
+ void prepareGameArea();
+ void displayRefreshScreen();
+ void restoreSurfaceSpeech();
+ void displayCharacterStatBar(int8 type, int16 averagePosX, int8 score, int16 posY);
+ void displayCharacter(int index, Common::Point pos, int flags);
+ void displayString(byte *buf, Common::Point pos);
+ void displayChar(int index, int var1);
+ void displaySmallAnims();
+ void displaySmallIndexedAnim(byte index, byte subIndex);
+
+ void unselectInterfaceHotspots();
+ void startNavigateFromMap();
+ void resetSmallAnims();
+ void paletteFadeOut();
+ void paletteFadeIn();
+
+ void sortCharacters();
+ void scrollToViewportCharacterTarget();
+ void viewportScrollTo(Common::Point goalPos);
+ void checkSpeechClosing();
+ void updateCharPosSequence();
+ void evaluateDirections(int index);
+ byte homeInAvoidDeadEnds(int indexb, int indexs);
+ void signalDispatcher(byte type, byte index, int var4);
+ void sendMessageToCharacter(byte index, int var4);
+ int16 checkEnclosure(Common::Point pos);
+ int16 checkOuterEnclosure(Common::Point pos);
+ byte sequenceSetMobility(int index, Common::Point var1);
+ byte sequenceEnd(int index);
+ void homeInPathFinding(int index);
+
+ void renderCharacters(byte *buf, Common::Point pos);
+
+ void checkNumericCode();
+ void keyboard_handleInterfaceShortcuts(bool &forceReturnFl);
+ byte sequenceCharacterHomeIn(int index, Common::Point param1);
+ byte getDirection(Common::Point param1, Common::Point param2);
+ void addCharToBuf(byte character);
+ void numberToString(int param1);
+ void handleCharacterTimers();
+ byte sequenceMoveCharacter(int idx, int moveType, int poseType);
+ void setCharacterPose(int idx, int poseIdx);
+ void checkSpecialCubes();
+ void checkInteractions();
+ byte sequenceSetCharacterDirection(int index, int direction, int poseType);
+ void handleSignals();
+ void checkInterfaceActivationDelay();
+ int16 checkObstacle(int x1, int y1, int x2, int y2);
+ void displayCharactersOnMap();
+ void restoreMapPoints();
+ void displayHeroismIndicator();
+ void handleGameMouseClick();
+ void handleInterfaceHotspot(byte index, byte button);
+ void checkInterfaceHotspots(bool &forceReturnFl);
+ bool isMouseOverHotspot(Common::Point mousePos, Common::Point hotspotPos);
+ void checkClickOnCharacter(Common::Point pos, bool &forceReturnFl);
+ void checkClickOnGameArea(Common::Point pos);
+ void displaySpeechBubbleTail(Common::Point displayPos);
+ void displaySpeechBubbleTailLine(Common::Point pos, int var2);
+ void displaySpeechLine(int vgaIndex, byte *srcBuf, int &bufIndex);
+ void checkMapClosing(bool &forceReturnFl);
+ void turnCharacter1(int index);
+ void turnCharacter2(int index);
+ void moveCharacterUp1(int index);
+ void moveCharacterUp2(int index);
+ void moveCharacterDown1(int index);
+ void moveCharacterDown2(int index);
+ void moveCharacterSpeed2(int index);
+ void moveCharacterSpeed4(int index);
+ void moveCharacterBack2(int index);
+ void moveCharacterSpeed3(int index);
+ void moveCharacterForward(int index, int16 speed);
+ void checkCollision(int index, Common::Point pos, int direction);
+ byte sequenceSeekMovingCharacter(int index, Common::Point var1);
+ byte sequenceSound(int index, Common::Point var1);
+ byte sequenceRepeat(int index, Common::Point var1, int tmpVal);
+ void homeInChooseDirection(int index);
+
+ void initGame(const LilliputGameDescription *gd);
+ byte *loadVGA(Common::String filename, int fileSize, bool loadPal);
+ byte *loadRaw(Common::String filename, int filesize);
+ void loadRules();
+
+ void displayVGAFile(Common::String fileName);
+ void initPalette();
+ void fixPaletteEntries(uint8 *palette, int num);
+
+ GameType getGameType() const;
+ Common::Platform getPlatform() const;
+
+ bool hasFeature(EngineFeature f) const;
+ const char *getCopyrightString() const;
+
+ Common::String getSavegameFilename(int slot);
+ void syncSoundSettings();
+
+ Common::Point _mousePos;
+ Common::Point _oldMousePos;
+ Common::Point _mouseDisplayPos;
+ int _mouseButton;
+ bool _mouseClicked;
+ Common::EventType _mousePreviousEventType;
+ Common::Point _savedMousePosDivided;
+ int _skipDisplayFlag1;
+ int _skipDisplayFlag2;
+
+ byte _actionType;
+ bool _delayedReactivationAction;
+ int8 _selectedCharacterId;
+ byte _numCharactersToDisplay;
+ int16 _host;
+ bool _shouldQuit;
+
+ void pollEvent();
+ void setCurrentCharacter(int index);
+ void unselectInterfaceButton();
+ void moveCharacters();
+ void setNextDisplayCharacter(int var1);
+ void handleGameScripts();
+
+ // Added by Strangerke
+ byte *getCharacterAttributesPtr(int16 index);
+
+ // Temporary stubs
+ Common::Event _keyboard_getch();
+ bool _keyboard_checkKeyboard();
+ void _keyboard_resetKeyboardBuffer();
+
+protected:
+ Common::EventManager *_eventMan;
+ int _lastTime;
+
+ // Engine APIs
+ Common::Error run();
+ void handleMenu();
+
+private:
+ static LilliputEngine *s_Engine;
+
+ LilliputConsole *_console;
+ GameType _gameType;
+ Common::Platform _platform;
+
+ void initialize();
+};
+
+} // End of namespace Lilliput
+
+#endif
diff --git a/engines/lilliput/module.mk b/engines/lilliput/module.mk
new file mode 100644
index 0000000000..8a095e8045
--- /dev/null
+++ b/engines/lilliput/module.mk
@@ -0,0 +1,20 @@
+MODULE := engines/lilliput
+
+MODULE_OBJS = \
+ console.o \
+ detection.o \
+ lilliput.o \
+ script.o \
+ sound.o \
+ stream.o
+
+MODULE_DIRS += \
+ engines/lilliput
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_LILLIPUT), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/lilliput/script.cpp b/engines/lilliput/script.cpp
new file mode 100644
index 0000000000..cc78c31d37
--- /dev/null
+++ b/engines/lilliput/script.cpp
@@ -0,0 +1,3355 @@
+/* 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 "lilliput/lilliput.h"
+#include "lilliput/script.h"
+#include "common/debug.h"
+
+#include "common/system.h"
+#include <climits>
+
+namespace Lilliput {
+
+LilliputScript::LilliputScript(LilliputEngine *vm) : _vm(vm), _currScript(NULL) {
+ _cubeSet = 0;
+ _lastRandomValue = 0;
+ _scriptForVal = 0;
+ _textVarNumber = 0;
+ _speechDisplaySpeed = 3;
+ _speechTimer = 0;
+ _word16F00_characterId = -1;
+ _monitoredCharacter = 0;
+ _viewportCharacterTarget = -1;
+ _heroismBarX = 0;
+ _heroismBarBottomY = 0;
+ _viewportPos.x = 0;
+ _viewportPos.y = 0;
+ _currentSpeechId = 0;
+ _monitoredAttr[0] = 0;
+ _monitoredAttr[1] = 1;
+ _monitoredAttr[2] = 2;
+ _monitoredAttr[3] = 3;
+ _barAttrPtr = NULL;
+ _word1825E = Common::Point(0, 0);
+
+ for (int i = 0; i < 20; i++) {
+ _interfaceHotspotStatus[i] = kHotspotOff;
+ _interfaceButtonActivationDelay[i] = 0;
+ }
+
+ for (int i = 0; i < 32; i++) {
+ _newEvaluatedModes[i]._mode = 0;
+ _newEvaluatedModes[i]._priority = 0;
+ }
+
+ for (int i = 0; i < 40; i++) {
+ _characterScriptEnabled[i] = 1;
+ _characterMapPixelColor[i] = 15;
+ _characterPose[i] = 0;
+ _characterNextSequence[i] = 16;
+ _characterLastSequence[i] = -1;
+ _characterTilePos[i] = Common::Point(0, 0);
+ _array122C1[i] = 0;
+ }
+
+ for (int i = 0; i < 640; i++) {
+ _sequenceArr[i] = Common::Point(-1, -1);
+ }
+
+ for (int i = 0; i < 1600; i++)
+ _interactions[i] = 0;
+
+ _heroismLevel = 0;
+ _talkingCharacter = -1;
+ _byte16F05_ScriptHandler = 0;
+ _word18821 = 0;
+}
+
+LilliputScript::~LilliputScript() {
+}
+
+byte LilliputScript::handleOpcodeType1(int curWord) {
+ debugC(2, kDebugScript, "handleOpcodeType1(0x%x)", curWord);
+ switch (curWord) {
+ case 0x0:
+ return OC_checkCharacterGoalPos();
+ break;
+ case 0x1:
+ return OC_comparePos();
+ break;
+ case 0x2:
+ return OC_checkIsoMap3();
+ break;
+ case 0x3:
+ return OC_compareCharacterVariable();
+ break;
+ case 0x4:
+ return OC_CompareLastRandomValue();
+ break;
+ case 0x5:
+ return OC_getRandom();
+ break;
+ case 0x6:
+ return OC_for();
+ break;
+ case 0x7:
+ return OC_compCurrentSpeechId();
+ break;
+ case 0x8:
+ return OC_checkSaveFlag();
+ break;
+ case 0x9:
+ return OC_compScriptForVal();
+ break;
+ case 0xA:
+ return OC_isCarrying();
+ break;
+ case 0xB:
+ return OC_CompareCharacterVariables();
+ break;
+ case 0xC:
+ return OC_compareCoords_1();
+ break;
+ case 0xD:
+ return OC_compareCoords_2();
+ break;
+ case 0xE:
+ return OC_CompareDistanceFromCharacterToPositionWith();
+ break;
+ case 0xF:
+ return OC_compareRandomCharacterId();
+ break;
+ case 0x10:
+ return OC_IsCurrentCharacterIndex();
+ break;
+ case 0x11:
+ return OC_hasVisibilityLevel();
+ break;
+ case 0x12:
+ return OC_hasGainedVisibilityLevel();
+ break;
+ case 0x13:
+ return OC_hasReducedVisibilityLevel();
+ break;
+ case 0x14:
+ return OC_isHost();
+ break;
+ case 0x15:
+ return OC_isSequenceActive();
+ break;
+ case 0x16:
+ return OC_isSequenceFinished();
+ break;
+ case 0x17:
+ return OC_CompareMapValueWith();
+ break;
+ case 0x18:
+ return OC_IsCharacterValid();
+ break;
+ case 0x19:
+ return OC_CheckWaitingSignal();
+ break;
+ case 0x1A:
+ return OC_CurrentCharacterVar0AndVar1Equals();
+ break;
+ case 0x1B:
+ return OC_CurrentCharacterVar0Equals();
+ break;
+ case 0x1C:
+ return OC_checkLastInterfaceHotspotIndexMenu13();
+ break;
+ case 0x1D:
+ return OC_checkLastInterfaceHotspotIndexMenu2();
+ break;
+ case 0x1E:
+ return OC_CompareNumberOfCharacterWithVar0Equals();
+ break;
+ case 0x1F:
+ return OC_IsPositionInViewport();
+ break;
+ case 0x20:
+ return OC_CompareGameVariables();
+ break;
+ case 0x21:
+ return OC_skipNextOpcode();
+ break;
+ case 0x22:
+ return OC_CheckCurrentCharacterAttr2();
+ break;
+ case 0x23:
+ return OC_CheckCurrentCharacterType();
+ break;
+ case 0x24:
+ return OC_CheckCurrentCharacterAttr0And();
+ break;
+ case 0x25:
+ return OC_IsCurrentCharacterAttr0LessEqualThan();
+ break;
+ case 0x26:
+ return OC_isCarried();
+ break;
+ case 0x27:
+ return OC_CheckCurrentCharacterAttr1();
+ break;
+ case 0x28:
+ return OC_isCurrentCharacterSpecial();
+ break;
+ case 0x29:
+ return OC_CurrentCharacterAttr3Equals1();
+ break;
+ case 0x2A:
+ return OC_checkCharacterDirection();
+ break;
+ case 0x2B:
+ return OC_checkLastInterfaceHotspotIndex();
+ break;
+ case 0x2C:
+ return OC_checkSelectedCharacter();
+ break;
+ case 0x2D:
+ return OC_checkDelayedReactivation();
+ break;
+ case 0x2E:
+ return OC_checkTargetReached();
+ break;
+ case 0x2F:
+ return OC_checkFunctionKeyPressed();
+ break;
+ case 0x30:
+ return OC_checkCodeEntered();
+ break;
+ case 0x31:
+ return OC_checkViewPortCharacterTarget();
+ break;
+ default:
+ error("Unexpected opcode %d", curWord);
+ break;
+ }
+}
+
+void LilliputScript::handleOpcodeType2(int curWord) {
+ debugC(2, kDebugScript, "handleOpcodeType2(0x%x)", curWord);
+ switch (curWord) {
+ case 0x0:
+ OC_setWord18821();
+ break;
+ case 0x1:
+ OC_ChangeIsoMap();
+ break;
+ case 0x2:
+ OC_startSpeech();
+ break;
+ case 0x3:
+ OC_getComputedVariantSpeech();
+ break;
+ case 0x4:
+ OC_getRotatingVariantSpeech();
+ break;
+ case 0x5:
+ OC_startSpeechIfMute();
+ break;
+ case 0x6:
+ OC_getComputedVariantSpeechIfMute();
+ break;
+ case 0x7:
+ OC_startSpeechIfSilent();
+ break;
+ case 0x8:
+ OC_ComputeCharacterVariable();
+ break;
+ case 0x9:
+ OC_setAttributeToRandom();
+ break;
+ case 0xA:
+ OC_setCharacterPosition();
+ break;
+ case 0xB:
+ OC_DisableCharacter();
+ break;
+ case 0xC:
+ OC_saveAndQuit();
+ break;
+ case 0xD:
+ OC_nSkipOpcodes();
+ break;
+ case 0xE:
+ OC_startSpeech5();
+ break;
+ case 0xF:
+ OC_resetHandleOpcodeFlag();
+ break;
+ case 0x10:
+ OC_deleteSavegameAndQuit();
+ break;
+ case 0x11:
+ OC_incScriptForVal();
+ break;
+ case 0x12:
+ OC_computeChararacterAttr();
+ break;
+ case 0x13:
+ OC_setTextVarNumber();
+ break;
+ case 0x14:
+ OC_callScript();
+ break;
+ case 0x15:
+ OC_callScriptAndReturn();
+ break;
+ case 0x16:
+ OC_setCurrentScriptCharacterPos();
+ break;
+ case 0x17:
+ OC_initScriptFor();
+ break;
+ case 0x18:
+ OC_setCurrentCharacterSequence();
+ break;
+ case 0x19:
+ OC_setNextCharacterSequence();
+ break;
+ case 0x1A:
+ OC_setHost();
+ break;
+ case 0x1B:
+ OC_changeMapCube();
+ break;
+ case 0x1C:
+ OC_setCharacterCarry();
+ break;
+ case 0x1D:
+ OC_dropCarried();
+ break;
+ case 0x1E:
+ OC_setCurrentCharacter();
+ break;
+ case 0x1F:
+ OC_sendSeeSignal();
+ break;
+ case 0x20:
+ OC_sendHearSignal();
+ break;
+ case 0x21:
+ OC_sendVarSignal();
+ break;
+ case 0x22:
+ OC_sendBroadcastSignal();
+ break;
+ case 0x23:
+ OC_resetWaitingSignal();
+ break;
+ case 0x24:
+ OC_enableCurrentCharacterScript();
+ break;
+ case 0x25:
+ OC_IncCurrentCharacterVar1();
+ break;
+ case 0x26:
+ OC_setCurrentCharacterPos();
+ break;
+ case 0x27:
+ OC_setCurrentCharacterBehavior();
+ break;
+ case 0x28:
+ OC_changeCurrentCharacterSprite();
+ break;
+ case 0x29:
+ OC_getList();
+ break;
+ case 0x2A:
+ OC_setList();
+ break;
+ case 0x2B:
+ OC_setCharacterDirectionTowardsPos();
+ break;
+ case 0x2C:
+ OC_turnCharacterTowardsAnother();
+ break;
+ case 0x2D:
+ OC_setSeek();
+ break;
+ case 0x2E:
+ OC_scrollAwayFromCharacter();
+ break;
+ case 0x2F:
+ OC_skipNextVal();
+ break;
+ case 0x30:
+ OC_setCurrentCharacterAttr6();
+ break;
+ case 0x31:
+ OC_setCurrentCharacterPose();
+ break;
+ case 0x32:
+ OC_setCharacterScriptEnabled();
+ break;
+ case 0x33:
+ OC_setCurrentCharacterAttr2();
+ break;
+ case 0x34:
+ OC_clearCurrentCharacterAttr2();
+ break;
+ case 0x35:
+ OC_setCharacterProperties();
+ break;
+ case 0x36:
+ OC_setMonitoredCharacter();
+ break;
+ case 0x37:
+ OC_setNewPose();
+ break;
+ case 0x38:
+ OC_setCurrentCharacterDirection();
+ break;
+ case 0x39:
+ OC_setInterfaceHotspot();
+ break;
+ case 0x3A:
+ OC_scrollViewPort();
+ break;
+ case 0x3B:
+ OC_setViewPortPos();
+ break;
+ case 0x3C:
+ OC_setCurrentCharacterAltitude();
+ break;
+ case 0x3D:
+ OC_setModePriority();
+ break;
+ case 0x3E:
+ OC_setComputedModePriority();
+ break;
+ case 0x3F:
+ OC_selectBestMode();
+ break;
+ case 0x40:
+ OC_magicPuffEntrance();
+ break;
+ case 0x41:
+ OC_spawnCharacterAtPos();
+ break;
+ case 0x42:
+ OC_CharacterVariableAddOrRemoveFlag();
+ break;
+ case 0x43:
+ OC_PaletteFadeOut();
+ break;
+ case 0x44:
+ OC_PaletteFadeIn();
+ break;
+ case 0x45:
+ OC_loadAndDisplayCubesGfx();
+ break;
+ case 0x46:
+ OC_setCurrentCharacterAttr3();
+ break;
+ case 0x47:
+ OC_setArray122C1();
+ break;
+ case 0x48:
+ OC_sub18367();
+ break;
+ case 0x49:
+ OC_enableCharacterScript();
+ break;
+ case 0x4A:
+ OC_setRulesBuffer2Element();
+ break;
+ case 0x4B:
+ OC_setDebugFlag();
+ break;
+ case 0x4C:
+ OC_setDebugFlag2();
+ break;
+ case 0x4D:
+ OC_waitForEvent();
+ break;
+ case 0x4E:
+ OC_disableInterfaceHotspot();
+ break;
+ case 0x4F:
+ OC_loadFileAerial();
+ break;
+ case 0x50:
+ OC_startSpeechIfSoundOff();
+ break;
+ case 0x51:
+ OC_sub1844A();
+ break;
+ case 0x52:
+ OC_displayNumericCharacterVariable();
+ break;
+ case 0x53:
+ OC_displayVGAFile();
+ break;
+ case 0x54:
+ OC_startSpeechWithoutSpeeker();
+ break;
+ case 0x55:
+ OC_displayTitleScreen();
+ break;
+ case 0x56:
+ OC_initGameAreaDisplay();
+ break;
+ case 0x57:
+ OC_displayCharacterStatBar();
+ break;
+ case 0x58:
+ OC_initSmallAnim();
+ break;
+ case 0x59:
+ OC_setCharacterHeroismBar();
+ break;
+ case 0x5A:
+ OC_setCharacterHome();
+ break;
+ case 0x5B:
+ OC_setViewPortCharacterTarget();
+ break;
+ case 0x5C:
+ OC_showObject();
+ break;
+ case 0x5D:
+ OC_playObjectSound();
+ break;
+ case 0x5E:
+ OC_startLocationSound();
+ break;
+ case 0x5F:
+ OC_stopObjectSound();
+ break;
+ case 0x60:
+ OC_stopLocationSound();
+ break;
+ case 0x61:
+ OC_toggleSound();
+ break;
+ case 0x62:
+ OC_playMusic();
+ break;
+ case 0x63:
+ OC_stopMusic();
+ break;
+ case 0x64:
+ OC_setCharacterMapColor();
+ break;
+ case 0x65:
+ OC_initGameAreaDisplay();
+ break;
+ default:
+ error("Unknown opcode %d", curWord);
+ break;
+ }
+}
+
+static const OpCode opCodes1[] = {
+ { "OC_checkCharacterGoalPos", 1, kgetPosFromScript, kNone, kNone, kNone, kNone },
+ { "OC_comparePos", 2, kGetValue1, kgetPosFromScript, kNone, kNone, kNone },
+ { "OC_checkIsoMap3", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_compareCharacterVariable", 4, kGetValue1, kImmediateValue, kCompareOperation, kImmediateValue, kNone },
+ { "OC_CompareLastRandomValue", 2, kCompareOperation, kImmediateValue, kNone, kNone, kNone },
+ { "OC_getRandom", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_for", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+ { "OC_compCurrentSpeechId", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_checkSaveFlag", 0, kNone, kNone, kNone, kNone, kNone },
+ { "OC_compScriptForVal", 2, kCompareOperation, kImmediateValue, kNone, kNone, kNone },
+ { "OC_isCarrying", 2, kGetValue1, kGetValue1, kNone, kNone, kNone },
+ { "OC_CompareCharacterVariables", 5, kGetValue1, kImmediateValue, kCompareOperation, kGetValue1, kImmediateValue },
+ { "OC_compareCoords_1", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_compareCoords_2", 2, kGetValue1, kImmediateValue, kNone, kNone, kNone },
+ { "OC_CompareDistanceFromCharacterToPositionWith", 3, kgetPosFromScript, kCompareOperation, kImmediateValue, kNone, kNone },
+ { "OC_compareRandomCharacterId", 3, kGetValue1, kCompareOperation, kImmediateValue, kNone, kNone },
+ { "OC_isCurrentCharacterIndex", 1, kGetValue1, kNone, kNone, kNone, kNone },
+ { "OC_hasVisibilityLevel", 2, kImmediateValue, kGetValue1, kNone, kNone, kNone },
+ { "OC_hasGainedVisibilityLevel", 2, kImmediateValue, kGetValue1, kNone, kNone, kNone },
+ { "OC_hasReducedVisibilityLevel", 2, kImmediateValue, kGetValue1, kNone, kNone, kNone },
+ { "OC_isHost", 1, kGetValue1, kNone, kNone, kNone, kNone },
+ { "OC_isSequenceActive", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_isSequenceFinished", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_compareMapValueWith", 4, kgetPosFromScript, kImmediateValue, kImmediateValue, kCompareOperation, kNone },
+ { "OC_isCharacterValid", 1, kGetValue1, kNone, kNone, kNone, kNone },
+ { "OC_checkWaitingSignal", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_currentCharacterVar0AndVar1Equals", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+ { "OC_currentCharacterVar0Equals", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_checkLastInterfaceHotspotIndexMenu13", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_checkLastInterfaceHotspotIndexMenu2", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_compareNumberOfCharacterWithVar0Equals", 3, kImmediateValue, kCompareOperation, kImmediateValue, kNone, kNone },
+ { "OC_isPositionInViewport", 1, kgetPosFromScript, kNone, kNone, kNone, kNone },
+ { "OC_compareGameVariables", 2, kGetValue1, kGetValue1, kNone, kNone, kNone },
+ { "OC_skipNextOpcode", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_CheckCurrentCharacterAttr2", 0, kNone, kNone, kNone, kNone, kNone },
+ { "OC_CheckCurrentCharacterType", 2, kGetValue1, kImmediateValue, kNone, kNone, kNone },
+ { "OC_CheckCurrentCharacterAttr0And", 3, kGetValue1, kImmediateValue, kImmediateValue, kNone, kNone },
+ { "OC_IsCurrentCharacterAttr0LessEqualThan", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_isCarried", 1, kGetValue1, kNone, kNone, kNone, kNone },
+ { "OC_CheckCurrentCharacterAttr1", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_isCurrentCharacterStung", 0, kNone, kNone, kNone, kNone, kNone },
+ { "OC_CurrentCharacterAttr3Equals1", 0, kNone, kNone, kNone, kNone, kNone },
+ { "OC_sub1796E", 2, kGetValue1, kImmediateValue, kNone, kNone, kNone },
+ { "OC_checkLastInterfaceHotspotIndex", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+ { "OC_checkSelectedCharacter", 0, kNone, kNone, kNone, kNone, kNone },
+ { "OC_checkDelayedReactivation", 0, kNone, kNone, kNone, kNone, kNone },
+ { "OC_checkTargetReached", 1, kgetPosFromScript, kNone, kNone, kNone, kNone },
+ { "OC_checkFunctionKeyPressed", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+ { "OC_checkCodeEntered", 3, kImmediateValue, kImmediateValue, kImmediateValue, kNone, kNone },
+ { "OC_checkViewPortCharacterTarget", 1, kGetValue1, kNone, kNone, kNone, kNone },
+};
+
+
+static const OpCode opCodes2[] = {
+/* 0x00 */ { "OC_setWord18821", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x01 */ { "OC_changeIsoMap", 3, kgetPosFromScript, kImmediateValue, kImmediateValue, kNone, kNone },
+/* 0x02 */ { "OC_startSpeech", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x03 */ { "OC_getComputedVariantSpeech", 4, kGetValue1, kImmediateValue, kImmediateValue, kImmediateValue, kNone },
+/* 0x04 */ { "OC_getRotatingVariantSpeech", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone }, // todo
+/* 0x05 */ { "OC_startSpeechIfMute", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x06 */ { "OC_getComputedVariantSpeechIfMute", 4, kGetValue1, kImmediateValue, kImmediateValue, kImmediateValue, kNone }, // pb
+/* 0x07 */ { "OC_startSpeechIfSilent", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+/* 0x08 */ { "OC_computeCharacterVariable", 4, kGetValue1, kImmediateValue, kComputeOperation, kImmediateValue, kNone },
+/* 0x09 */ { "OC_setAttributeToRandom", 3, kGetValue1, kImmediateValue, kImmediateValue, kNone, kNone },
+/* 0x0a */ { "OC_setCharacterPosition", 2, kGetValue1, kgetPosFromScript, kNone, kNone, kNone },
+/* 0x0b */ { "OC_disableCharacter", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x0c */ { "OC_saveAndQuit", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x0d */ { "OC_nSkipOpcodes", 1, kImmediateValue, kNone, kNone, kNone, kNone }, // todo : jump to other opcode
+/* 0x0e */ { "OC_startSpeech5", 0, kNone, kNone, kNone, kNone, kNone }, // todo
+/* 0x0f */ { "OC_resetHandleOpcodeFlag", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x10 */ { "OC_deleteSavegameAndQuit", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x11 */ { "OC_incScriptForVal", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x12 */ { "OC_ComputeChararacterAttr", 5, kGetValue1, kImmediateValue,kComputeOperation, kGetValue1, kImmediateValue },
+/* 0x13 */ { "OC_setTextVarNumber", 2, kGetValue1, kImmediateValue, kNone, kNone, kNone },
+/* 0x14 */ { "OC_callScript", 2, kImmediateValue, kGetValue1, kNone, kNone, kNone }, // run script
+/* 0x15 */ { "OC_callScriptAndReturn", 2, kImmediateValue, kGetValue1, kNone, kNone, kNone }, // run script then stop
+/* 0x16 */ { "OC_setCurrentScriptCharacterPos", 1, kgetPosFromScript, kNone, kNone, kNone, kNone },
+/* 0x17 */ { "OC_initScriptFor", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x18 */ { "OC_setCurrentCharacterSequence", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x19 */ { "OC_setNextCharacterSequence", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x1a */ { "OC_setHost", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x1b */ { "OC_changeMapCube", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x1c */ { "OC_setCharacterCarry", 4, kGetValue1, kGetValue1, kImmediateValue, kImmediateValue, kNone },
+/* 0x1d */ { "OC_dropCarried", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x1e */ { "OC_setCurrentCharacter", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x1f */ { "OC_sendSeeSignal", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+/* 0x20 */ { "OC_sendHearSignal", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+/* 0x21 */ { "OC_sendVarSignal", 3, kImmediateValue, kGetValue1, kImmediateValue, kNone, kNone },
+/* 0x22 */ { "OC_sendBroadcastSignal", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+/* 0x23 */ { "OC_resetWaitingSignal", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x24 */ { "OC_enableCurrentCharacterScript", 1, kImmediateValue, kNone, kNone, kNone, kNone }, // stop script
+/* 0x25 */ { "OC_incCurrentCharacterVar1", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x26 */ { "OC_setCurrentCharacterPos", 2, kImmediateValue, kgetPosFromScript, kNone, kNone, kNone },
+/* 0x27 */ { "OC_setCurrentCharacterBehavior", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x28 */ { "OC_changeCurrentCharacterSprite", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+/* 0x29 */ { "OC_getList", 4, kImmediateValue, kImmediateValue, kImmediateValue, kImmediateValue, kNone },
+/* 0x2a */ { "OC_setList", 4, kImmediateValue, kImmediateValue, kImmediateValue, kImmediateValue, kNone },
+/* 0x2b */ { "OC_setCharacterDirectionTowardsPos", 1, kgetPosFromScript, kNone, kNone, kNone, kNone },
+/* 0x2c */ { "OC_turnCharacterTowardsAnother", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x2d */ { "OC_setSeek", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x2e */ { "OC_scrollAwayFromCharacter", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x2f */ { "OC_skipNextVal", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x30 */ { "OC_setCurrentCharacterAttr6", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x31 */ { "OC_setCurrentCharacterPose", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x32 */ { "OC_setCharacterScriptEnabled", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x33 */ { "OC_setCurrentCharacterAttr2", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x34 */ { "OC_ClearCurrentCharacterAttr2", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x35 */ { "OC_setCharacterProperties", 5, kGetValue1, kImmediateValue, kImmediateValue, kImmediateValue, kImmediateValue },
+/* 0x36 */ { "OC_setMonitoredCharacter", 5, kGetValue1, kImmediateValue, kImmediateValue, kImmediateValue, kImmediateValue },
+/* 0x37 */ { "OC_setNewPose", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+/* 0x38 */ { "OC_setCurrentCharacterDirection", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x39 */ { "OC_setInterfaceHotspot", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+/* 0x3a */ { "OC_scrollViewPort", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x3b */ { "OC_setViewPortPos", 1, kgetPosFromScript, kNone, kNone, kNone, kNone },
+/* 0x3c */ { "OC_setCurrentCharacterAltitude", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x3d */ { "OC_setModePriority", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone },
+/* 0x3e */ { "OC_setComputedModePriority", 4, kImmediateValue, kImmediateValue, kImmediateValue, kImmediateValue, kNone },
+/* 0x3f */ { "OC_selectBestMode", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x40 */ { "OC_magicPuffEntrance", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x41 */ { "OC_spawnCharacterAtPos", 2, kGetValue1, kgetPosFromScript, kNone, kNone, kNone }, // TODO
+/* 0x42 */ { "OC_characterVariableAddOrRemoveFlag", 4, kGetValue1, kImmediateValue, kImmediateValue, kImmediateValue, kNone },
+/* 0x43 */ { "OC_paletteFadeOut", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x44 */ { "OC_paletteFadeIn", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x45 */ { "OC_loadAndDisplayCubesGfx", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x46 */ { "OC_setCurrentCharacterAttr3", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x47 */ { "OC_setArray122C1", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x48 */ { "OC_sub18367", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x49 */ { "OC_enableCharacterScript", 2, kGetValue1, kImmediateValue, kNone, kNone, kNone },
+/* 0x4a */ { "OC_setRulesBuffer2Element", 2, kGetValue1, kImmediateValue, kNone, kNone, kNone },
+/* 0x4b */ { "OC_setDebugFlag", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x4c */ { "OC_setDebugFlag2", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x4d */ { "OC_waitForEvent", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x4e */ { "OC_disableInterfaceHotspot", 2, kImmediateValue, kImmediateValue, kNone, kNone, kNone }, // TODO
+/* 0x4f */ { "OC_loadFileAerial", 1, kNone, kNone, kNone, kNone, kNone },
+/* 0x50 */ { "OC_startSpeechIfSoundOff", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x51 */ { "OC_sub1844A", 2, kGetValue1, kImmediateValue, kNone, kNone, kNone },
+/* 0x52 */ { "OC_displayNumericCharacterVariable", 5, kGetValue1, kImmediateValue, kImmediateValue, kImmediateValue, kImmediateValue },
+/* 0x53 */ { "OC_displayVGAFile", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x54 */ { "OC_startSpeechWithoutSpeeker", 1, kImmediateValue, kNone, kNone, kNone, kNone }, // TODO
+/* 0x55 */ { "OC_displayTitleScreen", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x56 */ { "OC_initGameAreaDisplay", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x57 */ { "OC_displayCharacterStatBar", 6, kGetValue1, kImmediateValue, kImmediateValue, kImmediateValue, kImmediateValue},
+/* 0x58 */ { "OC_initSmallAnim", 11, kImmediateValue, kImmediateValue, kImmediateValue, kImmediateValue, kImmediateValue },
+/* 0x59 */ { "OC_setCharacterHeroismBar", 4, kGetValue1, kImmediateValue, kImmediateValue, kImmediateValue, kNone },
+/* 0x5a */ { "OC_setCharacterHome", 2, kGetValue1, kgetPosFromScript, kNone, kNone, kNone }, //TODO
+/* 0x5b */ { "OC_setViewPortCharacterTarget", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x5c */ { "OC_showObject", 3, kGetValue1, kImmediateValue, kImmediateValue, kNone, kNone }, //TODO
+/* 0x5d */ { "OC_playObjectSound", 2, kGetValue1, kImmediateValue, kNone, kNone, kNone },
+/* 0x5e */ { "OC_startLocationSound", 2, kgetPosFromScript, kImmediateValue, kNone, kNone, kNone },
+/* 0x5f */ { "OC_stopObjectSound", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x60 */ { "OC_stopLocationSound", 1, kGetValue1, kNone, kNone, kNone, kNone },
+/* 0x61 */ { "OC_toggleSound", 1, kgetPosFromScript, kNone, kNone, kNone, kNone },
+/* 0x62 */ { "OC_playMusic", 1, kImmediateValue, kNone, kNone, kNone, kNone },
+/* 0x63 */ { "OC_stopMusic", 0, kNone, kNone, kNone, kNone, kNone },
+/* 0x64 */ { "OC_setCharacterMapColor", 2, kGetValue1, kImmediateValue, kNone, kNone, kNone },
+/* 0x65 */ { "OC_initGameAreaDisplay", 0, kNone, kNone, kNone, kNone, kNone }
+};
+
+Common::String LilliputScript::getArgumentString(kValueType type, ScriptStream& script) {
+
+ Common::String str;
+ if (type == kImmediateValue) {
+ str = Common::String::format("0x%x", script.readUint16LE());
+ } else if (type == kGetValue1) {
+ int val = script.readUint16LE();
+ if (val < 1000) {
+ str = Common::String::format("0x%x", val);
+ } else if (val > 1004) {
+ str = Common::String::format("getValue1(0x%x)", val);
+ } else if (val == 1000) {
+ str = Common::String("_selectedCharacterId");
+ } else if (val == 1001) {
+ str = Common::String("_characterIndex");
+ } else if (val == 1002) {
+ str = Common::String("_word16F00_characterId");
+ } else if (val == 1003) {
+ str = Common::String("_currentCharacterVariables[6]");
+ } else if (val == 1004) {
+ str = Common::String("_host");
+ }
+ } else if (type == kgetPosFromScript) {
+ int curWord = script.readUint16LE();
+ int tmpVal = curWord >> 8;
+ switch(tmpVal) {
+ case 0xFF:
+ str = "(_rulesBuffer2_13[currentCharacter],_rulesBuffer2_14[currentCharacter])";
+ break;
+ case 0xFE: {
+ int index = curWord & 0xFF;
+ assert((index >= 0) && (index < 40));
+ str = Common::String::format("_vm->_rulesBuffer2_13[%d],_vm->_rulesBuffer2_14[%d]", index, index);
+ break;
+ }
+ case 0xFD:
+ str = "_currentScriptCharacterPosition";
+ break;
+ case 0xFC: {
+ int index = curWord & 0xFF;
+ assert(index < 40);
+ str = Common::String::format("(characterPositionTileX[%d], characterPositionTileY[%d])", index, index);
+ break;
+ }
+ case 0xFB: {
+ str = "(characterPositionTileX[_word16F00_characterId], characterPositionTileY[_word16F00_characterId])";
+ break;
+ }
+ case 0xFA:
+ str = Common::String::format("(_characterTargetPosX[currentCharacter], _characterTargetPosY[currentCharacter])");
+ break;
+ case 0xF9:
+ str = Common::String::format("(_currentCharacterVariables[4], _currentCharacterVariables[5])");
+ break;
+ case 0xF8: {
+ int index = curWord & 0xFF;
+ assert((index >= 0) && (index < 40));
+ str = Common::String::format("_vm->_rulesBuffer12Pos3[%d]", index);
+ break;
+ }
+ case 0xF7: {
+ str = Common::String::format("(_characterPositionTileX[_currentCharacterVariables[6]], _characterPositionTileY[_currentCharacterVariables[6]])");
+ break;
+ }
+ case 0xF6:
+ str = "_savedMousePosDivided";
+ break;
+ default:
+ str = Common::String::format("(0x%x,0x%x)", curWord >> 8, curWord & 0xFF);
+ break;
+ }
+ } else if (type == kCompareOperation) {
+ int comp = script.readUint16LE();
+ if (comp != '<' && comp != '>')
+ comp = '=';
+ str = Common::String::format("%c", comp);
+ }
+ else if (type == kComputeOperation) {
+ int comp = script.readUint16LE();
+ str = Common::String::format("%c", comp);
+ }
+ return str;
+}
+
+void LilliputScript::disasmScript(ScriptStream script) {
+ while (!script.eos()) {
+ uint16 val = script.readUint16LE();
+ if (val == 0xFFF6) // end of script
+ return;
+
+ bool firstIf = true;
+
+ // check the conditions.
+ while (val != 0xFFF8) {
+ bool neg = false;
+
+ if (val >= 1000) {
+ val -= 1000;
+ // negative condition
+ neg = true;
+ }
+
+ // op code type 1
+ assert(val < sizeof(opCodes1) / sizeof(OpCode));
+ const OpCode *opCode = &opCodes1[val];
+ const kValueType *opArgType = &opCode->_arg1;
+
+ Common::String str;
+
+ if (firstIf) {
+ str = "if (";
+ firstIf = false;
+ } else {
+ str = " ";
+ }
+ if (neg)
+ str += "not ";
+ str += Common::String(opCode->_opName);
+ str += "(";
+
+ for (int p = 0; p < opCode->_numArgs; p++) {
+ str += getArgumentString(*opArgType, script);
+ if (p != opCode->_numArgs - 1)
+ str += ", ";
+
+ opArgType++;
+ }
+ str += ")";
+
+ val = script.readUint16LE();
+
+ if (val == 0xFFF8) {
+ str += ")";
+ }
+
+ debugC(2, kDebugScript, "%s", str.c_str());
+ }
+
+ debugC(2, kDebugScript, "{ ");
+
+ val = script.readUint16LE();
+
+ while (val != 0xFFF7) {
+ // op code type 2
+ assert(val < sizeof(opCodes2) / sizeof(OpCode));
+ const OpCode *opCode = &opCodes2[val];
+ const kValueType *opArgType = &opCode->_arg1;
+
+ Common::String str;
+ str = " ";
+ str += Common::String(opCode->_opName);
+ str += "(";
+
+ for (int p = 0; p < opCode->_numArgs; p++) {
+ str += getArgumentString(*opArgType, script);
+ if (p != opCode->_numArgs - 1)
+ str += ", ";
+ if (p < 4)
+ opArgType++;
+ }
+ str += ");";
+
+ debugC(2, kDebugScript, "%s", str.c_str());
+
+ val = script.readUint16LE();
+ }
+
+ debugC(2, kDebugScript, "} ");
+ debugC(2, kDebugScript, " ");
+ }
+}
+
+int LilliputScript::handleOpcode(ScriptStream *script) {
+ debugC(2, kDebugScript, "handleOpcode");
+
+ _currScript = script;
+ uint16 curWord = _currScript->readUint16LE();
+ if (curWord == 0xFFF6)
+ return 0xFF;
+
+ for (; curWord != 0xFFF8; curWord = _currScript->readUint16LE()) {
+ byte mask = 0;
+ if (curWord > 1000) {
+ curWord -= 1000;
+ mask = 1;
+ }
+ byte result = handleOpcodeType1(curWord);
+ if ((result ^ mask) == 0) {
+ do {
+ curWord = _currScript->readUint16LE();
+ } while (curWord != 0xFFF7);
+ return 0;
+ }
+ }
+
+ _vm->_handleOpcodeReturnCode = 1;
+
+ for (;;) {
+ curWord = _currScript->readUint16LE();
+ if (curWord == 0xFFF7)
+ return _vm->_handleOpcodeReturnCode;
+
+ handleOpcodeType2(curWord);
+ }
+}
+
+void LilliputScript::runScript(ScriptStream script) {
+ debugC(1, kDebugScript, "runScript");
+
+ _byte16F05_ScriptHandler = 1;
+
+ while (handleOpcode(&script) != 0xFF)
+ _vm->update();
+}
+
+void LilliputScript::runMenuScript(ScriptStream script) {
+ debugC(1, kDebugScript, "runMenuScript");
+
+ _byte16F05_ScriptHandler = 0;
+
+ while (handleOpcode(&script) == 0)
+ _vm->update();
+}
+
+byte LilliputScript::compareValues(int16 var1, uint16 oper, int16 var2) {
+ debugC(2, kDebugScript, "compareValues(%d, %c, %d)", var1, oper & 0xFF, var2);
+
+ switch (oper & 0xFF) {
+ case '<':
+ if (var1 < var2)
+ return 1;
+ break;
+ case '>':
+ if (var1 > var2)
+ return 1;
+ break;
+ default:
+ if (var1 == var2)
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+void LilliputScript::computeOperation(byte *bufPtr, uint16 oper, int16 var3) {
+ debugC(1, kDebugScript, "computeOperation(bufPtr, %c, %d)", oper & 0xFF, var3 & 0xFF);
+
+ switch (oper & 0xFF) {
+ case '=':
+ bufPtr[0] = var3 & 0xFF;
+ break;
+ case '+': {
+ int tmpVal = bufPtr[0] + var3;
+ if (tmpVal > 0xFF)
+ bufPtr[0] = 0xFF;
+ else
+ bufPtr[0] = (byte)tmpVal;
+ }
+ break;
+ case '-': {
+ int tmpVal = bufPtr[0] - var3;
+ if (tmpVal < 0)
+ bufPtr[0] = 0;
+ else
+ bufPtr[0] = (byte)tmpVal;
+ }
+ break;
+ case '*': {
+ int tmpVal = bufPtr[0] * var3;
+ bufPtr[0] = tmpVal & 0xFF;
+ }
+ break;
+ case '/': {
+ if (var3 != 0)
+ bufPtr[0] /= var3;
+ }
+ break;
+ default: {
+ warning("computeOperation : oper %d", oper);
+ if (var3 != 0) {
+ int tmpVal = bufPtr[0] / var3;
+ if (tmpVal < 0)
+ bufPtr[0] = 0xFF;
+ else
+ bufPtr[0] = 0;
+ }
+ break;
+ }
+ }
+}
+
+void LilliputScript::enableCharacterScript(byte index, byte var1, byte *curBufPtr) {
+ debugC(1, kDebugScript, "enableCharacterScript(%d, %d, curBufPtr)", index, var1);
+
+ assert (index < 40);
+ _characterScriptEnabled[index] = 1;
+ curBufPtr[0] = var1;
+ curBufPtr[1] = 0;
+ curBufPtr[2] = 0;
+ curBufPtr[3] = 0;
+}
+
+void LilliputScript::skipOpcodes(int var1) {
+ debugC(1, kDebugScript, "skipOpcodes(%d)", var1);
+
+ if (var1 == 0) {
+ int curWord = 0;
+ while (curWord != 0xFFF6)
+ curWord = _currScript->readUint16LE();
+
+ _currScript->seek(_currScript->pos() - 4);
+ return;
+ }
+
+ ++var1;
+ int curVal = 0;
+ while (curVal < var1) {
+ int tmpVal = _currScript->readUint16LE();
+ if (tmpVal == 0xFFF7)
+ ++curVal;
+ }
+
+ _currScript->seek(_currScript->pos() - 2);
+}
+
+void LilliputScript::copySequence(int index, byte *buf) {
+ debugC(1, kDebugScript, "copySequence()");
+
+ _characterNextSequence[index] = 0;
+
+ for (int i = 0; i < 16; i++) {
+ _sequenceArr[(index * 16) + i] = Common::Point(buf[(2 * i) + 1], buf[2 * i]);
+ }
+}
+
+void LilliputScript::setSequence(int charIdx, int8 seqIdx) {
+ debugC(1, kDebugScript, "setSequence(%d, %d)", charIdx, seqIdx);
+
+ assert(charIdx < 40);
+ _characterLastSequence[charIdx] = seqIdx;
+
+ byte *buf = _vm->_sequencesArr;
+ if (seqIdx != 0) {
+ int count = 0;
+ while (count < seqIdx) {
+ if ((buf[0] == 0xFF) && (buf[1] == 0xFF))
+ ++count;
+ buf += 2;
+ }
+ }
+
+ copySequence(charIdx, buf);
+}
+
+void LilliputScript::checkSpeechAllowed(bool &forceReturnFl) {
+ debugC(1, kDebugScript, "checkSpeechAllowed()");
+
+ forceReturnFl = false;
+ if ((!_vm->_displayMap) && (_vm->_characterRelativePos[_vm->_currentScriptCharacter].x != -1))
+ return;
+
+ forceReturnFl = true;
+ return;
+}
+
+void LilliputScript::formatSpeechString() {
+ debugC(2, kDebugScript, "formatSpeechString()");
+
+ int index = 0;
+ int var2 = 0x100;
+
+ for (;;) {
+ int var1 = _vm->_displayStringBuf[index++];
+ if (var1 == 0)
+ break;
+
+ if (var1 == '|') {
+ var2 &= 0xFF;
+ ++var2;
+ continue;
+ }
+
+ var2 += 0x100;
+ if ((var2 >> 8) < 61)
+ continue;
+
+ if ((var2 & 0xFF) == 1) {
+ _vm->_displayStringBuf[index - 1] = 0;
+ break;
+ }
+
+ --index;
+ while (_vm->_displayStringBuf[index] != ' ')
+ --index;
+
+ _vm->_displayStringBuf[index] = '|';
+ ++var2;
+ var2 &= 0xFF;
+ ++index;
+ }
+}
+
+void LilliputScript::showSpeech() {
+ debugC(2, kDebugScript, "showSpeech()");
+
+ formatSpeechString();
+ int index = 0;
+
+ for (;;) {
+ if (_vm->_displayStringBuf[index] == 0)
+ break;
+ ++index;
+ }
+
+ index /= _speechDisplaySpeed;
+ index += 4;
+ _speechTimer = index;
+ _vm->displaySpeechBubble();
+ _vm->displaySpeech(_vm->_displayStringBuf);
+}
+
+void LilliputScript::decodePackedText(char *buf) {
+ debugC(2, kDebugScript, "decodePackedText(buf)");
+
+ // All the languages use the English dictionary
+ static const char *nounsArrayPtr = "I am |You are |you are |hou art |in the |"
+ "is the |is a |in a |To the |to the |by |going |here |The|the|and |"
+ "some |build|not |way|I |a |an |from |of |him|her|by |his |ing |tion|"
+ "have |you|I've |can't |up |to |he |she |down |what|What|with|are |"
+ "and|ent|ian|ome|ed |me|my|ai|it|is|of|oo|ea|er|es|th|we|ou|ow|or|"
+ "gh|go|er|st|ee|th|sh|ch|ct|on|ly|ng|nd|nt|ty|ll|le|de|as|ie|in|ss|"
+ "'s |'t |re|gg|tt|pp|nn|ay|ar|wh|";
+
+ _vm->_displayStringIndex = 0;
+ int index = 0;
+ byte var1 = 0;
+ for (;;) {
+ var1 = buf[index];
+ ++index;
+ if (var1 == ']')
+ var1 = 0;
+
+ if (var1 < 0x80) {
+ if (var1 == '@') {
+ var1 = buf[index];
+ ++index;
+ if (var1 == '#') {
+ _vm->numberToString(_textVarNumber);
+ }
+ } else {
+ _vm->addCharToBuf(var1);
+ if (var1 == 0)
+ break;
+ }
+ } else {
+ int nounIndex = 0;
+ byte var3 = 0xFF - var1;
+ for (int i = 0; i < var3; i++) {
+ for (;;) {
+ var1 = nounsArrayPtr[nounIndex];
+ ++nounIndex;
+
+ if (var1 == '|')
+ break;
+ }
+ }
+
+ for (;;) {
+ var1 = nounsArrayPtr[nounIndex];
+ ++nounIndex;
+
+ if (var1 == '|')
+ break;
+
+ _vm->addCharToBuf(var1);
+ }
+ }
+ }
+
+ showSpeech();
+}
+
+int LilliputScript::getPackedStringStartRelativeIndex(int index) {
+ debugC(2, kDebugScript, "getPackedStringStartRelativeIndex(%d)", index);
+
+ int chunk4Index = _vm->_packedStringIndex[index];
+ int result = 0;
+ while (_vm->_packedStrings[chunk4Index + result] == 0x5B)
+ ++result;
+
+ return result + 1;
+}
+
+// Part of the script decompiler
+void LilliputScript::listAllTexts() {
+ debugC(1, kDebugScript, "listAllTexts");
+
+ for (int i = 0; i < _vm->_packedStringNumb; i++) {
+ int index = _vm->_packedStringIndex[i];
+ int variantCount = 0;
+ while (_vm->_packedStrings[index + variantCount] == 0x5B)
+ ++variantCount;
+ /*
+ int it = 0;
+ if (variantCount != 0) {
+ for (int j = 0; j < variantCount; j++) {
+ decodePackedText(&_vm->_packedStrings[index + variantCount + it]);
+ warning("Text 0x%x variant %d : %s", i, j, _vm->_displayStringBuf);
+ do {
+ ++it;
+ } while (_vm->_packedStrings[index + variantCount + it] != 0x5B);
+ }
+ } else {*/
+ decodePackedText(&_vm->_packedStrings[index + variantCount]);
+ debugC(1, kDebugScript, "Text 0x%x variant 0 : %s", i, _vm->_displayStringBuf);
+ /* }*/
+ }
+}
+
+void LilliputScript::startSpeech(int speechId) {
+ debugC(2, kDebugScript, "startSpeech(%d)", speechId);
+
+ if (speechId == -1)
+ return;
+
+ _currentSpeechId = speechId;
+
+ int index = _vm->_packedStringIndex[speechId];
+ int count = 0;
+ while (_vm->_packedStrings[index + count] == '[')
+ ++count;
+
+ int i = 0;
+ if (count != 0) {
+ int tmpVal = _vm->_rnd->getRandomNumber(count);
+ if (tmpVal != 0) {
+ for (int j = 0; j < tmpVal; j++) {
+ do {
+ ++i;
+ } while (_vm->_packedStrings[index + count + i] != ']');
+ ++i;
+ }
+ }
+ }
+
+ decodePackedText(&_vm->_packedStrings[index + count + i]);
+}
+
+int16 LilliputScript::getValue1() {
+ debugC(2, kDebugScript, "getValue1()");
+
+ int16 curWord = _currScript->readUint16LE();
+ if (curWord < 1000)
+ return curWord;
+
+ switch (curWord) {
+ case 1000:
+ return _vm->_selectedCharacterId;
+ case 1001:
+ return _vm->_currentScriptCharacter;
+ case 1002:
+ return _word16F00_characterId;
+ case 1003:
+ return (int16)_vm->_currentCharacterAttributes[6];
+ case 1004:
+ return _vm->_host;
+ default:
+ warning("getValue1: Unexpected large value %d", curWord);
+ return curWord;
+ }
+}
+
+Common::Point LilliputScript::getPosFromScript() {
+ debugC(2, kDebugScript, "getPosFromScript()");
+
+ int curWord = _currScript->readUint16LE();
+ int tmpVal = curWord >> 8;
+ switch(tmpVal) {
+ case 0xFF:
+ assert((_vm->_currentScriptCharacter >= 0) && (_vm->_currentScriptCharacter < 40));
+ return _vm->_characterHomePos[_vm->_currentScriptCharacter];
+ case 0xFE: {
+ int8 index = curWord & 0xFF;
+ assert((index >= 0) && (index < 40));
+ return _vm->_characterHomePos[index];
+ }
+ case 0xFD:
+ return _vm->_currentScriptCharacterPos;
+ case 0xFC: {
+ int8 index = curWord & 0xFF;
+ assert((index >= 0) && (index < 40));
+ int16 x = _vm->_characterPos[index].x >> 3;
+ int16 y = _vm->_characterPos[index].y >> 3;
+
+ return Common::Point(x, y);
+ }
+ case 0xFB: {
+ int index = _word16F00_characterId;
+ assert((index >= 0) && (index < 40));
+ int16 x = _vm->_characterPos[index].x >> 3;
+ int16 y = _vm->_characterPos[index].y >> 3;
+
+ return Common::Point(x, y);
+ }
+ case 0xFA:
+ return _vm->_characterTargetPos[_vm->_currentScriptCharacter];
+ case 0xF9:
+ return Common::Point(_vm->_currentCharacterAttributes[4], _vm->_currentCharacterAttributes[5]);
+ case 0xF8: {
+ int8 index = curWord & 0xFF;
+ assert((index >= 0) && (index < 40));
+ return _vm->_keyPos[index];
+ }
+ case 0xF7: {
+ int8 index = _vm->_currentCharacterAttributes[6];
+ assert((index >= 0) && (index < 40));
+ return Common::Point(_vm->_characterPos[index].x >> 3, _vm->_characterPos[index].y >> 3);
+ }
+ case 0xF6:
+ return _vm->_savedMousePosDivided;
+ default:
+ Common::Point pos = Common::Point(curWord >> 8, curWord & 0xFF);
+ // warning("getPosFromScript - High value %d -> %d %d", curWord, pos.x, pos.y);
+ return pos;
+ }
+}
+
+byte *LilliputScript::getCharacterAttributesPtr() {
+ debugC(2, kDebugScript, "getCharacterVariablePtr()");
+
+ int8 tmpVal = (int8) (getValue1() & 0xFF);
+ int index = tmpVal * 32;
+ index += _currScript->readUint16LE();
+
+ return _vm->getCharacterAttributesPtr(index);
+}
+
+byte LilliputScript::OC_checkCharacterGoalPos() {
+ debugC(2, kDebugScript, "OC_checkCharacterGoalPos()");
+
+ if (_vm->_currentScriptCharacterPos == getPosFromScript()) {
+ return 1;
+ }
+ return 0;
+}
+
+byte LilliputScript::OC_comparePos() {
+ debugC(2, kDebugScript, "OC_comparePos()");
+
+ int index = getValue1();
+ Common::Point var1 = getPosFromScript();
+
+ if (var1 == _characterTilePos[index])
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_checkIsoMap3() {
+ debugC(1, kDebugScript, "OC_checkIsoMap3()");
+
+ Common::Point var = _vm->_currentScriptCharacterPos;
+ if (var == Common::Point(-1, -1)) {
+ _currScript->readUint16LE();
+ return 0;
+ }
+
+ byte *isoMapBuf = getMapPtr(var);
+ byte var2 = isoMapBuf[3];
+
+ int16 var3 = _currScript->readUint16LE();
+ byte var4 = 8 >> var3;
+
+ if ((var2 & var4) != 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+byte LilliputScript::OC_compareCharacterVariable() {
+ debugC(1, kDebugScript, "OC_compareCharacterVariable()");
+
+ byte *tmpArr = getCharacterAttributesPtr();
+ byte var1 = tmpArr[0];
+ uint16 oper = _currScript->readUint16LE();
+ int16 var2 = _currScript->readUint16LE();
+
+ return compareValues(var1, oper, var2);
+}
+
+byte LilliputScript::OC_CompareLastRandomValue() {
+ debugC(1, kDebugScript, "OC_CompareLastRandomValue()");
+
+ uint16 operation = _currScript->readUint16LE();
+ int16 val2 = _currScript->readSint16LE();
+ return compareValues(_lastRandomValue, operation, val2);
+}
+
+byte LilliputScript::OC_getRandom() {
+ debugC(1, kDebugScript, "OC_getRandom()");
+
+ int maxVal = _currScript->readUint16LE();
+ int rand = _vm->_rnd->getRandomNumber(maxVal);
+ _lastRandomValue = (rand & 0xFF);
+
+ if (rand == 0)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_for() {
+ debugC(1, kDebugScript, "OC_for()");
+
+ int var1 = _currScript->readUint16LE();
+ int tmpVal = _currScript->readUint16LE() + 1;
+ // no need to seek later, the move is already done
+ _currScript->writeUint16LE(tmpVal, -2);
+ // overwrite the recently used "variable" in the script
+ if (tmpVal < var1)
+ return 0;
+
+ _currScript->writeUint16LE(0, -2);
+ return 1;
+}
+
+byte LilliputScript::OC_compCurrentSpeechId() {
+ debugC(1, kDebugScript, "OC_compCurrentSpeechId()");
+
+ int var1 = _currScript->readUint16LE();
+
+ if (var1 == _currentSpeechId)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_checkSaveFlag() {
+ debugC(1, kDebugScript, "OC_checkSaveFlag()");
+
+ if (_vm->_saveFlag)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_compScriptForVal() {
+ debugC(1, kDebugScript, "OC_compScriptForVal()");
+
+ uint16 oper = _currScript->readUint16LE();
+ int16 var2 = _currScript->readUint16LE();
+
+ return compareValues(_scriptForVal, oper, var2);
+}
+
+byte LilliputScript::OC_isCarrying() {
+ debugC(1, kDebugScript, "OC_isCarrying()");
+
+ int8 tmpVal = getValue1() & 0xFF;
+ uint16 curWord = _currScript->readUint16LE();
+
+ if (curWord == 3000) {
+ for (int index = 0; index < _vm->_numCharacters; index++) {
+ if (_vm->_characterCarried[index] == tmpVal) {
+ _word16F00_characterId = index;
+ return 1;
+ }
+ }
+ } else {
+ _currScript->seek(_currScript->pos() - 2);
+ int index = getValue1();
+ assert(index < 40);
+ if (_vm->_characterCarried[index] == tmpVal) {
+ _word16F00_characterId = index;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+byte LilliputScript::OC_CompareCharacterVariables() {
+ debugC(1, kDebugScript, "OC_CompareCharacterVariables()");
+
+ byte* buf1 = getCharacterAttributesPtr();
+ int var1 = *buf1;
+
+ int operation = _currScript->readUint16LE();
+
+ byte* buf2 = getCharacterAttributesPtr();
+ int var2 = *buf2;
+
+ return compareValues(var1, operation, var2);
+}
+
+// TODO Rename function to "Check if current script character pos is in enclosure"
+byte LilliputScript::OC_compareCoords_1() {
+ debugC(1, kDebugScript, "OC_compareCoords_1()");
+
+ int index = _currScript->readUint16LE();
+ assert(index < 40);
+
+ if (_vm->_enclosureRect[index].contains(_vm->_currentScriptCharacterPos))
+ return 1;
+
+ return 0;
+}
+
+// TODO Rename function to "Check if given character pos is in enclosure"
+byte LilliputScript::OC_compareCoords_2() {
+ debugC(1, kDebugScript, "OC_compareCoords_2()");
+
+ int16 idx1 = getValue1();
+ int16 idx2 = _currScript->readUint16LE();
+
+ if (_vm->_enclosureRect[idx2].contains(_characterTilePos[idx1]))
+ return 1;
+ return 0;
+}
+
+byte LilliputScript::OC_CompareDistanceFromCharacterToPositionWith() {
+ debugC(1, kDebugScript, "OC_CompareDistanceFromCharacterToPositionWith()");
+
+ Common::Point var1 = getPosFromScript();
+ Common::Point pos = _vm->_currentScriptCharacterPos;
+
+ int dx = var1.x - pos.x;
+ if (dx < 0)
+ dx = -dx;
+
+ int dy = var1.y - pos.y;
+ if (dy < 0)
+ dy = -dy;
+
+ int16 dist = dx + dy;
+
+ uint16 operation = _currScript->readUint16LE();
+ int16 var2 = _currScript->readSint16LE();
+
+ return compareValues(dist, operation, var2);
+}
+
+byte LilliputScript::OC_compareRandomCharacterId() {
+ debugC(1, kDebugScript, "OC_compareRandomCharacterId()");
+
+ byte *tmpArr = getCharacterAttributesPtr();
+ _lastRandomValue = _vm->_rnd->getRandomNumber(tmpArr[0] + 1);
+ uint16 oper = _currScript->readUint16LE();
+ int16 var2 = _currScript->readSint16LE();
+
+ return compareValues(_lastRandomValue, oper, var2);
+}
+
+byte LilliputScript::OC_IsCurrentCharacterIndex() {
+ debugC(1, kDebugScript, "OC_IsCurrentCharacterIndex()");
+
+ int tmpVal = getValue1();
+ if (tmpVal == _vm->_currentScriptCharacter)
+ return 1;
+ return 0;
+}
+
+byte LilliputScript::OC_hasVisibilityLevel() {
+ debugC(1, kDebugScript, "OC_hasVisibilityLevel()");
+
+ byte var4 = _currScript->readUint16LE() & 0xFF;
+ int tmpVal = _currScript->readUint16LE();
+
+ if (tmpVal < 2000) {
+ _currScript->seek(_currScript->pos() - 2);
+ int index = getValue1();
+ int var1 = _interactions[(_vm->_currentScriptCharacter * 40) + index];
+ if ((var1 & 0xFF) < var4)
+ return 0;
+
+ _word16F00_characterId = index;
+ return 1;
+ }
+
+ if (tmpVal == 3000) {
+ for (int i = 0; i < _vm->_numCharacters; i++) {
+ int var1 = _interactions[(_vm->_currentScriptCharacter * 40) + i];
+ if ((var1 & 0xFF) >= var4) {
+ _word16F00_characterId = i;
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ tmpVal -= 2000;
+ byte var4b = tmpVal & 0xFF;
+ for (int i = 0; i < _vm->_numCharacters; i++) {
+ int var1 = _interactions[(_vm->_currentScriptCharacter * 40) + i];
+ if (((var1 & 0xFF) >= var4) && (_vm->_characterBehaviour[i] == var4b)) {
+ _word16F00_characterId = i;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+byte LilliputScript::OC_hasGainedVisibilityLevel() {
+ debugC(1, kDebugScript, "OC_hasGainedVisibilityLevel()");
+
+ uint16 var4 = _currScript->readUint16LE();
+ int index = _vm->_currentScriptCharacter * 40;
+ uint16 tmpVal = _currScript->readUint16LE();
+
+ if (tmpVal < 2000) {
+ _currScript->seek(_currScript->pos() - 2);
+ int subIndex = getValue1();
+ tmpVal = _interactions[index + subIndex];
+ byte v1 = tmpVal & 0xFF;
+ byte v2 = tmpVal >> 8;
+ if ((v1 < (var4 & 0xFF)) || (v2 >= (var4 & 0xFF)))
+ return 0;
+ _word16F00_characterId = subIndex;
+ return 1;
+ }
+
+ int var1 = tmpVal;
+ if (var1 == 3000) {
+ for (int i = 0; i < _vm->_numCharacters; i++) {
+ tmpVal = _interactions[index + i];
+ byte v1 = tmpVal & 0xFF;
+ byte v2 = tmpVal >> 8;
+ if ((v1 >= (var4 & 0xFF)) && (v2 < (var4 & 0xFF))) {
+ _word16F00_characterId = i;
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ var1 -= 2000;
+ var4 = ((var1 & 0xFF) << 8) + (var4 & 0xFF);
+ for (int i = 0; i < _vm->_numCharacters; i++) {
+ tmpVal = _interactions[index + i];
+ byte v1 = tmpVal & 0xFF;
+ byte v2 = tmpVal >> 8;
+ if ((v1 >= (var4 & 0xFF)) && (v2 < (var4 & 0xFF)) && (_vm->_characterBehaviour[i] == (var4 >> 8))) {
+ _word16F00_characterId = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+byte LilliputScript::OC_hasReducedVisibilityLevel() {
+ debugC(1, kDebugScript, "OC_hasReducedVisibilityLevel()");
+
+ byte var4 = _currScript->readUint16LE() & 0xFF;
+
+ int tmpVal = _currScript->readUint16LE();
+
+ if (tmpVal < 2000) {
+ _currScript->seek(_currScript->pos() - 2);
+ int index = getValue1();
+ int var1 = _interactions[(_vm->_currentScriptCharacter * 40) + index];
+ if (((var1 & 0xFF) >= var4) || ((var1 >> 8) < var4))
+ return 0;
+
+ _word16F00_characterId = index;
+ return 1;
+ }
+
+ if (tmpVal == 3000) {
+ for (int i = 0; i < _vm->_numCharacters; i++) {
+ int var1 = _interactions[(_vm->_currentScriptCharacter * 40) + i];
+ if (((var1 & 0xFF) < var4) && ((var1 >> 8) >= var4)) {
+ _word16F00_characterId = i;
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ tmpVal -= 2000;
+ byte var4b = tmpVal & 0xFF;
+ for (int i = 0; i < _vm->_numCharacters; i++) {
+ int var1 = _interactions[(_vm->_currentScriptCharacter * 40) + i];
+ if (((var1 & 0xFF) < var4) && ((var1 >> 8) >= var4)) {
+ if (_vm->_characterBehaviour[i] == var4b) {
+ _word16F00_characterId = i;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+byte LilliputScript::OC_isHost() {
+ debugC(1, kDebugScript, "OC_isHost()");
+
+ int tmpVal = getValue1();
+ if (tmpVal == _vm->_host)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_isSequenceActive() {
+ debugC(1, kDebugScript, "OC_isSequenceActive()");
+
+ int8 var1 = (_currScript->readUint16LE() & 0xFF);
+ if ((var1 == _characterLastSequence[_vm->_currentScriptCharacter]) && (_characterNextSequence[_vm->_currentScriptCharacter] != 16))
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_isSequenceFinished() {
+ debugC(1, kDebugScript, "OC_isSequenceFinished()");
+
+ int8 var1 = (_currScript->readUint16LE() & 0xFF);
+ if ((var1 == _characterLastSequence[_vm->_currentScriptCharacter]) && (_characterNextSequence[_vm->_currentScriptCharacter] == 16))
+ return 1;
+
+ return 0;
+}
+
+byte *LilliputScript::getMapPtr(Common::Point val) {
+ debugC(1, kDebugScript, "getMapPtr(%d %d)", val.x, val.y);
+
+ return &_vm->_bufferIsoMap[(val.y * 64 + val.x) << 2];
+}
+
+byte LilliputScript::OC_CompareMapValueWith() {
+ debugC(1, kDebugScript, "OC_CompareMapValueWith()");
+
+ Common::Point tmpVal = getPosFromScript();
+
+ if (tmpVal == Common::Point(-1, -1)) {
+ _currScript->seek(_currScript->pos() + 6);
+ return 0;
+ }
+ int16 var2 = _currScript->readUint16LE();
+ byte *buf = getMapPtr(tmpVal);
+ int16 var1 = buf[var2];
+ uint16 oper = _currScript->readUint16LE();
+ var2 = _currScript->readSint16LE();
+
+ return compareValues(var1, oper, var2);
+}
+
+byte LilliputScript::OC_IsCharacterValid() {
+ debugC(1, kDebugScript, "OC_IsCharacterValid()");
+
+ int index = getValue1();
+ if (_vm->_characterPos[index].x == -1)
+ return 0;
+
+ return 1;
+}
+
+byte LilliputScript::OC_CheckWaitingSignal() {
+ debugC(1, kDebugScript, "OC_CheckWaitingSignal()");
+
+ byte curByte = _currScript->readUint16LE() & 0xFF;
+ byte tmpVal = _vm->_waitingSignal;
+
+ if (curByte != tmpVal)
+ return 0;
+
+ _word16F00_characterId = _vm->_waitingSignalCharacterId;
+ return 1;
+}
+
+byte LilliputScript::OC_CurrentCharacterVar0AndVar1Equals() {
+ debugC(1, kDebugScript, "OC_CurrentCharacterVar0AndVar1Equals()");
+
+ byte var1 = _currScript->readUint16LE() & 0xFF;
+ byte var2 = _currScript->readUint16LE() & 0xFF;
+
+ assert(_vm->_currentCharacterAttributes != NULL);
+
+ if ((var1 == _vm->_currentCharacterAttributes[0]) && (var2 == _vm->_currentCharacterAttributes[1]))
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_CurrentCharacterVar0Equals() {
+ debugC(1, kDebugScript, "OC_CurrentCharacterVar0Equals()");
+
+ byte curByte = (_currScript->readUint16LE() & 0xFF);
+ assert(_vm->_currentCharacterAttributes != NULL);
+ if (_vm->_currentCharacterAttributes[0] == curByte)
+ return 1;
+ return 0;
+}
+
+byte LilliputScript::OC_checkLastInterfaceHotspotIndexMenu13() {
+ debugC(1, kDebugScript, "OC_checkLastInterfaceHotspotIndexMenu13()");
+
+ byte tmpVal = (_currScript->readUint16LE() & 0xFF);
+
+ if ((_vm->_actionType != kButtonPressed) && (_vm->_actionType != kActionTalk))
+ return 0;
+
+ if (tmpVal == _vm->_lastInterfaceHotspotIndex)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_checkLastInterfaceHotspotIndexMenu2() {
+ debugC(1, kDebugScript, "OC_checkLastInterfaceHotspotIndexMenu2()");
+
+ int8 hotspotIndex = (_currScript->readUint16LE() & 0xFF);
+
+ if ((_vm->_actionType == kButtonReleased) && (hotspotIndex == _vm->_lastInterfaceHotspotIndex))
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_CompareNumberOfCharacterWithVar0Equals() {
+ debugC(1, kDebugScript, "OC_CompareNumberOfCharacterWithVar0Equals()");
+
+ byte curByte = (_currScript->readUint16LE() & 0xFF);
+ int16 count = 0;
+
+ for (int i = 0; i < _vm->_numCharacters; i++) {
+ if (curByte == *_vm->getCharacterAttributesPtr(32 * i))
+ ++count;
+ }
+
+ uint16 oper = _currScript->readUint16LE();
+ int16 var2 = _currScript->readSint16LE();
+
+ return compareValues(count, oper, var2);
+}
+
+byte LilliputScript::OC_IsPositionInViewport() {
+ debugC(1, kDebugScript, "OC_IsPositionInViewport()");
+
+ Common::Point var1 = getPosFromScript();
+
+ int16 dx = var1.x - _viewportPos.x;
+ int16 dy = var1.y - _viewportPos.y;
+
+ if ((dx >= 0) && (dx < 8) && (dy >= 0) && (dy < 8))
+ return 1;
+ return 0;
+}
+
+byte LilliputScript::OC_CompareGameVariables() {
+ debugC(1, kDebugScript, "OC_CompareGameVariables()");
+
+ int16 var1 = getValue1();
+ int16 var2 = getValue1();
+ if (var1 == var2)
+ return 1;
+ return 0;
+}
+
+byte LilliputScript::OC_skipNextOpcode() {
+ debugC(1, kDebugScript, "OC_skipNextOpcode()");
+
+ _currScript->readUint16LE();
+ return 1;
+}
+
+byte LilliputScript::OC_CheckCurrentCharacterAttr2() {
+ debugC(1, kDebugScript, "OC_CheckCurrentCharacterAttr2()");
+
+ assert(_vm->_currentCharacterAttributes != NULL);
+ if (_vm->_currentCharacterAttributes[2] == 1)
+ return 1;
+ return 0;
+}
+
+byte LilliputScript::OC_CheckCurrentCharacterType() {
+ debugC(1, kDebugScript, "OC_CheckCurrentCharacterType()");
+
+ int index = getValue1();
+ assert (index < 40);
+
+ byte curByte = (_currScript->readUint16LE() & 0xFF);
+ if (curByte == _vm->_characterBehaviour[index])
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_CheckCurrentCharacterAttr0And() {
+ debugC(1, kDebugScript, "OC_CheckCurrentCharacterAttr0And()");
+
+ byte *bufPtr = getCharacterAttributesPtr();
+ byte var1 = bufPtr[0];
+ byte curByte = (_currScript->readUint16LE() & 0xFF);
+
+ if (var1 & curByte)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_IsCurrentCharacterAttr0LessEqualThan() {
+ debugC(1, kDebugScript, "OC_IsCurrentCharacterAttr0LessEqualThan()");
+
+ assert(_vm->_currentCharacterAttributes != NULL);
+ byte curByte = (_currScript->readUint16LE() & 0xFF);
+
+ if (curByte <= _vm->_currentCharacterAttributes[0])
+ return 1;
+ return 0;
+}
+
+byte LilliputScript::OC_isCarried() {
+ debugC(1, kDebugScript, "OC_isCarried()");
+
+ int16 index = getValue1();
+ assert((index >= 0) && (index < 40));
+ if (_vm->_characterCarried[index] == -1)
+ return 0;
+
+ _word16F00_characterId = _vm->_characterCarried[index];
+
+ return 1;
+}
+
+byte LilliputScript::OC_CheckCurrentCharacterAttr1() {
+ debugC(1, kDebugScript, "OC_CheckCurrentCharacterAttr1()");
+
+ assert(_vm->_currentCharacterAttributes != NULL);
+ byte curByte = (_currScript->readUint16LE() & 0xFF);
+
+ if (_vm->_currentCharacterAttributes[1] == curByte)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_isCurrentCharacterSpecial() {
+ debugC(1, kDebugScript, "OC_isCurrentCharacterSpecial()");
+
+ if (_vm->_currentScriptCharacterPos == Common::Point(-1, -1))
+ return 0;
+
+ if (_vm->_specialCubes[_vm->_currentScriptCharacter] == 0)
+ return 0;
+
+ return 1;
+}
+
+byte LilliputScript::OC_CurrentCharacterAttr3Equals1() {
+ debugC(1, kDebugScript, "OC_CurrentCharacterAttr3Equals1()");
+
+ assert(_vm->_currentCharacterAttributes != NULL);
+ if (_vm->_currentCharacterAttributes[3] == 1)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_checkCharacterDirection() {
+ debugC(1, kDebugScript, "OC_checkCharacterDirection()");
+
+ int16 index = getValue1();
+ byte expectedVal = (_currScript->readUint16LE() & 0xFF);
+
+ if (_vm->_characterDirectionArray[index] == expectedVal)
+ return 1;
+ return 0;
+}
+
+byte LilliputScript::OC_checkLastInterfaceHotspotIndex() {
+ debugC(1, kDebugScript, "OC_checkLastInterfaceHotspotIndex()");
+
+ uint16 index = _currScript->readUint16LE();
+ int8 var2 = (_currScript->readUint16LE() & 0xFF);
+
+ assert(index < 20);
+
+ if (_interfaceHotspotStatus[index] == var2)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_checkSelectedCharacter() {
+ debugC(1, kDebugScript, "OC_checkSelectedCharacter()");
+
+ if ((_vm->_selectedCharacterId != -1) || (_vm->_savedMousePosDivided == Common::Point(-1, -1)))
+ return 0;
+
+ return 1;
+}
+
+byte LilliputScript::OC_checkDelayedReactivation() {
+ debugC(1, kDebugScript, "OC_checkDelayedReactivation()");
+
+ if (_vm->_delayedReactivationAction || (_vm->_selectedCharacterId == -1))
+ return 0;
+
+ return 1;
+}
+
+byte LilliputScript::OC_checkTargetReached() {
+ debugC(1, kDebugScript, "OC_checkTargetReached()");
+ Common::Point pos = getPosFromScript();
+
+ if (_vm->_characterTargetPos[_vm->_currentScriptCharacter] == pos)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_checkFunctionKeyPressed() {
+ debugC(1, kDebugScript, "OC_checkFunctionKeyPressed()");
+
+ static const Common::KeyCode specialKeys[10] = {
+ Common::KEYCODE_F10, Common::KEYCODE_F1, Common::KEYCODE_F2, Common::KEYCODE_F3, Common::KEYCODE_F4,
+ Common::KEYCODE_F5, Common::KEYCODE_F6, Common::KEYCODE_F7, Common::KEYCODE_F8, Common::KEYCODE_F9};
+
+ int8 index = (_currScript->readUint16LE() & 0xFF) - 0x30;
+
+ if (specialKeys[index] == _vm->_lastKeyPressed.kbd.keycode)
+ return 1;
+
+ return 0;
+}
+
+byte LilliputScript::OC_checkCodeEntered() {
+ debugC(1, kDebugScript, "OC_checkCodeEntered()");
+
+ static const byte solutionArr[10] = {11, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+
+ if (_vm->_actionType == kCodeEntered) {
+ uint16 index = _currScript->readUint16LE();
+ if (solutionArr[index] == _vm->_codeEntered[0]) {
+ index = _currScript->readUint16LE();
+ if (solutionArr[index] == _vm->_codeEntered[1]) {
+ index = _currScript->readUint16LE();
+ if (solutionArr[index] == _vm->_codeEntered[2]) {
+ return 1;
+ }
+ } else
+ // skip last index check
+ _currScript->seek(_currScript->pos() + 2);
+ } else
+ // skip two last index checks
+ _currScript->seek(_currScript->pos() + 4);
+ } else
+ // skip the three index checks
+ _currScript->seek(_currScript->pos() + 6);
+
+ return 0;
+}
+
+byte LilliputScript::OC_checkViewPortCharacterTarget() {
+ debugC(1, kDebugScript, "OC_checkViewPortCharacterTarget()");
+
+ int var1 = getValue1();
+ if (var1 == _viewportCharacterTarget)
+ return 1;
+
+ return 0;
+}
+
+void LilliputScript::OC_setWord18821() {
+ debugC(1, kDebugScriptTBC, "OC_setWord18821()");
+
+ _word18821 = getValue1();
+}
+
+void LilliputScript::OC_ChangeIsoMap() {
+ debugC(1, kDebugScript, "OC_ChangeIsoMap()");
+
+ Common::Point var1 = getPosFromScript();
+ int var2 = _currScript->readUint16LE();
+ int var3 = _currScript->readUint16LE();
+ byte* mapPtr = getMapPtr(var1);
+
+ int mask = 8 >> var2;
+ mask = ~mask;
+ mapPtr[3] &= mask;
+
+ if (var3 > 0) {
+ mask = ~mask;
+ mapPtr[3] |= mask;
+ }
+}
+
+void LilliputScript::OC_startSpeech() {
+ debugC(1, kDebugScript, "OC_startSpeech()");
+
+ int curWord = _currScript->readUint16LE();
+
+ bool forceReturnFl = false;
+ checkSpeechAllowed(forceReturnFl);
+ if (forceReturnFl)
+ return;
+
+ _talkingCharacter = _vm->_currentScriptCharacter;
+ startSpeech(curWord);
+}
+
+void LilliputScript::getSpeechVariant(int speechIndex, int speechVariant) {
+ debugC(2, kDebugScript, "getSpeechVariant(%d, %d)", speechIndex, speechVariant);
+
+ // The packed strings are stored by variants, enclosed by imbricated brackets.
+ // So the different possibilities are:
+ // text
+ // [text1]text2
+ // [[text1]text2]text3
+ // etc etc
+
+ if (speechIndex == -1)
+ return;
+
+ _currentSpeechId = speechIndex;
+ int index = _vm->_packedStringIndex[speechIndex];
+
+ // Skip the speech variant opening characters
+ while (_vm->_packedStrings[index] == '[')
+ ++index;
+
+ for (int i = 0; i < speechVariant; i++) {
+ byte tmpVal = ' ';
+ // Skip a speech variant
+ while (tmpVal != ']') {
+ tmpVal = _vm->_packedStrings[index];
+ ++index;
+ }
+ }
+
+ if (_vm->_packedStrings[index] == 0)
+ return;
+
+ decodePackedText(&_vm->_packedStrings[index]);
+}
+
+void LilliputScript::OC_getComputedVariantSpeech() {
+ debugC(1, kDebugScript, "OC_getComputedVariantSpeech()");
+
+ int tmpVal1 = getCharacterAttributesPtr()[0];
+ int tmpVal2 = (_currScript->readUint16LE() & 0xFF);
+ int speechVariant = tmpVal1 / tmpVal2;
+
+ int speechIndex = _currScript->readUint16LE();
+
+ bool forceReturnFl = false;
+ checkSpeechAllowed(forceReturnFl);
+ if (forceReturnFl)
+ return;
+
+ _talkingCharacter = _vm->_currentScriptCharacter;
+ getSpeechVariant(speechIndex, speechVariant);
+}
+
+void LilliputScript::OC_getRotatingVariantSpeech() {
+ debugC(1, kDebugScript, "OC_getRotatingVariantSpeech()");
+
+ int index = _currScript->readUint16LE();
+ int maxValue = getPackedStringStartRelativeIndex(index);
+
+ int currVariant = _currScript->readUint16LE();
+ int nextVariant = currVariant + 1;
+ if (nextVariant >= maxValue)
+ nextVariant = 0;
+ _currScript->writeUint16LE(nextVariant, -2);
+
+ bool forceReturnFl = false;
+ checkSpeechAllowed(forceReturnFl);
+ if (forceReturnFl)
+ return;
+
+ _talkingCharacter = _vm->_currentScriptCharacter;
+
+ getSpeechVariant(index, currVariant);
+
+}
+
+void LilliputScript::OC_startSpeechIfMute() {
+ debugC(1, kDebugScript, "OC_startSpeechIfMute()");
+
+ if (_talkingCharacter == -1) {
+ OC_startSpeech();
+ return;
+ }
+
+ _currScript->readUint16LE();
+}
+
+void LilliputScript::OC_getComputedVariantSpeechIfMute() {
+ debugC(1, kDebugScript, "OC_getComputedVariantSpeechIfMute()");
+
+ if (_talkingCharacter == -1) {
+ OC_getComputedVariantSpeech();
+ return;
+ }
+ _currScript->readUint16LE();
+ _currScript->readUint16LE();
+ _currScript->readUint16LE();
+ _currScript->readUint16LE();
+
+}
+
+void LilliputScript::OC_startSpeechIfSilent() {
+ debugC(1, kDebugScript, "OC_startSpeechIfSilent()");
+
+ if (_talkingCharacter == -1) {
+ OC_getRotatingVariantSpeech();
+ return;
+ }
+ _currScript->readUint16LE();
+ _currScript->readUint16LE();
+}
+
+void LilliputScript::OC_ComputeCharacterVariable() {
+ debugC(1, kDebugScript, "OC_ComputeCharacterVariable()");
+
+ byte *bufPtr = getCharacterAttributesPtr();
+ uint16 oper = _currScript->readUint16LE();
+ int16 var3 = _currScript->readSint16LE();
+
+ computeOperation(bufPtr, oper, var3);
+}
+
+void LilliputScript::OC_setAttributeToRandom() {
+ debugC(1, kDebugScript, "OC_setAttributeToRandom()");
+
+ byte *bufPtr = getCharacterAttributesPtr();
+ int maxVal = _currScript->readUint16LE();
+ int randomVal = _vm->_rnd->getRandomNumber(maxVal);
+ *bufPtr = randomVal;
+}
+
+void LilliputScript::OC_setCharacterPosition() {
+ debugC(1, kDebugScript, "OC_setCharacterPosition()");
+
+ int index = getValue1();
+ assert((index >= 0) && (index < 40));
+ Common::Point tmpVal = getPosFromScript();
+
+ int charPosX = (tmpVal.x << 3) + 4;
+ int charPosY = (tmpVal.y << 3) + 4;
+
+ _vm->_characterPos[index] = Common::Point(charPosX, charPosY);
+}
+
+void LilliputScript::OC_DisableCharacter() {
+ debugC(1, kDebugScript, "OC_DisableCharacter()");
+
+ int characterIndex = getValue1();
+ assert(characterIndex < 40);
+
+ if (characterIndex == _vm->_host)
+ _viewportCharacterTarget = -1;
+
+ _vm->_characterPos[characterIndex] = Common::Point(-1, -1);
+}
+
+void LilliputScript::OC_saveAndQuit() {
+ warning("TODO: OC_saveAndQuit");
+ _vm->_soundHandler->remove(); // Kill music
+ // TODO: Save game
+ _vm->_shouldQuit = true;
+}
+
+void LilliputScript::OC_nSkipOpcodes() {
+ debugC(1, kDebugScript, "OC_nSkipOpcodes()");
+
+ int var1 = _currScript->readUint16LE();
+ skipOpcodes(var1);
+}
+
+void LilliputScript::OC_startSpeech5() {
+ debugC(1, kDebugScript, "OC_startSpeech5()");
+
+ bool forceReturnFl = false;
+ checkSpeechAllowed(forceReturnFl);
+ if (forceReturnFl)
+ return;
+
+ _talkingCharacter = _vm->_currentScriptCharacter;
+ startSpeech(5);
+}
+
+void LilliputScript::OC_resetHandleOpcodeFlag() {
+ debugC(1, kDebugScript, "OC_resetHandleOpcodeFlag()");
+
+ _vm->_handleOpcodeReturnCode = 0;
+}
+
+void LilliputScript::OC_deleteSavegameAndQuit() {
+ warning("TODO: OC_deleteSavegameAndQuit");
+ _vm->_shouldQuit = true;
+}
+
+void LilliputScript::OC_incScriptForVal() {
+ debugC(1, kDebugScript, "OC_incScriptForVal()");
+
+ ++_scriptForVal;
+}
+
+void LilliputScript::OC_computeChararacterAttr() {
+ debugC(1, kDebugScript, "OC_ComputeChararacterAttr()");
+
+ byte *tmpArr = getCharacterAttributesPtr();
+ uint16 oper = _currScript->readUint16LE();
+ int16 var3 = getCharacterAttributesPtr()[0];
+ computeOperation(tmpArr, oper, var3);
+}
+
+void LilliputScript::OC_setTextVarNumber() {
+ debugC(1, kDebugScript, "OC_setTextVarNumber()");
+
+ byte *tmpArr = getCharacterAttributesPtr();
+ _textVarNumber = *tmpArr;
+}
+
+void LilliputScript::OC_callScript() {
+ debugC(1, kDebugScript, "OC_callScript()");
+
+ int index = _currScript->readUint16LE();
+ int charIndex = getValue1();
+ _vm->setCurrentCharacter(charIndex);
+
+ int tmpIndex = _vm->_currentScriptCharacter;
+
+ assert(index < _vm->_gameScriptIndexSize);
+ int scriptIndex = _vm->_arrayGameScriptIndex[index];
+
+ _scriptStack.push(_currScript);
+
+ if (_byte16F05_ScriptHandler == 0) {
+ _vm->_handleOpcodeReturnCode = 0;
+ debugC(1, kDebugScript, "========================== Menu Script %d==============================", scriptIndex);
+ runMenuScript(ScriptStream(&_vm->_arrayGameScripts[scriptIndex], _vm->_arrayGameScriptIndex[index + 1] - _vm->_arrayGameScriptIndex[index]));
+ debugC(1, kDebugScript, "========================== End of Menu Script==============================");
+ } else {
+ runScript(ScriptStream(&_vm->_arrayGameScripts[scriptIndex], _vm->_arrayGameScriptIndex[index + 1] - _vm->_arrayGameScriptIndex[index]));
+ }
+
+ _currScript = _scriptStack.pop();
+
+ _vm->setCurrentCharacter(tmpIndex);
+}
+
+void LilliputScript::OC_callScriptAndReturn() {
+ debugC(1, kDebugScript, "OC_callScriptAndReturn()");
+
+ OC_callScript();
+ skipOpcodes(0);
+}
+
+void LilliputScript::OC_setCurrentScriptCharacterPos() {
+ debugC(1, kDebugScript, "OC_setCurrentScriptCharacterPos()");
+
+ Common::Point pos = getPosFromScript();
+ _vm->_characterTargetPos[_vm->_currentScriptCharacter] = pos;
+ _vm->_characterSubTargetPos[_vm->_currentScriptCharacter].x = -1;
+}
+
+void LilliputScript::OC_initScriptFor() {
+ debugC(1, kDebugScript, "OC_initScriptFor()");
+
+ _scriptForVal = 0;
+}
+
+void LilliputScript::OC_setCurrentCharacterSequence() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacterSequence()");
+
+ int8 seqIdx = (_currScript->readUint16LE() & 0xFF);
+ setSequence(_vm->_currentScriptCharacter, seqIdx);
+}
+
+void LilliputScript::OC_setNextCharacterSequence() {
+ debugC(1, kDebugScript, "OC_setNextCharacterSequence()");
+
+ int8 seqIdx = (_currScript->readUint16LE() & 0xFF);
+ setSequence(_vm->_currentScriptCharacter + 1, seqIdx);
+}
+
+void LilliputScript::OC_setHost() {
+ debugC(1, kDebugScript, "OC_setHost()");
+
+ _vm->_host = getValue1();
+}
+
+void LilliputScript::OC_changeMapCube() {
+ debugC(1, kDebugScript, "OC_changeMapCube()");
+
+ assert(_vm->_currentCharacterAttributes != NULL);
+ Common::Point var1 = Common::Point(_vm->_currentCharacterAttributes[4], _vm->_currentCharacterAttributes[5]);
+ byte var2 = _vm->_currentCharacterAttributes[6];
+
+ byte *mapPtr = getMapPtr(var1);
+ mapPtr[var2] = _vm->_currentCharacterAttributes[7];
+ mapPtr[3] = _vm->_currentCharacterAttributes[8];
+
+ if (var2 == 0) {
+ _vm->_refreshScreenFlag = true;
+ _vm->displayLandscape();
+ _vm->_refreshScreenFlag = false;
+ }
+}
+
+void LilliputScript::OC_setCharacterCarry() {
+ debugC(1, kDebugScript, "OC_setCharacterCarry()");
+
+ int8 carriedIdx = (getValue1() & 0xFF);
+ int16 index = getValue1();
+
+ int8 distBehind = (_currScript->readSint16LE() & 0xFF);
+ byte distAbove = (_currScript->readUint16LE() & 0xFF);
+
+ assert((index >= 0) && (index < 40));
+ _vm->_characterCarried[index] = carriedIdx;
+ _vm->_characterBehindDist[index] = distBehind;
+ _vm->_characterAboveDist[index] = distAbove;
+}
+
+void LilliputScript::OC_dropCarried() {
+ debugC(1, kDebugScript, "OC_dropCarried()");
+
+ int index = getValue1();
+ _vm->_characterCarried[index] = -1;
+ _vm->_characterPosAltitude[index] = 0;
+ _characterScriptEnabled[index] = 1;
+}
+
+void LilliputScript::OC_setCurrentCharacter() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacter()");
+ int index = getValue1();
+ _vm->setCurrentCharacter(index);
+}
+
+void LilliputScript::sendSignal(int16 var1, byte var2h, byte characterId, int16 var4) {
+ debugC(2, kDebugScript, "sendSignal(%d, %d, %d, %d)", var1, var2h, characterId, var4);
+
+ int index = 0;
+ for (int i = 0; i < 10; i++) {
+ if (_vm->_signalArray[index + 1] == -1) {
+ _vm->_signalArray[index + 1] = var1;
+ _vm->_signalArray[index + 2] = (var2h << 8) + characterId;
+ _vm->_signalArray[index + 0] = _vm->_signalTimer + var4;
+ return;
+ }
+ index += 3;
+ }
+}
+
+void LilliputScript::OC_sendSeeSignal() {
+ debugC(1, kDebugScript, "OC_sendSeeSignal()");
+
+ int16 type = 2 << 8; // SEE
+ int16 var4 = _currScript->readSint16LE();
+ byte var2h = (_currScript->readUint16LE() & 0xFF);
+
+ sendSignal(type, var2h, _vm->_currentScriptCharacter, var4);
+}
+
+void LilliputScript::OC_sendHearSignal() {
+ debugC(1, kDebugScript, "OC_sendHearSignal()");
+
+ int16 type = 1 << 8; // HEAR
+ int16 var4 = _currScript->readSint16LE();
+ byte var2h = (_currScript->readUint16LE() & 0xFF);
+
+ sendSignal(type, var2h, _vm->_currentScriptCharacter, var4);
+}
+
+void LilliputScript::OC_sendVarSignal() {
+ debugC(1, kDebugScript, "OC_sendVarSignal()");
+
+ int16 var4 = _currScript->readSint16LE();
+ int16 type = getValue1();
+ byte var2h = (_currScript->readUint16LE() & 0xFF);
+
+ sendSignal(type, var2h, _vm->_currentScriptCharacter, var4);
+}
+
+void LilliputScript::OC_sendBroadcastSignal() {
+ debugC(1, kDebugScript, "OC_sendBroadcastSignal()");
+
+ int16 type = 3 << 8;
+ int16 var4 = _currScript->readSint16LE();
+ byte var2h = (_currScript->readUint16LE() & 0xFF);
+
+ sendSignal(type, var2h, _vm->_currentScriptCharacter, var4);
+}
+
+void LilliputScript::OC_resetWaitingSignal() {
+ debugC(1, kDebugScript, "OC_resetWaitingSignal()");
+
+ _vm->_waitingSignal = -1;
+ _vm->_waitingSignalCharacterId = -1;
+}
+
+void LilliputScript::OC_enableCurrentCharacterScript() {
+ debugC(1, kDebugScript, "OC_enableCurrentCharacterScript()");
+
+ uint8 var1 = (_currScript->readUint16LE() & 0xFF);
+ enableCharacterScript(_vm->_currentScriptCharacter , var1, _vm->_currentCharacterAttributes);
+ skipOpcodes(0);
+}
+
+void LilliputScript::OC_IncCurrentCharacterVar1() {
+ debugC(1, kDebugScript, "OC_IncCurrentCharacterVar1()");
+
+ assert(_vm->_currentCharacterAttributes != NULL);
+ ++_vm->_currentCharacterAttributes[1];
+}
+
+void LilliputScript::OC_setCurrentCharacterPos() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacterPos()");
+
+ uint16 oper = _currScript->readUint16LE();
+ Common::Point var1 = getPosFromScript();
+ byte* buf = _vm->_currentCharacterAttributes + 4;
+ computeOperation(buf, oper, var1.x);
+ computeOperation(buf + 1, oper, var1.y);
+}
+
+void LilliputScript::OC_setCurrentCharacterBehavior() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacterBehavior()");
+
+ uint16 var1 = _currScript->readUint16LE();
+ _vm->_characterBehaviour[_vm->_currentScriptCharacter] = (var1 - 2000) & 0xFF;
+}
+
+void LilliputScript::OC_changeCurrentCharacterSprite() {
+ debugC(2, kDebugScript, "OC_changeCurrentCharacterSprite()");
+
+ int16 var1 = _currScript->readSint16LE();
+ byte var2 = (_currScript->readUint16LE() & 0xFF);
+ _vm->_characterFrameArray[_vm->_currentScriptCharacter] = var1;
+ _vm->_spriteSizeArray[_vm->_currentScriptCharacter] = var2;
+
+}
+
+byte *LilliputScript::getCurrentCharacterVarFromScript() {
+ debugC(2, kDebugScript, "getCurrentCharacterVarFromScript()");
+
+ int index = _currScript->readUint16LE();
+ return &_vm->_currentCharacterAttributes[index];
+}
+
+void LilliputScript::OC_getList() {
+ debugC(1, kDebugScript, "OC_getList()");
+
+ byte *compBuf = getCurrentCharacterVarFromScript();
+ uint16 oper = _currScript->readUint16LE();
+ int index = _currScript->readUint16LE();
+
+ byte *buf = getCurrentCharacterVarFromScript();
+ byte var1 = buf[0];
+ byte var3 = _vm->_listArr[var1 + _vm->_listIndex[index]];
+
+ computeOperation(compBuf, oper, var3);
+}
+
+void LilliputScript::OC_setList() {
+ debugC(1, kDebugScript, "OC_setList()");
+
+ int indexChunk10 = _currScript->readUint16LE();
+
+ byte *compBuf = getCurrentCharacterVarFromScript();
+ int indexChunk11 = _vm->_listIndex[indexChunk10] + compBuf[0];
+
+ uint16 oper = _currScript->readUint16LE();
+
+ byte *tmpBuf = getCurrentCharacterVarFromScript();
+ int16 var3 = tmpBuf[0];
+
+ computeOperation(&_vm->_listArr[indexChunk11], oper, var3);
+}
+
+Common::Point LilliputScript::getCharacterTilePos(int index) {
+ debugC(2, kDebugScript, "getCharacterTilePos(%d)", index);
+
+ return Common::Point(_vm->_characterPos[index].x >> 3, _vm->_characterPos[index].y >> 3);
+}
+
+void LilliputScript::OC_setCharacterDirectionTowardsPos() {
+ debugC(1, kDebugScript, "OC_setCharacterDirectionTowardsPos()");
+
+ Common::Point pos1 = getPosFromScript();
+ Common::Point tilePos = getCharacterTilePos(_vm->_currentScriptCharacter);
+
+ _vm->_characterDirectionArray[_vm->_currentScriptCharacter] = _vm->getDirection(tilePos, pos1);
+}
+
+void LilliputScript::OC_turnCharacterTowardsAnother() {
+ debugC(1, kDebugScript, "OC_turnCharacterTowardsAnother()");
+
+ int index = getValue1();
+
+ static const byte _directionsArray[] = { 0, 2, 0, 1, 3, 2, 3, 1 };
+
+ int dx = _vm->_characterPos[index].x - _vm->_characterPos[_vm->_currentScriptCharacter].x;
+ int dy = _vm->_characterPos[index].y - _vm->_characterPos[_vm->_currentScriptCharacter].y;
+
+ int flag = 0;
+ if (dx < 0) {
+ dx = -dx;
+ flag |= 4;
+ }
+ if (dy < 0) {
+ dy = -dy;
+ flag |= 2;
+ }
+ if (dx < dy) {
+ flag |= 1;
+ }
+
+ _vm->_characterDirectionArray[_vm->_currentScriptCharacter] = _directionsArray[flag];
+}
+
+void LilliputScript::OC_setSeek() {
+ debugC(1, kDebugScript, "OC_setSeek()");
+
+ int16 var = getValue1();
+ _characterSeek[_vm->_currentScriptCharacter] = (byte)(var & 0xFF);
+ _vm->_characterSubTargetPos[_vm->_currentScriptCharacter].x = -1;
+}
+
+void LilliputScript::OC_scrollAwayFromCharacter() {
+ debugC(1, kDebugScript, "OC_scrollAwayFromCharacter()");
+
+ if (_vm->_currentScriptCharacter != _viewportCharacterTarget)
+ return;
+
+ static const int8 speedX[] = {-1, -3, -3, -6};
+ static const int8 speedY[] = {-3, -6, -1, -3};
+
+ int cx = speedX[_vm->_characterDirectionArray[_vm->_currentScriptCharacter]];
+ int cy = speedY[_vm->_characterDirectionArray[_vm->_currentScriptCharacter]];
+
+ Common::Point pos = getCharacterTilePos(_vm->_currentScriptCharacter);
+
+ int newPosX = pos.x + cx;
+ int newPosY = pos.y + cy;
+
+ newPosX = CLIP(newPosX, 0, 56);
+ newPosY = CLIP(newPosY, 0, 56);
+
+ _vm->_refreshScreenFlag = true;
+ _vm->viewportScrollTo(Common::Point(newPosX, newPosY));
+ _vm->_refreshScreenFlag = false;
+
+}
+
+void LilliputScript::OC_skipNextVal() {
+ debugC(1, kDebugScript, "OC_skipNextVal()");
+
+ _currScript->readUint16LE();
+}
+
+void LilliputScript::OC_setCurrentCharacterAttr6() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacterAttr6()");
+
+ uint16 var1 = (uint16)getValue1();
+ _vm->_currentCharacterAttributes[6] = var1 & 0xFF;
+}
+
+void LilliputScript::OC_setCurrentCharacterPose() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacterPose()");
+
+ int index = _currScript->readUint16LE();
+
+ int tmpVal = (_vm->_currentScriptCharacter * 32) + index;
+ assert (tmpVal < 40 * 32);
+ _characterPose[_vm->_currentScriptCharacter] = _vm->_poseArray[tmpVal];
+ _characterNextSequence[_vm->_currentScriptCharacter] = 16;
+}
+
+void LilliputScript::OC_setCharacterScriptEnabled() {
+ debugC(1, kDebugScript, "OC_setCharacterScriptEnabled()");
+
+ int16 index = getValue1();
+ _characterScriptEnabled[index] = 1;
+}
+
+void LilliputScript::OC_setCurrentCharacterAttr2() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacterAttr2()");
+
+ int curWord = _currScript->readUint16LE();
+ assert(_vm->_currentCharacterAttributes != NULL);
+ _vm->_currentCharacterAttributes[2] = curWord & 0xFF;
+}
+
+void LilliputScript::OC_clearCurrentCharacterAttr2() {
+ debugC(1, kDebugScript, "OC_clearCurrentCharacterAttr2()");
+
+ assert(_vm->_currentCharacterAttributes != NULL);
+ _vm->_currentCharacterAttributes[2] = 0;
+}
+
+void LilliputScript::OC_setCharacterProperties() {
+ debugC(1, kDebugScript, "OC_setCharacterProperties()");
+
+ int16 index = getValue1();
+
+ int16 x = _vm->_characterPos[index].x & 0xFFF8;
+ x += _currScript->readSint16LE();
+ _vm->_characterPos[index].x = x;
+
+ int16 y = _vm->_characterPos[index].y & 0xFFF8;
+ y += _currScript->readSint16LE();
+ _vm->_characterPos[index].y = y;
+
+ _vm->_characterPosAltitude[index] = (int8)(_currScript->readUint16LE() & 0xFF);
+ _vm->_characterDirectionArray[index] = _currScript->readUint16LE() & 0xFF;
+}
+
+void LilliputScript::OC_setMonitoredCharacter() {
+ debugC(1, kDebugScript, "OC_setMonitoredCharacter()");
+
+ _monitoredCharacter = getValue1();
+ for (int i = 0; i < 4; i++)
+ _monitoredAttr[i] = _currScript->readUint16LE() & 0xFF;
+}
+
+void LilliputScript::OC_setNewPose() {
+ debugC(1, kDebugScript, "OC_setNewPose()");
+
+ int var2 = _currScript->readUint16LE();
+ byte var1 = (_currScript->readUint16LE() & 0xFF);
+
+ _vm->_poseArray[(_vm->_currentScriptCharacter * 32) + var2] = var1;
+}
+
+void LilliputScript::OC_setCurrentCharacterDirection() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacterDirection()");
+
+ _vm->_characterDirectionArray[_vm->_currentScriptCharacter] = (_currScript->readUint16LE() & 0xFF);
+}
+
+void LilliputScript::OC_setInterfaceHotspot() {
+ debugC(1, kDebugScript, "OC_setInterfaceHotspot()");
+
+ int16 index = _currScript->readSint16LE();
+ assert((index >= 0) && (index < 20));
+
+ uint16 curWord = _currScript->readUint16LE();
+ _interfaceHotspotStatus[index] = (curWord & 0xFF);
+ _interfaceButtonActivationDelay[index] = (curWord >> 8);
+
+ _vm->displayInterfaceHotspots();
+}
+
+void LilliputScript::OC_scrollViewPort() {
+ debugC(1, kDebugScript, "OC_scrollViewPort()");
+
+ _viewportCharacterTarget = -1;
+
+ int direction = _currScript->readUint16LE();
+
+ static const int8 scrollValX[] = { 6, 0, 0, -6 };
+ static const int8 scrollValY[] = { 0, -6, 6, 0 };
+
+ int x = _viewportPos.x + scrollValX[direction];
+ int y = _viewportPos.y + scrollValY[direction];
+
+ x = CLIP(x, 0, 56);
+ y = CLIP(y, 0, 56);
+
+ _vm->_refreshScreenFlag = true;
+ _vm->viewportScrollTo(Common::Point(x, y));
+ _vm->_refreshScreenFlag = false;
+}
+
+void LilliputScript::OC_setViewPortPos() {
+ debugC(1, kDebugScript, "OC_setViewPortPos()");
+
+ _viewportCharacterTarget = -1;
+ _viewportPos = getPosFromScript();
+
+ _vm->displayLandscape();
+ _vm->prepareGameArea();
+}
+
+void LilliputScript::OC_setCurrentCharacterAltitude() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacterAltitude()");
+
+ _vm->_characterPosAltitude[_vm->_currentScriptCharacter] = (_currScript->readUint16LE() & 0xFF);
+}
+
+void LilliputScript::OC_setModePriority() {
+ debugC(1, kDebugScript, "OC_setModePriority()");
+
+ EvaluatedMode newMode;
+
+ newMode._mode = _currScript->readUint16LE() & 0xFF;
+ newMode._priority = _currScript->readUint16LE() & 0xFF;
+
+ setMode(newMode);
+}
+
+void LilliputScript::setMode(EvaluatedMode newMode) {
+ debugC(2, kDebugScript, "setMode(%d - %d)", newMode._mode, newMode._priority);
+
+ for (int i = 0; i < _vm->_newModesEvaluatedNumber; i++) {
+ if (_newEvaluatedModes[i]._mode == newMode._mode) {
+ int newPriority = newMode._priority + _newEvaluatedModes[i]._priority;
+ newPriority = CLIP(newPriority, 0, 255);
+
+ _newEvaluatedModes[i]._priority = newPriority;
+ return;
+ }
+ }
+
+ _newEvaluatedModes[_vm->_newModesEvaluatedNumber] = newMode;
+ ++_vm->_newModesEvaluatedNumber;
+}
+
+void LilliputScript::OC_setComputedModePriority() {
+ debugC(1, kDebugScript, "OC_setComputedModePriority()");
+
+ int8 mode = (int8)(_currScript->readUint16LE() & 0xFF);
+ byte oper = _currScript->readUint16LE() & 0xFF;
+ uint16 index = _currScript->readUint16LE();
+ int16 c = _vm->_currentCharacterAttributes[index];
+
+ switch (oper) {
+ case '-':
+ c = -1 - c;
+ break;
+ case '>':
+ c -= 128;
+ if (c < 0)
+ c = 0;
+ c *= 2;
+ break;
+ case '<':
+ c = -1 - c - 128;
+ if (c < 0)
+ c = 0;
+ c *= 2;
+ break;
+ case '+':
+ break;
+ default:
+ warning("OC_setComputedModePriority: skipped oper %c", oper);
+ break;
+ }
+ if (c > 0xFF)
+ warning("OC_setComputedModePriority- Abnormal value c = %d, should put back c &= 0xFF;", c);
+
+ int priority = (_currScript->readSint16LE() * c) + c;
+ priority >>= 8;
+
+ EvaluatedMode newMode;
+ newMode._mode = mode;
+ newMode._priority = priority;
+
+ setMode(newMode);
+}
+
+void LilliputScript::OC_selectBestMode() {
+ debugC(1, kDebugScript, "OC_selectBestMode()");
+
+ uint16 var1 = _currScript->readUint16LE();
+
+ int maxValue = 0;
+ int maxItem = var1 & 0xFF;
+
+ for (int i = 0; i < _vm->_newModesEvaluatedNumber; i++) {
+ if (_newEvaluatedModes[i]._priority > maxValue) {
+ maxValue = _newEvaluatedModes[i]._priority;
+ maxItem = _newEvaluatedModes[i]._mode;
+ }
+ }
+ enableCharacterScript(_vm->_currentScriptCharacter, maxItem, _vm->_currentCharacterAttributes);
+}
+
+void LilliputScript::OC_magicPuffEntrance() {
+ debugC(1, kDebugScript, "OC_magicPuffEntrance()");
+
+ int16 index = getValue1();
+ assert((index >0) && (index < 40));
+
+ _vm->_characterMagicPuffFrame[index] = 4;
+}
+
+void LilliputScript::OC_spawnCharacterAtPos() {
+ debugC(1, kDebugScript, "OC_spawnCharacterAtPos()");
+
+ int index = getValue1();
+ Common::Point var4 = getPosFromScript();
+
+ Common::Point pt = var4 + _viewportPos;
+ byte *isoMapBuf = getMapPtr(pt);
+
+ if (isoMapBuf[1] != 0xFF) {
+ int minVal = INT_MAX;
+ for (int var2 = 7; var2 >= 0; var2--) {
+ for (int var3 = 7; var3 >= 0; var3--) {
+ Common::Point(_viewportPos.x + var2, _viewportPos.y + var3);
+ isoMapBuf = getMapPtr(pt);
+
+ if (isoMapBuf[1] == 0xFF) {
+ int x = abs(var2 - var4.x);
+ int y = abs(var3 - var4.y);
+ if (x + y < minVal) {
+ minVal = x + y;
+ _word1825E = Common::Point(var2, var3);
+ }
+ }
+ }
+ }
+ var4 = _word1825E;
+ }
+
+ _vm->_characterPos[index].x = (var4.x + _viewportPos.x) * 8;
+ _vm->_characterPos[index].y = (var4.y + _viewportPos.y) * 8;
+}
+
+void LilliputScript::OC_CharacterVariableAddOrRemoveFlag() {
+ debugC(1, kDebugScript, "OC_CharacterVariableAddOrRemoveFlag()");
+
+ byte *tmpArr = getCharacterAttributesPtr();
+
+ byte var1 = (_currScript->readUint16LE() & 0xFF);
+ byte var2 = (_currScript->readUint16LE() & 0xFF);
+
+ if (var2 == 0)
+ tmpArr[0] &= ~var1;
+ else
+ tmpArr[0] |= var1;
+}
+
+void LilliputScript::OC_PaletteFadeOut() {
+ debugC(1, kDebugScript, "OC_PaletteFadeOut()");
+
+ _vm->_refreshScreenFlag = true;
+ _vm->paletteFadeOut();
+ _vm->_refreshScreenFlag = false;
+}
+
+void LilliputScript::OC_PaletteFadeIn() {
+ debugC(1, kDebugScript, "OC_PaletteFadeIn()");
+
+ _vm->_refreshScreenFlag = true;
+ _vm->paletteFadeIn();
+ _vm->_refreshScreenFlag = false;
+}
+
+void LilliputScript::OC_loadAndDisplayCubesGfx() {
+ debugC(1, kDebugScript, "OC_loadAndDisplayCubesGfx()");
+
+ int setNumb = (_currScript->readUint16LE() & 0xFF);
+ assert((setNumb >= 0) && (setNumb <= 9));
+ Common::String fileName = Common::String::format("CUBES%d.GFX", setNumb);
+ _cubeSet = setNumb; // Useless in this variant, keep for the moment for Rome
+
+ _vm->_bufferCubegfx = _vm->loadVGA(fileName, 61440, false);
+ _vm->displayLandscape();
+ _vm->prepareGameArea();
+}
+
+void LilliputScript::OC_setCurrentCharacterAttr3() {
+ debugC(1, kDebugScript, "OC_setCurrentCharacterAttr3()");
+
+ byte var1 = _currScript->readUint16LE() & 0xFF;
+ assert(_vm->_currentCharacterAttributes != NULL);
+
+ _vm->_currentCharacterAttributes[3] = var1;
+}
+
+void LilliputScript::OC_setArray122C1() {
+ debugC(1, kDebugScript, "OC_setArray122C1()");
+
+ byte var1 = (_currScript->readUint16LE() & 0xFF);
+ _array122C1[_vm->_currentScriptCharacter] = var1;
+}
+
+void LilliputScript::OC_sub18367() {
+ debugC(1, kDebugScriptTBC, "OC_sub18367()");
+
+ _characterScriptEnabled[_vm->_currentScriptCharacter] = 1;
+ _vm->_currentCharacterAttributes[0] = _array122C1[_vm->_currentScriptCharacter];
+ _vm->_currentCharacterAttributes[1] = 0;
+ _vm->_currentCharacterAttributes[2] = 0;
+ _vm->_currentCharacterAttributes[3] = 0;
+}
+
+void LilliputScript::OC_enableCharacterScript() {
+ debugC(1, kDebugScript, "OC_enableCharacterScript()");
+
+ int16 index = getValue1();
+ byte var2 = _currScript->readUint16LE() & 0xFF;
+
+ enableCharacterScript(index, var2, _vm->getCharacterAttributesPtr(index * 32));
+}
+
+void LilliputScript::OC_setRulesBuffer2Element() {
+ debugC(1, kDebugScript, "OC_setRulesBuffer2Element()");
+
+ int index = getValue1();
+ byte var1 = _currScript->readUint16LE() & 0xFF;
+
+ assert((index >= 0) && (index < 40));
+ _vm->_characterMobility[index] = var1;
+}
+
+void LilliputScript::OC_setDebugFlag() {
+ debugC(1, kDebugScript, "OC_setDebugFlag()");
+
+ _vm->_debugFlag = 1;
+}
+
+void LilliputScript::OC_setDebugFlag2() {
+ debugC(1, kDebugScript, "OC_setDebugFlag2()");
+
+ _vm->_debugFlag2 = 1;
+}
+
+void LilliputScript::OC_waitForEvent() {
+ debugC(1, kDebugScript, "OC_waitForEvent()");
+
+ _vm->_refreshScreenFlag = true;
+ while (true) {
+ if (_vm->_keyboard_checkKeyboard()) {
+ _vm->_keyboard_getch();
+ break;;
+ }
+ if (_vm->_mouseButton == 1)
+ break;
+
+ _vm->update();
+ }
+
+ _vm->_mouseButton = 0;
+ _vm->_refreshScreenFlag = false;
+}
+
+void LilliputScript::OC_disableInterfaceHotspot() {
+ debugC(1, kDebugScript, "OC_disableInterfaceHotspot()");
+
+ int index = _currScript->readUint16LE();
+ _interfaceButtonActivationDelay[index] = (_currScript->readUint16LE() & 0xFF);
+ _interfaceHotspotStatus[index] = kHotspotDisabled;
+
+ _vm->displayInterfaceHotspots();
+}
+
+void LilliputScript::OC_loadFileAerial() {
+ debugC(1, kDebugScript, "OC_loadFileAerial()");
+
+ // Unused variable, and the script position is restored afterwards
+ // TODO: Check if this part of the code is present in Rome, else remove it
+ // int var1 = _currScript->readUint16LE() & 0xFF;
+ // byte _byte15EAD = var1;
+
+ _vm->_refreshScreenFlag = true;
+ _talkingCharacter = -1;
+ OC_PaletteFadeOut();
+ _vm->_displayGreenHand = true;
+ _vm->displayVGAFile("AERIAL.GFX");
+ OC_PaletteFadeIn();
+
+ _vm->displayCharactersOnMap();
+ _vm->_displayMap = true;
+
+ _vm->_keyboard_resetKeyboardBuffer();
+
+ _vm->_refreshScreenFlag = false;
+}
+
+void LilliputScript::OC_startSpeechIfSoundOff() {
+ debugC(1, kDebugScript, "OC_startSpeechIfSoundOff()");
+
+ // HACK: In the original, OC_startSpeechIfSoundOff() only calls
+ // OC_startSpeech if sound is off. For the moment, it's always called
+
+ OC_startSpeech();
+}
+
+void LilliputScript::OC_sub1844A() {
+ debugC(1, kDebugScriptTBC, "OC_sub1844A()");
+
+ int characterIndex = getValue1();
+ int var2 = _currScript->readUint16LE();
+
+ _vm->_characterTypes[characterIndex] = (var2 & 0xFF);
+
+ for (int i = 0; i < 40; i++) {
+ _interactions[40 * characterIndex + i] = 0;
+ _interactions[characterIndex + 40 * i] = 0;
+ }
+}
+
+void LilliputScript::OC_displayNumericCharacterVariable() {
+ debugC(1, kDebugScript, "OC_displayNumericCharacterVariable()");
+
+ byte *charAttrArr = getCharacterAttributesPtr();
+ byte attr = charAttrArr[0];
+ int divisor = _currScript->readUint16LE();
+ assert(divisor != 0);
+ int displayVal = attr / (divisor & 0xFF);
+ int posX = _currScript->readSint16LE();
+ int posY = _currScript->readSint16LE();
+
+ if (!_vm->_displayMap)
+ displayNumber(displayVal, Common::Point(posX, posY));
+}
+
+void LilliputScript::displayNumber(byte var1, Common::Point pos) {
+ debugC(1, kDebugScript, "displayNumber(%d, %d - %d)", var1, pos.x, pos.y);
+
+ _vm->_displayStringIndex = 0;
+ _vm->_displayStringBuf[0] = 32;
+ _vm->_displayStringBuf[1] = 32;
+ _vm->_displayStringBuf[2] = 32;
+ _vm->_displayStringBuf[3] = 0;
+
+ _vm->numberToString(var1);
+ _vm->displayString(_vm->_displayStringBuf, pos);
+}
+
+void LilliputScript::OC_displayVGAFile() {
+ debugC(1, kDebugScript, "OC_displayVGAFile()");
+
+ _vm->_refreshScreenFlag = true;
+ _vm->paletteFadeOut();
+ int curWord = _currScript->readUint16LE();
+ int index = _vm->_packedStringIndex[curWord];
+ Common::String fileName = Common::String((const char *)&_vm->_packedStrings[index]);
+ _talkingCharacter = -1;
+ _vm->displayVGAFile(fileName);
+ _vm->paletteFadeIn();
+}
+
+void LilliputScript::OC_startSpeechWithoutSpeeker() {
+ debugC(1, kDebugScript, "OC_startSpeechWithoutSpeeker()");
+
+ int16 speechId = _currScript->readUint16LE();
+ startSpeech(speechId);
+}
+
+void LilliputScript::OC_displayTitleScreen() {
+ debugC(1, kDebugScript, "OC_displayTitleScreen()");
+
+ _vm->_keyDelay = (_currScript->readUint16LE() & 0xFF);
+ _vm->_int8Timer = _vm->_keyDelay;
+
+ _vm->_keyboard_resetKeyboardBuffer();
+
+ _vm->_mouseButton = 0;
+ _vm->_lastKeyPressed = Common::Event();
+
+ while (!_vm->_shouldQuit) {
+ _vm->displaySmallAnims();
+ _vm->update();
+ _vm->pollEvent();
+ if (_vm->_keyboard_checkKeyboard()) {
+ Common::Event event = _vm->_keyboard_getch();
+ _vm->_lastKeyPressed = event;
+ if (event.type == Common::EVENT_KEYDOWN)
+ _vm->_keyboard_getch();
+ break;
+ }
+
+ if (_vm->_mouseButton == 1)
+ break;
+
+ if ((_vm->_keyDelay != 0) && (_vm->_int8Timer == 0))
+ break;
+
+ _vm->_system->delayMillis(1);
+ }
+
+ _vm->_mouseButton = 0;
+}
+
+void LilliputScript::OC_initGameAreaDisplay() {
+ debugC(1, kDebugScript, "OC_initGameAreaDisplay()");
+
+ OC_PaletteFadeOut();
+ _vm->_displayMap = false;
+ _heroismLevel = 0;
+ _vm->unselectInterfaceHotspots();
+
+ _vm->initGameAreaDisplay();
+
+ OC_PaletteFadeIn();
+ _vm->_refreshScreenFlag = false;
+
+ _vm->_soundHandler->update();
+}
+
+void LilliputScript::OC_displayCharacterStatBar() {
+ debugC(1, kDebugScript, "OC_displayCharacterStatBar()");
+
+ byte *tmpArr = getCharacterAttributesPtr();
+ int8 type = (_currScript->readUint16LE() & 0xFF);
+ int8 score = (((70 * tmpArr[0]) / (_currScript->readUint16LE() & 0xFF)) & 0xFF);
+ int16 posX = _currScript->readSint16LE();
+ int16 posY = _currScript->readSint16LE();
+
+ _vm->displayCharacterStatBar(type, posX, score, posY);
+}
+
+void LilliputScript::OC_initSmallAnim() {
+ debugC(1, kDebugScript, "OC_initSmallAnim()");
+
+ int index = _currScript->readUint16LE();
+ assert (index < 4);
+ _vm->_smallAnims[index]._active = true;
+ _vm->_smallAnims[index]._pos.x = _currScript->readSint16LE();
+ _vm->_smallAnims[index]._pos.y = _currScript->readSint16LE();
+
+ for (int i = 0; i < 8; i++)
+ _vm->_smallAnims[index]._frameIndex[i] = _currScript->readUint16LE();
+}
+
+void LilliputScript::OC_setCharacterHeroismBar() {
+ debugC(1, kDebugScript, "OC_setCharacterHeroismBar()");
+
+ _barAttrPtr = getCharacterAttributesPtr();
+ _heroismBarX = _currScript->readUint16LE();
+ _heroismBarBottomY = _currScript->readUint16LE();
+}
+
+void LilliputScript::OC_setCharacterHome() {
+ debugC(1, kDebugScript, "OC_setCharacterHome()");
+
+ int index = getValue1();
+ _vm->_characterHomePos[index] = getPosFromScript();
+}
+
+void LilliputScript::OC_setViewPortCharacterTarget() {
+ debugC(1, kDebugScript, "OC_setViewPortCharacterTarget()");
+
+ _viewportCharacterTarget = getValue1();
+}
+
+void LilliputScript::OC_showObject() {
+ debugC(1, kDebugScript, "OC_showObject()");
+
+ int frameIdx = getValue1();
+ int posX = _currScript->readUint16LE();
+ int posY = _currScript->readUint16LE();
+ Common::Point pos = Common::Point(posX, posY);
+
+ _vm->fill16x16Rect(16, pos);
+
+ int frame = _vm->_characterFrameArray[frameIdx];
+ byte* buf = _vm->_bufferMen;
+
+ if (frame > 240) {
+ buf = _vm->_bufferMen2;
+ frame -= 240;
+ }
+
+ _vm->display16x16IndexedBuf(buf, frame, pos);
+}
+
+void LilliputScript::OC_playObjectSound() {
+ debugC(1, kDebugScript, "OC_playObjectSound()");
+ int index = getValue1();
+ assert(index < 40);
+
+ Common::Point var4 = Common::Point(0xFF, index & 0xFF);
+ int soundId = (_currScript->readUint16LE() & 0xFF);
+
+ _vm->_soundHandler->play(soundId, _viewportPos, _characterTilePos[index], var4);
+}
+
+void LilliputScript::OC_startLocationSound() {
+ debugC(1, kDebugScript, "OC_startLocationSound()");
+
+ Common::Point var3 = getPosFromScript();
+ Common::Point var4 = var3;
+ Common::Point var2 = _viewportPos;
+ int var1 = (_currScript->readUint16LE() & 0xFF);
+
+ _vm->_soundHandler->play(var1, var2, var3, var4);
+}
+
+void LilliputScript::OC_stopObjectSound() {
+ debugC(1, kDebugScript, "OC_stopObjectSound()");
+
+ Common::Point var4 = Common::Point(-1, getValue1() & 0xFF);
+
+ _vm->_soundHandler->stop(var4); // Stop Sound
+}
+
+void LilliputScript::OC_stopLocationSound() {
+ debugC(1, kDebugScript, "OC_stopLocationSound()");
+
+ Common::Point var4 = getPosFromScript();
+
+ _vm->_soundHandler->stop(var4);
+}
+
+void LilliputScript::OC_toggleSound() {
+ debugC(1, kDebugScript, "OC_toggleSound()");
+
+ _vm->_soundHandler->toggleOnOff();
+}
+
+void LilliputScript::OC_playMusic() {
+ debugC(1, kDebugScript, "OC_playMusic()");
+
+ Common::Point var4 = Common::Point(-1, -1);
+ Common::Point var2 = _viewportPos;
+ int var1 = _currScript->readSint16LE() & 0xFF;
+ warning("OC_playMusic: unknown value for var3");
+ Common::Point var3 = Common::Point(-1, -1);
+
+ _vm->_soundHandler->play(var1, var2, var3, var4);
+}
+
+void LilliputScript::OC_stopMusic() {
+ debugC(1, kDebugScript, "OC_stopMusic()");
+
+ _vm->_soundHandler->remove();
+}
+
+void LilliputScript::OC_setCharacterMapColor() {
+ debugC(1, kDebugScript, "OC_setCharacterMapColor()");
+
+ byte index = (getValue1() & 0xFF);
+ int color = _currScript->readUint16LE();
+
+ assert(index < 40);
+ _characterMapPixelColor[index] = (color & 0xFF);
+}
+
+} // End of namespace
diff --git a/engines/lilliput/script.h b/engines/lilliput/script.h
new file mode 100644
index 0000000000..d75d24e3cf
--- /dev/null
+++ b/engines/lilliput/script.h
@@ -0,0 +1,316 @@
+/* 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 LILLIPUT_SCRIPT_H
+#define LILLIPUT_SCRIPT_H
+
+#include "common/memstream.h"
+#include "common/stack.h"
+#include "common/random.h"
+#include "common/rect.h"
+
+#include "lilliput/stream.h"
+
+namespace Lilliput {
+
+class LilliputEngine;
+
+enum kActionType {
+ kActionNone = 0,
+ kButtonPressed = 1,
+ kButtonReleased = 2,
+ kActionTalk = 3,
+ kActionGoto = 4,
+ kCubeSelected = 5,
+ kCodeEntered = 6
+};
+
+enum kValueType {
+ kNone,
+ kImmediateValue,
+ kCompareOperation,
+ kComputeOperation,
+ kGetValue1,
+ kgetPosFromScript
+};
+
+struct OpCode {
+ const char* _opName;
+ int _numArgs;
+ kValueType _arg1;
+ kValueType _arg2;
+ kValueType _arg3;
+ kValueType _arg4;
+ kValueType _arg5;
+};
+
+struct EvaluatedMode {
+ int _mode;
+ int _priority;
+};
+
+class LilliputScript {
+public:
+ byte _heroismLevel;
+ byte _speechTimer;
+
+ byte _characterScriptEnabled[40];
+ int8 _interfaceHotspotStatus[20];
+ Common::Point _characterTilePos[40];
+ int8 _characterNextSequence[40];
+ int8 _characterPose[40];
+ byte _interfaceButtonActivationDelay[20];
+ byte _array122C1[40];
+ byte _characterSeek[40];
+ int16 _interactions[40 * 40];
+
+ byte *_barAttrPtr;
+
+ Common::Point _viewportPos;
+ int16 _viewportCharacterTarget;
+ int16 _talkingCharacter;
+ int _heroismBarX;
+ int _heroismBarBottomY;
+
+ Common::Point _sequenceArr[640];
+ byte _characterMapPixelColor[40];
+ int8 _characterLastSequence[40];
+ EvaluatedMode _newEvaluatedModes[32];
+
+ LilliputScript(LilliputEngine *vm);
+ ~LilliputScript();
+
+ void disasmScript(ScriptStream script);
+ void listAllTexts();
+ static Common::String getArgumentString(kValueType type, ScriptStream& script);
+ void runScript(ScriptStream script);
+ void runMenuScript(ScriptStream script);
+private:
+ LilliputEngine *_vm;
+
+ ScriptStream *_currScript;
+ Common::Stack<ScriptStream *> _scriptStack;
+
+ byte _byte16F05_ScriptHandler;
+ byte _cubeSet;
+ byte _lastRandomValue;
+ byte _scriptForVal;
+ byte _textVarNumber;
+ byte _speechDisplaySpeed;
+
+ int16 _word16F00_characterId;
+ int _currentSpeechId;
+ int _word18821;
+ int _monitoredCharacter;
+ Common::Point _word1825E;
+
+ char _monitoredAttr[4];
+
+ int handleOpcode(ScriptStream *script);
+ byte handleOpcodeType1(int curWord);
+ void handleOpcodeType2(int curWord);
+
+ void enableCharacterScript(byte index, byte var1, byte *curBufPtr);
+ void skipOpcodes(int var1);
+ void copySequence(int index, byte *buf);
+ void setSequence(int charIdx, int8 seqIdx);
+ void checkSpeechAllowed(bool &forceReturnFl);
+ void decodePackedText(char *buf);
+ void startSpeech(int var);
+ void displayNumber(byte var1, Common::Point pos);
+ byte *getMapPtr(Common::Point val);
+ byte *getCurrentCharacterVarFromScript();
+ void sendSignal(int16 var1, byte var2h, byte characterId, int16 var4);
+ void getSpeechVariant(int speechIndex, int speechVariant);
+ void showSpeech();
+ void formatSpeechString();
+ Common::Point getCharacterTilePos(int index);
+ int getPackedStringStartRelativeIndex(int index);
+
+ int16 getValue1();
+ Common::Point getPosFromScript();
+
+ byte *getCharacterAttributesPtr();
+ byte compareValues(int16 var1, uint16 oper, int16 var2);
+ void computeOperation(byte *bufPtr, uint16 oper, int16 var2);
+
+ //Opcodes Type 1
+ byte OC_checkCharacterGoalPos();
+ byte OC_comparePos();
+ byte OC_checkIsoMap3();
+ byte OC_compareCharacterVariable();
+ byte OC_CompareLastRandomValue();
+ byte OC_getRandom();
+ byte OC_for();
+ byte OC_compCurrentSpeechId();
+ byte OC_checkSaveFlag();
+ byte OC_compScriptForVal();
+ byte OC_isCarrying();
+ byte OC_CompareCharacterVariables();
+ byte OC_compareCoords_1();
+ byte OC_compareCoords_2();
+ byte OC_CompareDistanceFromCharacterToPositionWith();
+ byte OC_compareRandomCharacterId();
+ byte OC_IsCurrentCharacterIndex();
+ byte OC_hasVisibilityLevel();
+ byte OC_hasGainedVisibilityLevel();
+ byte OC_hasReducedVisibilityLevel();
+ byte OC_isHost();
+ byte OC_isSequenceActive();
+ byte OC_isSequenceFinished();
+ byte OC_CompareMapValueWith();
+ byte OC_IsCharacterValid();
+ byte OC_CheckWaitingSignal();
+ byte OC_CurrentCharacterVar0AndVar1Equals();
+ byte OC_CurrentCharacterVar0Equals();
+ byte OC_checkLastInterfaceHotspotIndexMenu13();
+ byte OC_checkLastInterfaceHotspotIndexMenu2();
+ byte OC_CompareNumberOfCharacterWithVar0Equals();
+ byte OC_IsPositionInViewport();
+ byte OC_CompareGameVariables();
+ byte OC_skipNextOpcode();
+ byte OC_CheckCurrentCharacterAttr2();
+ byte OC_CheckCurrentCharacterType();
+ byte OC_CheckCurrentCharacterAttr0And();
+ byte OC_IsCurrentCharacterAttr0LessEqualThan();
+ byte OC_isCarried();
+ byte OC_CheckCurrentCharacterAttr1();
+ byte OC_isCurrentCharacterSpecial();
+ byte OC_CurrentCharacterAttr3Equals1();
+ byte OC_checkCharacterDirection();
+ byte OC_checkLastInterfaceHotspotIndex();
+ byte OC_checkSelectedCharacter();
+ byte OC_checkDelayedReactivation();
+ byte OC_checkTargetReached();
+ byte OC_checkFunctionKeyPressed();
+ byte OC_checkCodeEntered();
+ byte OC_checkViewPortCharacterTarget();
+
+ // Opcodes Type 2
+ void OC_setWord18821();
+ void OC_ChangeIsoMap();
+ void OC_startSpeech();
+ void OC_getComputedVariantSpeech();
+ void OC_getRotatingVariantSpeech();
+ void OC_startSpeechIfMute();
+ void OC_getComputedVariantSpeechIfMute();
+ void OC_startSpeechIfSilent();
+ void OC_ComputeCharacterVariable();
+ void OC_setAttributeToRandom();
+ void OC_setCharacterPosition();
+ void OC_DisableCharacter();
+ void OC_saveAndQuit();
+ void OC_nSkipOpcodes();
+ void OC_startSpeech5();
+ void OC_resetHandleOpcodeFlag();
+ void OC_deleteSavegameAndQuit();
+ void OC_incScriptForVal();
+ void OC_computeChararacterAttr();
+ void OC_setTextVarNumber();
+ void OC_callScript();
+ void OC_callScriptAndReturn();
+ void OC_setCurrentScriptCharacterPos();
+ void OC_initScriptFor();
+ void OC_setCurrentCharacterSequence();
+ void OC_setNextCharacterSequence();
+ void OC_setHost();
+ void OC_changeMapCube();
+ void OC_setCharacterCarry();
+ void OC_dropCarried();
+ void OC_setCurrentCharacter();
+ void OC_sendSeeSignal();
+ void OC_sendHearSignal();
+ void OC_sendVarSignal();
+ void OC_sendBroadcastSignal();
+ void OC_resetWaitingSignal();
+ void OC_enableCurrentCharacterScript();
+ void OC_IncCurrentCharacterVar1();
+ void OC_setCurrentCharacterPos();
+ void OC_setCurrentCharacterBehavior();
+ void OC_changeCurrentCharacterSprite();
+ void OC_getList();
+ void OC_setList();
+ void OC_setCharacterDirectionTowardsPos();
+ void OC_turnCharacterTowardsAnother();
+ void OC_setSeek();
+ void OC_scrollAwayFromCharacter();
+ void OC_skipNextVal();
+ void OC_setCurrentCharacterAttr6();
+ void OC_setCurrentCharacterPose();
+ void OC_setCharacterScriptEnabled();
+ void OC_setCurrentCharacterAttr2();
+ void OC_clearCurrentCharacterAttr2();
+ void OC_setCharacterProperties();
+ void OC_setMonitoredCharacter();
+ void OC_setNewPose();
+ void OC_setCurrentCharacterDirection();
+ void OC_setInterfaceHotspot();
+ void OC_scrollViewPort();
+ void OC_setViewPortPos();
+ void OC_setCurrentCharacterAltitude();
+ void OC_setModePriority();
+ void setMode(EvaluatedMode newMode);
+ void OC_setComputedModePriority();
+ void OC_selectBestMode();
+ void OC_magicPuffEntrance();
+ void OC_spawnCharacterAtPos();
+ void OC_CharacterVariableAddOrRemoveFlag();
+ void OC_PaletteFadeOut();
+ void OC_PaletteFadeIn();
+ void OC_loadAndDisplayCubesGfx();
+ void OC_setCurrentCharacterAttr3();
+ void OC_setArray122C1();
+ void OC_sub18367();
+ void OC_enableCharacterScript();
+ void OC_setRulesBuffer2Element();
+ void OC_setDebugFlag();
+ void OC_setDebugFlag2();
+ void OC_waitForEvent();
+ void OC_disableInterfaceHotspot();
+ void OC_loadFileAerial();
+ void OC_startSpeechIfSoundOff();
+ void OC_sub1844A();
+ void OC_displayNumericCharacterVariable();
+ void OC_displayVGAFile();
+ void OC_startSpeechWithoutSpeeker();
+ void OC_displayTitleScreen();
+ void OC_initGameAreaDisplay();
+ void OC_displayCharacterStatBar();
+ void OC_initSmallAnim();
+ void OC_setCharacterHeroismBar();
+ void OC_setCharacterHome();
+ void OC_setViewPortCharacterTarget();
+ void OC_showObject();
+ void OC_playObjectSound();
+ void OC_startLocationSound();
+ void OC_stopObjectSound();
+ void OC_stopLocationSound();
+ void OC_toggleSound();
+ void OC_playMusic();
+ void OC_stopMusic();
+ void OC_setCharacterMapColor();
+};
+
+} // End of namespace Lilliput
+
+#endif
+
diff --git a/engines/lilliput/sound.cpp b/engines/lilliput/sound.cpp
new file mode 100644
index 0000000000..9045e47c9a
--- /dev/null
+++ b/engines/lilliput/sound.cpp
@@ -0,0 +1,248 @@
+/* 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 "lilliput/lilliput.h"
+#include "lilliput/sound.h"
+
+#include "common/debug.h"
+
+namespace Lilliput {
+
+static const byte _aliasArr[40] = {
+ 44, 0, 1, 2, 37, 3, 24, 45, 20, 19,
+ 16, 10, 11, 12, 41, 39, 40, 21, 22, 23,
+ 4, 5, 6, 52, 7, 8, 9, 33, 13, 14,
+ 15, 18, 26, 25, 38, 29, 36, 0xFF, 28, 40
+};
+
+static const bool _loopArr[40] = {
+ 0, 0, 0, 1, 1, 1, 0, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const byte _soundType [40] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0
+};
+
+LilliputSound::LilliputSound(LilliputEngine *vm) : _vm(vm) {
+ _unpackedFiles = nullptr;
+ _unpackedSizes = nullptr;
+ _fileNumb = 0;
+
+ _isGM = false;
+
+ MidiPlayer::createDriver();
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
+}
+
+LilliputSound::~LilliputSound() {
+ Audio::MidiPlayer::stop();
+
+ if (_unpackedFiles) {
+ for (int i = 0; i < _fileNumb; i++)
+ free(_unpackedFiles[i]);
+ }
+ free(_unpackedFiles);
+ free(_unpackedSizes);
+}
+
+byte LilliputSound::readByte(const byte *data, uint32 offset) {
+ uint16 al = data[0x201 + (offset >> 1)];
+ return data[1 + (offset & 1) + (al << 1)];
+}
+
+uint32 LilliputSound::decode(const byte *src, byte *dst, uint32 len, uint32 start) {
+ uint32 i = start;
+ for (; i < len; ++i) {
+ *dst++ = readByte(src, i);
+ }
+ return i;
+}
+
+void LilliputSound::loadMusic(Common::String filename) {
+ debugC(1, kDebugSound, "loadMusic(%s)", filename.c_str());
+
+ Common::File f;
+
+ if (!f.open(filename))
+ error("Missing music file %s", filename.c_str());
+
+ _fileNumb = f.readUint16LE();
+
+ int *fileSizes = new int[_fileNumb + 1];
+ for (int i = 0; i < _fileNumb; ++i)
+ fileSizes[i] = f.readUint16LE();
+ f.seek(0, SEEK_END);
+ fileSizes[_fileNumb] = f.pos();
+
+ _unpackedFiles = new byte *[_fileNumb];
+ _unpackedSizes = new uint16[_fileNumb];
+ int pos = (_fileNumb + 1) * 2; // file number + file sizes
+ for (int i = 0; i < _fileNumb; ++i) {
+ int packedSize = fileSizes[i + 1] - fileSizes[i];
+ byte *srcBuf = new byte[packedSize];
+ f.seek(pos, SEEK_SET);
+ f.read(srcBuf, packedSize);
+ if (srcBuf[0] == 'c' || srcBuf[0] == 'C') {
+ int shift = (srcBuf[0] == 'c') ? 1 : 0;
+ _unpackedSizes[i] = (1 + packedSize - 0x201) * 2 - shift;
+ byte *dstBuf = new byte[_unpackedSizes[i]];
+ decode(srcBuf, dstBuf, _unpackedSizes[i], shift);
+ _unpackedFiles[i] = dstBuf;
+ } else {
+ _unpackedSizes[i] = packedSize;
+ byte *dstBuf = new byte[packedSize];
+ for (int j = 0; j < packedSize; ++j)
+ dstBuf[j] = srcBuf[j];
+ _unpackedFiles[i] = dstBuf;
+ }
+ delete[] srcBuf;
+ pos += packedSize;
+ }
+
+ delete[] fileSizes;
+ f.close();
+
+ /* Debug code
+ for (int i = 0; i < _fileNumb; ++i) {
+ Common::DumpFile dmp;
+ Common::String name = Common::String::format("dmp%d.mid", i);
+ dmp.open(name);
+ dmp.write(_unpackedFiles[i], _unpackedSizes[i]);
+ dmp.close();
+ }
+ */
+}
+
+void LilliputSound::send(uint32 b) {
+ if (((b & 0xF0) == 0xC0) && !_isGM && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+
+ Audio::MidiPlayer::send(b);
+}
+
+void LilliputSound::sendToChannel(byte channel, uint32 b) {
+ if (!_channelsTable[channel]) {
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // If a new channel is allocated during the playback, make sure
+ // its volume is correctly initialized.
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
+ }
+
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
+}
+
+// Used during initialization
+void LilliputSound::init() {
+ debugC(1, kDebugSound, "LilliputSound::init()");
+
+ loadMusic("ROBIN.MUS");
+}
+
+void LilliputSound::refresh() {
+ debugC(1, kDebugSound, "LilliputSound::refresh()");
+}
+
+void LilliputSound::play(int var1, Common::Point var2, Common::Point var3, Common::Point var4) {
+ debugC(1, kDebugSound, "LilliputSound::play(%d, %d - %d, %d - %d, %d - %d)", var1, var2.x, var2.y, var3.x, var3.y, var4.x, var4.y);
+ // warning("LilliputSound::play(%d, %d - %d, %d - %d, %d - %d)", var1, var2.x, var2.y, var3.x, var3.y, var4.x, var4.y);
+
+ // save camera (var2)
+ if (_aliasArr[var1] == 0xFF) {
+ return;
+ }
+
+ if (var3 == Common::Point(-1, -1)) {
+ playMusic(var1);
+ } else if (_soundType[var1] == 0) {
+ warning("Transient");
+ } else {
+ warning("longterm");
+ }
+
+ return;
+}
+void LilliputSound::playMusic(int var1) {
+ int idx = _aliasArr[var1];
+ bool loop = _loopArr[var1];
+
+ _isGM = true;
+
+ if (_parser)
+ _parser->stopPlaying();
+
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_unpackedFiles[idx], _unpackedSizes[idx])) {
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(_driver->getBaseTempo());
+ parser->property(MidiParser::mpAutoLoop, loop);
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+
+ _parser = parser;
+
+ syncVolume();
+
+ _isLooping = loop;
+ _isPlaying = true;
+ }
+}
+
+void LilliputSound::stop(Common::Point pos) {
+ debugC(1, kDebugSound, "LilliputSound::stop(%d - %d)", pos.x, pos.y);
+ warning("LilliputSound::stop(%d - %d)", pos.x, pos.y);
+}
+
+void LilliputSound::toggleOnOff() {
+ debugC(1, kDebugSound, "LilliputSound::toggleOnOff()");
+ warning("LilliputSound::toggleOnOff()");
+}
+
+void LilliputSound::update() {
+ debugC(1, kDebugSound, "LilliputSound::update()");
+ warning("LilliputSound::update()");
+}
+
+void LilliputSound::remove() {
+ debugC(1, kDebugSound, "Lilliput::remove()");
+
+ _parser->stopPlaying();
+}
+
+} // End of namespace
diff --git a/engines/lilliput/sound.h b/engines/lilliput/sound.h
new file mode 100644
index 0000000000..f56fd58a6f
--- /dev/null
+++ b/engines/lilliput/sound.h
@@ -0,0 +1,71 @@
+/* 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 LILLIPUT_SOUND_H
+#define LILLIPUT_SOUND_H
+
+#include "audio/audiostream.h"
+#include "audio/decoders/wave.h"
+#include "audio/mididrv.h"
+#include "audio/midiparser.h"
+#include "audio/midiplayer.h"
+#include "audio/mixer.h"
+
+namespace Lilliput {
+
+class LilliputEngine;
+
+class LilliputSound: public Audio::MidiPlayer {
+public:
+ LilliputSound(LilliputEngine *vm);
+ ~LilliputSound();
+
+ void init();
+ void refresh();
+ void play(int var1, Common::Point var2, Common::Point var3, Common::Point var4);
+ void stop(Common::Point pos);
+ void toggleOnOff();
+ void update();
+ void remove();
+
+private:
+ LilliputEngine *_vm;
+
+ int _fileNumb;
+ byte **_unpackedFiles;
+ uint16 *_unpackedSizes;
+ bool _isGM;
+
+ uint32 decode(const byte *src, byte *dst, uint32 len, uint32 start);
+ byte readByte(const byte *data, uint32 offset);
+
+ void loadMusic(Common::String filename);
+ void playMusic(int var1);
+
+ virtual void send(uint32 b);
+ virtual void sendToChannel(byte channel, uint32 b);
+};
+
+} // End of namespace Lilliput
+
+#endif
+
diff --git a/engines/lilliput/stream.cpp b/engines/lilliput/stream.cpp
new file mode 100644
index 0000000000..6b33c9d357
--- /dev/null
+++ b/engines/lilliput/stream.cpp
@@ -0,0 +1,42 @@
+/* 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 "lilliput/stream.h"
+
+namespace Lilliput {
+
+ScriptStream::ScriptStream(byte *buf, int bufSize) : Common::MemoryReadStream(buf, bufSize) {
+ _orgPtr = buf;
+}
+
+ScriptStream::~ScriptStream() {
+}
+
+void ScriptStream::writeUint16LE(int value, int relativePos) {
+ int writePos = pos() + relativePos;
+ assert((writePos >= 0) && (writePos + 2 < size()));
+
+ Common::MemoryWriteStream tmpStream = Common::MemoryWriteStream(_orgPtr + writePos, size() - writePos);
+ tmpStream.writeUint16LE(value);
+}
+
+} // End of namespace Lilliput
diff --git a/engines/lilliput/stream.h b/engines/lilliput/stream.h
new file mode 100644
index 0000000000..52b80e3524
--- /dev/null
+++ b/engines/lilliput/stream.h
@@ -0,0 +1,42 @@
+/* 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 LILLIPUT_STREAM_H
+#define LILLIPUT_STREAM_H
+
+#include "common/memstream.h"
+
+namespace Lilliput {
+
+class ScriptStream : public Common::MemoryReadStream {
+private:
+ byte *_orgPtr;
+public:
+ ScriptStream(byte *buf, int bufSize);
+ virtual ~ScriptStream();
+
+ void writeUint16LE(int value, int relativePos = 0);
+};
+
+} // End of namespace Lilliput
+
+#endif
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 25d68c762d..5acd6d81a0 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -649,10 +649,7 @@ MidiMusic::~MidiMusic() {
}
void MidiMusic::setVolume(int volume) {
- if (volume < 0)
- volume = 0;
- else if (volume > 255)
- volume = 255;
+ volume = CLIP(volume, 0, 255);
if (_volume == volume)
return;
diff --git a/engines/macventure/detection.cpp b/engines/macventure/detection.cpp
index ba583ef743..5eda420cb2 100644
--- a/engines/macventure/detection.cpp
+++ b/engines/macventure/detection.cpp
@@ -54,7 +54,7 @@ static const PlainGameDescriptor macventureGames[] = {
namespace MacVenture {
-SaveStateDescriptor loadMetaData(Common::SeekableReadStream *s, int slot);
+SaveStateDescriptor loadMetaData(Common::SeekableReadStream *s, int slot, bool skipThumbnail = true);
class MacVentureMetaEngine : public AdvancedMetaEngine {
public:
@@ -63,18 +63,19 @@ public:
_md5Bytes = 5000000; // TODO: Upper limit, adjust it once all games are added
}
- virtual const char *getName() const override {
+ const char *getName() const {
return "MacVenture";
}
- virtual const char *getOriginalCopyright() const override {
+ const char *getOriginalCopyright() const {
return "(C) ICOM Simulations";
}
- 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;
+protected:
+ bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ bool hasFeature(MetaEngineFeature f) const;
+ SaveStateList listSaves(const char *target) const;
+ int getMaximumSaveSlot() const;
+ void removeSaveState(const char *target, int slot) const;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
};
@@ -163,7 +164,7 @@ SaveStateDescriptor MacVentureMetaEngine::querySaveMetaInfos(const char *target,
Common::InSaveFile *in = saveFileMan->openForLoading(saveFileName);
if (in) {
- desc = loadMetaData(in, slot);
+ desc = loadMetaData(in, slot, false);
delete in;
return desc;
}
diff --git a/engines/macventure/saveload.cpp b/engines/macventure/saveload.cpp
index 89a6301318..c63b6a6951 100644
--- a/engines/macventure/saveload.cpp
+++ b/engines/macventure/saveload.cpp
@@ -42,7 +42,7 @@ namespace MacVenture {
#define MACVENTURE_SAVE_VERSION 1 //1 BYTE
#define MACVENTURE_DESC_LENGTH 4 //4 BYTE for the metadata length
-SaveStateDescriptor loadMetaData(Common::SeekableReadStream *s, int slot) {
+SaveStateDescriptor loadMetaData(Common::SeekableReadStream *s, int slot, bool skipThumbnail) {
// Metadata is stored at the end of the file
// |THUMBNAIL |
// | |
@@ -65,8 +65,11 @@ SaveStateDescriptor loadMetaData(Common::SeekableReadStream *s, int slot) {
s->seek(-(5 + MACVENTURE_DESC_LENGTH + metaSize), SEEK_END);
// Load the thumbnail
- Graphics::Surface *thumb = Graphics::loadThumbnail(*s);
- desc.setThumbnail(thumb);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*s, thumbnail, skipThumbnail)) {
+ return desc;
+ }
+ desc.setThumbnail(thumbnail);
// Load the description
Common::String name;
diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
index 636c2d147c..bf05385c88 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -535,7 +535,7 @@ public:
virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
- const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
};
@@ -557,7 +557,7 @@ bool MadeMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGame
return gd != 0;
}
-const ADGameDescription *MadeMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ADDetectedGame MadeMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
// Set the default values for the fallback descriptor's ADGameDescription part.
Made::g_fallbackDesc.desc.language = Common::UNK_LANG;
Made::g_fallbackDesc.desc.platform = Common::kPlatformDOS;
@@ -569,7 +569,7 @@ const ADGameDescription *MadeMetaEngine::fallbackDetect(const FileMap &allFiles,
Made::g_fallbackDesc.version = 3;
//return (const ADGameDescription *)&Made::g_fallbackDesc;
- return NULL;
+ return ADDetectedGame();
}
#if PLUGIN_ENABLED_DYNAMIC(MADE)
diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp
index a9734ed47d..d8ceb87bb6 100644
--- a/engines/made/resource.cpp
+++ b/engines/made/resource.cpp
@@ -400,7 +400,8 @@ ResourceReader::~ResourceReader() {
// V2
void ResourceReader::open(const char *filename) {
_fd = new Common::File();
- _fd->open(filename);
+ if (!_fd->open(filename))
+ error("ResourceReader::open() Could not open '%s'", filename);
_fd->skip(0x18); // skip header for now
diff --git a/engines/mads/detection.cpp b/engines/mads/detection.cpp
index 4fb8b82eb3..8eb3b4eee9 100644
--- a/engines/mads/detection.cpp
+++ b/engines/mads/detection.cpp
@@ -203,11 +203,8 @@ SaveStateList MADSMetaEngine::listSaves(const char *target) const {
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
- MADS::Game::readSavegameHeader(in, header);
- saveList.push_back(SaveStateDescriptor(slot, header._saveName));
-
- header._thumbnail->free();
- delete header._thumbnail;
+ if (MADS::Game::readSavegameHeader(in, header))
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
delete in;
}
}
@@ -233,7 +230,10 @@ SaveStateDescriptor MADSMetaEngine::querySaveMetaInfos(const char *target, int s
if (f) {
MADS::MADSSavegameHeader header;
- MADS::Game::readSavegameHeader(f, header);
+ if (!MADS::Game::readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
delete f;
// Create the return descriptor
diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp
index 0a6741ba7a..bea0ea3bb4 100644
--- a/engines/mads/game.cpp
+++ b/engines/mads/game.cpp
@@ -485,11 +485,6 @@ void Game::loadGame(int slotNumber) {
if (!readSavegameHeader(_saveFile, header))
error("Invalid savegame");
- if (header._thumbnail) {
- header._thumbnail->free();
- delete header._thumbnail;
- }
-
// Load most of the savegame data with the exception of scene specific info
synchronize(s, true);
@@ -527,9 +522,8 @@ void Game::saveGame(int slotNumber, const Common::String &saveName) {
const char *const SAVEGAME_STR = "MADS";
#define SAVEGAME_STR_SIZE 4
-bool Game::readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header) {
+WARN_UNUSED_RESULT bool Game::readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
- header._thumbnail = nullptr;
// Validate the header Id
in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
@@ -546,9 +540,9 @@ bool Game::readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header
while ((ch = (char)in->readByte()) != '\0') header._saveName += ch;
// Get the thumbnail
- header._thumbnail = Graphics::loadThumbnail(*in);
- if (!header._thumbnail)
+ if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
header._year = in->readSint16LE();
diff --git a/engines/mads/game.h b/engines/mads/game.h
index 9defb58b1a..b979160f3d 100644
--- a/engines/mads/game.h
+++ b/engines/mads/game.h
@@ -237,7 +237,7 @@ public:
/**
* Read in a savegame header
*/
- static bool readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, MADSSavegameHeader &header, bool skipThumbnail = true);
/**
* Creates a temporary thumbnail for use in saving games
diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp
index 1db5eaea00..99402748b8 100644
--- a/engines/mads/nebular/game_nebular.cpp
+++ b/engines/mads/nebular/game_nebular.cpp
@@ -45,8 +45,9 @@ GameNebular::GameNebular(MADSEngine *vm)
}
ProtectionResult GameNebular::checkCopyProtection() {
- //if (!ConfMan.getBool("copy_protection"))
- // return PROTECTION_SUCCEED;
+ // Only show copy protection dialog if explicitly wanted
+ if (!ConfMan.getBool("copy_protection"))
+ return PROTECTION_SUCCEED;
CopyProtectionDialog *dlg;
bool correctAnswer;
diff --git a/engines/mads/nebular/nebular_scenes4.cpp b/engines/mads/nebular/nebular_scenes4.cpp
index a4c6a3ebe1..8b7eb1a9ec 100644
--- a/engines/mads/nebular/nebular_scenes4.cpp
+++ b/engines/mads/nebular/nebular_scenes4.cpp
@@ -2443,7 +2443,7 @@ void Scene405::step() {
}
if (_game._trigger == 70) {
- _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ;
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
_game._player._visible = true;
_globals._sequenceIndexes[1] = _scene->_sequences.addReverseSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
_scene->_sequences.addSubEntry(_globals._sequenceIndexes[1], SEQUENCE_TRIGGER_EXPIRE, 0, 71);
@@ -2458,7 +2458,7 @@ void Scene405::step() {
}
if (_game._trigger == 75) {
- _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount ;
+ _game._player._priorTimer = _scene->_frameStartTime + _game._player._ticksAmount;
_game._player._visible = true;
_scene->_sequences.remove(_globals._sequenceIndexes[1]);
_globals._sequenceIndexes[1] = _scene->_sequences.addSpriteCycle(_globals._spriteIndexes[1], false, 6, 1, 0, 0);
diff --git a/engines/metaengine.h b/engines/metaengine.h
index b3aaa96a8f..a95ff1593e 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -69,17 +69,17 @@ public:
virtual const char *getOriginalCopyright() const = 0;
/** Returns a list of games supported by this engine. */
- virtual GameList getSupportedGames() const = 0;
+ virtual PlainGameList getSupportedGames() const = 0;
- /** Query the engine for a GameDescriptor for the specified gameid, if any. */
- virtual GameDescriptor findGame(const char *gameid) const = 0;
+ /** Query the engine for a PlainGameDescriptor for the specified gameid, if any. */
+ virtual PlainGameDescriptor findGame(const char *gameId) const = 0;
/**
* Runs the engine's game detector on the given list of files, and returns a
* (possibly empty) list of games supported by the engine which it was able
* to detect amongst the given files.
*/
- virtual GameList detectGames(const Common::FSList &fslist) const = 0;
+ virtual DetectedGames detectGames(const Common::FSList &fslist) const = 0;
/**
* Tries to instantiate an engine instance based on the settings of
@@ -267,10 +267,17 @@ public:
*/
class EngineManager : public Common::Singleton<EngineManager> {
public:
- GameDescriptor findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin = NULL) const;
- GameDescriptor findGame(const Common::String &gameName, const Plugin **plugin = NULL) const;
- GameList detectGames(const Common::FSList &fslist) const;
+ PlainGameDescriptor findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin = NULL) const;
+ PlainGameDescriptor findGame(const Common::String &gameName, const Plugin **plugin = NULL) const;
+ DetectionResults detectGames(const Common::FSList &fslist) const;
const PluginList &getPlugins() const;
+
+ /**
+ * Create a target from the supplied game descriptor
+ *
+ * Returns the created target name.
+ */
+ Common::String createTargetForGame(const DetectedGame &game);
};
/** Convenience shortcut for accessing the engine manager. */
diff --git a/engines/mohawk/bitmap.cpp b/engines/mohawk/bitmap.cpp
index d8c6d6aacd..205feb824f 100644
--- a/engines/mohawk/bitmap.cpp
+++ b/engines/mohawk/bitmap.cpp
@@ -70,7 +70,7 @@ MohawkBitmap::~MohawkBitmap() {
void MohawkBitmap::decodeImageData(Common::SeekableReadStream *stream) {
_data = stream;
- _header.colorTable.palette = NULL;
+ _header.colorTable.palette = nullptr;
// NOTE: Only the bottom 12 bits of width/height/bytesPerRow are
// considered valid and bytesPerRow has to be an even number.
@@ -650,7 +650,7 @@ MohawkSurface *MystBitmap::decodeImage(Common::SeekableReadStream *stream) {
error("Could not decode Myst bitmap");
const Graphics::Surface *bmpSurface = bitmapDecoder.getSurface();
- Graphics::Surface *newSurface = 0;
+ Graphics::Surface *newSurface = nullptr;
if (bmpSurface->format.bytesPerPixel == 1) {
_bitsPerPixel = 8;
@@ -662,7 +662,7 @@ MohawkSurface *MystBitmap::decodeImage(Common::SeekableReadStream *stream) {
}
// Copy the palette to one of our own
- byte *newPal = 0;
+ byte *newPal = nullptr;
if (bitmapDecoder.hasPalette()) {
const byte *palette = bitmapDecoder.getPalette();
@@ -729,7 +729,7 @@ MohawkSurface *LivingBooksBitmap_v1::decodeImage(Common::SeekableReadStream *str
leRLE8 = true;
_data = stream;
- stream = NULL;
+ stream = nullptr;
}
Graphics::Surface *surface = createSurface(_header.width, _header.height);
diff --git a/engines/mohawk/bitmap.h b/engines/mohawk/bitmap.h
index ea8664f39d..18ea72b3ee 100644
--- a/engines/mohawk/bitmap.h
+++ b/engines/mohawk/bitmap.h
@@ -148,16 +148,16 @@ private:
// Mohawk Bitmap format.
class MystBitmap : public MohawkBitmap {
public:
- MystBitmap() : MohawkBitmap() {}
- ~MystBitmap() {}
+ MystBitmap() : MohawkBitmap(), _bitsPerPixel(8) {}
+ ~MystBitmap() override {}
- MohawkSurface *decodeImage(Common::SeekableReadStream *stream);
+ MohawkSurface *decodeImage(Common::SeekableReadStream *stream) override;
protected:
- byte getBitsPerPixel() { return _bitsPerPixel; }
+ byte getBitsPerPixel() override { return _bitsPerPixel; }
private:
- uint16 _bitsPerPixel;
+ byte _bitsPerPixel;
};
#endif
@@ -165,23 +165,23 @@ private:
class LivingBooksBitmap_v1 : public MohawkBitmap {
public:
LivingBooksBitmap_v1() : MohawkBitmap() {}
- ~LivingBooksBitmap_v1() {}
+ ~LivingBooksBitmap_v1() override {}
- MohawkSurface *decodeImage(Common::SeekableReadStream *stream);
+ MohawkSurface *decodeImage(Common::SeekableReadStream *stream) override;
protected:
- byte getBitsPerPixel() { return 8; }
+ byte getBitsPerPixel() override { return 8; }
};
class DOSBitmap : public MohawkBitmap {
public:
DOSBitmap() : MohawkBitmap() {}
- ~DOSBitmap() {}
+ ~DOSBitmap() override {}
- MohawkSurface *decodeImage(Common::SeekableReadStream *stream);
+ MohawkSurface *decodeImage(Common::SeekableReadStream *stream) override;
protected:
- byte getBitsPerPixel() { return ((_header.format & 0x30) >> 4) + 1; }
+ byte getBitsPerPixel() override { return ((_header.format & 0x30) >> 4) + 1; }
private:
void expandMonochromePlane(Graphics::Surface *surface, Common::SeekableReadStream *rawStream);
diff --git a/engines/mohawk/console.h b/engines/mohawk/console.h
index 0cae87da51..7d94bf576f 100644
--- a/engines/mohawk/console.h
+++ b/engines/mohawk/console.h
@@ -35,8 +35,8 @@ class MohawkEngine_Myst;
class MystConsole : public GUI::Debugger {
public:
- MystConsole(MohawkEngine_Myst *vm);
- virtual ~MystConsole(void);
+ explicit MystConsole(MohawkEngine_Myst *vm);
+ ~MystConsole() override;
private:
MohawkEngine_Myst *_vm;
@@ -66,8 +66,8 @@ class MohawkEngine_Riven;
class RivenConsole : public GUI::Debugger {
public:
- RivenConsole(MohawkEngine_Riven *vm);
- virtual ~RivenConsole(void);
+ explicit RivenConsole(MohawkEngine_Riven *vm);
+ ~RivenConsole() override;
private:
MohawkEngine_Riven *_vm;
@@ -95,8 +95,8 @@ private:
class LivingBooksConsole : public GUI::Debugger {
public:
- LivingBooksConsole(MohawkEngine_LivingBooks *vm);
- virtual ~LivingBooksConsole(void);
+ explicit LivingBooksConsole(MohawkEngine_LivingBooks *vm);
+ ~LivingBooksConsole() override;
private:
MohawkEngine_LivingBooks *_vm;
diff --git a/engines/mohawk/cstime.h b/engines/mohawk/cstime.h
index 1c39a86ca0..9edd185085 100644
--- a/engines/mohawk/cstime.h
+++ b/engines/mohawk/cstime.h
@@ -129,7 +129,7 @@ enum CSTimeState {
class MohawkEngine_CSTime : public MohawkEngine {
protected:
- Common::Error run();
+ Common::Error run() override;
public:
MohawkEngine_CSTime(OSystem *syst, const MohawkGameDescription *gamedesc);
@@ -142,7 +142,7 @@ public:
CSTimeGraphics *_gfx;
bool _needsUpdate;
- GUI::Debugger *getDebugger() { return _console; }
+ GUI::Debugger *getDebugger() override { return _console; }
CSTimeView *getView() { return _view; }
CSTimeCase *getCase() { return _case; }
CSTimeInterface *getInterface() { return _interface; }
diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp
index cef24e14e5..84b1c73e04 100644
--- a/engines/mohawk/cursors.cpp
+++ b/engines/mohawk/cursors.cpp
@@ -151,7 +151,7 @@ NECursorManager::NECursorManager(const Common::String &appName) {
if (!_exe->loadFromEXE(appName)) {
// Not all have cursors anyway, so this is not a problem
delete _exe;
- _exe = 0;
+ _exe = nullptr;
}
}
@@ -183,10 +183,10 @@ MacCursorManager::MacCursorManager(const Common::String &appName) {
if (!_resFork->open(appName)) {
// Not all have cursors anyway, so this is not a problem
delete _resFork;
- _resFork = 0;
+ _resFork = nullptr;
}
} else {
- _resFork = 0;
+ _resFork = nullptr;
}
}
@@ -219,7 +219,7 @@ LivingBooksCursorManager_v2::LivingBooksCursorManager_v2() {
if (!_sysArchive->openFile("system.mhk")) {
delete _sysArchive;
- _sysArchive = 0;
+ _sysArchive = nullptr;
}
}
diff --git a/engines/mohawk/cursors.h b/engines/mohawk/cursors.h
index d0d38c9b46..ff5db5b59c 100644
--- a/engines/mohawk/cursors.h
+++ b/engines/mohawk/cursors.h
@@ -72,11 +72,11 @@ protected:
// Uses standard tCUR resources
class DefaultCursorManager : public CursorManager {
public:
- DefaultCursorManager(MohawkEngine *vm, uint32 tag = ID_TCUR) : _vm(vm), _tag(tag) {}
- ~DefaultCursorManager() {}
+ explicit DefaultCursorManager(MohawkEngine *vm, uint32 tag = ID_TCUR) : _vm(vm), _tag(tag) {}
+ ~DefaultCursorManager() override {}
- void setCursor(uint16 id);
- bool hasSource() const { return true; }
+ void setCursor(uint16 id) override;
+ bool hasSource() const override { return true; }
private:
MohawkEngine *_vm;
@@ -110,14 +110,14 @@ class MohawkEngine_Myst;
// Uses WDIB + CLRC resources
class MystCursorManager : public CursorManager {
public:
- MystCursorManager(MohawkEngine_Myst *vm);
- ~MystCursorManager();
+ explicit MystCursorManager(MohawkEngine_Myst *vm);
+ ~MystCursorManager() override;
- void showCursor();
- void hideCursor();
- void setCursor(uint16 id);
- void setDefaultCursor();
- bool hasSource() const { return true; }
+ void showCursor() override;
+ void hideCursor() override;
+ void setCursor(uint16 id) override;
+ void setDefaultCursor() override;
+ bool hasSource() const override { return true; }
private:
MohawkEngine_Myst *_vm;
@@ -128,11 +128,11 @@ private:
// The cursor manager for NE EXE's
class NECursorManager : public CursorManager {
public:
- NECursorManager(const Common::String &appName);
- ~NECursorManager();
+ explicit NECursorManager(const Common::String &appName);
+ ~NECursorManager() override;
- void setCursor(uint16 id);
- bool hasSource() const { return _exe != 0; }
+ void setCursor(uint16 id) override;
+ bool hasSource() const override { return _exe != nullptr; }
private:
Common::NEResources *_exe;
@@ -141,11 +141,11 @@ private:
// The cursor manager for Mac applications
class MacCursorManager : public CursorManager {
public:
- MacCursorManager(const Common::String &appName);
- ~MacCursorManager();
+ explicit MacCursorManager(const Common::String &appName);
+ ~MacCursorManager() override;
- void setCursor(uint16 id);
- bool hasSource() const { return _resFork != 0; }
+ void setCursor(uint16 id) override;
+ bool hasSource() const override { return _resFork != nullptr; }
private:
Common::MacResManager *_resFork;
@@ -156,11 +156,11 @@ private:
class LivingBooksCursorManager_v2 : public CursorManager {
public:
LivingBooksCursorManager_v2();
- ~LivingBooksCursorManager_v2();
+ ~LivingBooksCursorManager_v2() override;
- void setCursor(uint16 id);
- void setCursor(const Common::String &name);
- bool hasSource() const { return _sysArchive != 0; }
+ void setCursor(uint16 id) override;
+ void setCursor(const Common::String &name) override;
+ bool hasSource() const override { return _sysArchive != nullptr; }
private:
MohawkArchive *_sysArchive;
@@ -169,11 +169,11 @@ private:
// The cursor manager for PE EXE's
class PECursorManager : public CursorManager {
public:
- PECursorManager(const Common::String &appName);
- ~PECursorManager();
+ explicit PECursorManager(const Common::String &appName);
+ ~PECursorManager() override;
- void setCursor(uint16 id);
- bool hasSource() const { return !_cursors.empty(); }
+ void setCursor(uint16 id) override;
+ bool hasSource() const override { return !_cursors.empty(); }
private:
struct CursorItem {
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index 439ea152c4..58d1483bee 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -116,19 +116,12 @@ static const PlainGameDescriptor mohawkGames[] = {
{"myst", "Myst"},
{"makingofmyst", "The Making of Myst"},
{"riven", "Riven: The Sequel to Myst"},
- {"zoombini", "Logical Journey of the Zoombinis"},
{"cstime", "Where in Time is Carmen Sandiego?"},
- {"csworld", "Where in the World is Carmen Sandiego?"},
- {"csamtrak", "Where in America is Carmen Sandiego? (The Great Amtrak Train Adventure)"},
{"carmentq", "Carmen Sandiego's ThinkQuick Challenge"},
{"carmentqc", "Carmen Sandiego's ThinkQuick Challenge Custom Question Creator"},
{"maggiesfa", "Maggie's Farmyard Adventure"},
- {"jamesmath", "James Discovers/Explores Math"},
- {"treehouse", "The Treehouse"},
{"greeneggs", "Green Eggs and Ham"},
{"seussabc", "Dr Seuss's ABC"},
- {"1stdegree", "In the 1st Degree"},
- {"csusa", "Where in the USA is Carmen Sandiego?"},
{"tortoise", "Aesop's Fables: The Tortoise and the Hare"},
{"arthur", "Arthur's Teacher Trouble"},
{"grandma", "Just Grandma and Me"},
@@ -147,7 +140,7 @@ static const PlainGameDescriptor mohawkGames[] = {
{"stellaluna", "Stellaluna"},
{"sheila", "Sheila Rae, the Brave"},
{"rugratsps", "Rugrats Print Shop" },
- {0, 0}
+ {nullptr, nullptr}
};
#include "mohawk/detection_tables.h"
@@ -159,7 +152,7 @@ static const char *directoryGlobs[] = {
"program",
"95instal",
"Rugrats Adventure Game",
- 0
+ nullptr
};
static const ADExtraGuiOptionsMap optionsList[] = {
@@ -184,25 +177,25 @@ public:
_directoryGlobs = directoryGlobs;
}
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override {
return detectGameFilebased(allFiles, fslist, Mohawk::fileBased);
}
- virtual const char *getName() const {
+ const char *getName() const override {
return "Mohawk";
}
- virtual const char *getOriginalCopyright() const {
+ const char *getOriginalCopyright() const override {
return "Myst and Riven (C) Cyan Worlds\nMohawk OS (C) Ubisoft";
}
- virtual bool hasFeature(MetaEngineFeature f) const;
- virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
- virtual SaveStateList listSaves(const char *target) const;
+ bool hasFeature(MetaEngineFeature f) const override;
+ bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
+ SaveStateList listSaves(const char *target) const override;
SaveStateList listSavesForPrefix(const char *prefix, const char *extension) 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;
+ int getMaximumSaveSlot() const override { return 999; }
+ void removeSaveState(const char *target, int slot) const override;
+ SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
};
bool MohawkMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -340,21 +333,12 @@ bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa
warning("CSTime support not compiled in");
return false;
#endif
- case Mohawk::GType_ZOOMBINI:
- case Mohawk::GType_CSWORLD:
- case Mohawk::GType_CSAMTRAK:
- case Mohawk::GType_JAMESMATH:
- case Mohawk::GType_TREEHOUSE:
- case Mohawk::GType_1STDEGREE:
- case Mohawk::GType_CSUSA:
- warning("Unsupported Mohawk Engine");
- return false;
default:
error("Unknown Mohawk Engine");
}
}
- return (gd != 0);
+ return (gd != nullptr);
}
#if PLUGIN_ENABLED_DYNAMIC(MOHAWK)
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
index a06b814fbd..e887c11051 100644
--- a/engines/mohawk/detection_tables.h
+++ b/engines/mohawk/detection_tables.h
@@ -500,6 +500,24 @@ static const MohawkGameDescription gameDescriptions[] = {
},
// Riven: The Sequel to Myst
+ // Version 1.1 (DVD, Pressing code rvd 2811 ab, RVD8AB-BI RVD2811AB)
+ // From wouwehand in #10519
+ {
+ {
+ "riven",
+ "DVD",
+ AD_ENTRY1("a_Data.MHK", "3370cd9a9696814365a2b7fd7a7b726e"),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUI_OPTIONS_RIVEN
+ },
+ GType_RIVEN,
+ GF_DVD,
+ 0,
+ },
+
+ // Riven: The Sequel to Myst
// Version 1.0 (DVD, From "Myst: Die Trilogie")
// From DrMcCoy
{
@@ -600,127 +618,6 @@ static const MohawkGameDescription gameDescriptions[] = {
0
},
-
- {
- {
- "zoombini",
- "",
- AD_ENTRY1("ZOOMBINI.MHK", "98b758fec55104c096cfd129048be9a6"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_ZOOMBINI,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "zoombini",
- "",
- AD_ENTRY1("ZOOMBINI.MHK", "0672f65c40dd065840c896e41c13f980"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_ZOOMBINI,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "zoombini",
- "v2.0",
- AD_ENTRY1("ZOOMBINI.MHK", "506b1122ffa740e2566cf0b583d24478"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_NO_FLAGS,
- GUIO1(GUIO_NOASPECT)
- },
- GType_ZOOMBINI,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "zoombini",
- "",
- AD_ENTRY1("ZOOMBINI.MHK", "6ae0bdf791266b1fe3d4fabbf44c3faa"),
- Common::DE_DEU,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_ZOOMBINI,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "zoombini",
- "",
- AD_ENTRY1("ZOOMBINI.MHK", "8231e58525143ccf6e8b747df34b139f"),
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_ZOOMBINI,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "csworld",
- "v3.0",
- AD_ENTRY1("C2K.MHK", "605fe88380848031bbd0ff84ade6fe40"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_CSWORLD,
- 0,
- 0
- },
-
- {
- {
- "csworld",
- "v3.5",
- AD_ENTRY1("C2K.MHK", "d4857aeb0f5e2e0c4ac556aa74f38c23"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_CSWORLD,
- 0,
- 0
- },
-
- {
- {
- "csamtrak",
- "",
- AD_ENTRY1("AMTRAK.MHK", "2f95301f0bb950d555bb7b0e3b1b7eb1"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_CSAMTRAK,
- 0,
- 0
- },
-
// Harry and the Haunted House v1.0E
// English Windows 3.11
// From strangerke
@@ -935,52 +832,6 @@ static const MohawkGameDescription gameDescriptions[] = {
{
{
- "jamesmath",
- "",
- AD_ENTRY1("BRODER.MHK", "007299da8b2c6e8ec1cde9598c243024"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_JAMESMATH,
- GF_HASMIDI,
- 0
- },
-
- // This is in the NEWDATA folder, so I assume it's a newer version ;)
- {
- {
- "jamesmath",
- "",
- AD_ENTRY1("BRODER.MHK", "53c000938a50dca92860fd9b546dd276"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_JAMESMATH,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "treehouse",
- "",
- AD_ENTRY1("MAINROOM.MHK", "12f51894d7f838af639ea9bf1bc8f45b"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_TREEHOUSE,
- GF_HASMIDI,
- 0
- },
-
- {
- {
"greeneggs",
"",
AD_ENTRY1("GREEN.LB", "5df8438138186f89e71299d7b4f88d06"),
@@ -1088,54 +939,6 @@ static const MohawkGameDescription gameDescriptions[] = {
{
{
- "1stdegree",
- "",
- AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_1STDEGREE,
- GF_HASMIDI,
- 0
- },
-
- // In The 1st Degree
- // French Windows
- // From Strangerke
- {
- {
- "1stdegree",
- "",
- AD_ENTRY1("AL236_1.MHK", "0e0c70b1b702b6ddca61a1192ada1282"),
- Common::FR_FRA,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_1STDEGREE,
- GF_HASMIDI,
- 0
- },
-
- {
- {
- "csusa",
- "",
- AD_ENTRY1("USAC2K.MHK", "b8c9d3a2586f62bce3a48b50d7a700e9"),
- Common::EN_ANY,
- Common::kPlatformWindows,
- ADGF_UNSTABLE,
- GUIO1(GUIO_NOASPECT)
- },
- GType_CSUSA,
- 0,
- 0
- },
-
- {
- {
"tortoise",
"",
AD_ENTRY1("TORTOISE.512", "dfcf7bff3d0f187832c9897497efde0e"),
diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp
index 029867f6a6..5700a4641b 100644
--- a/engines/mohawk/dialogs.cpp
+++ b/engines/mohawk/dialogs.cpp
@@ -180,22 +180,22 @@ void MohawkOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd,
MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : MohawkOptionsDialog(vm), _vm(vm) {
// I18N: Option for fast scene switching
- _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);
+ _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 220, 15, _("~Z~ip Mode Activated"), nullptr, kZipCmd);
+ _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 220, 15, _("~T~ransitions Enabled"), nullptr, kTransCmd);
// I18N: Drop book page
- _dropPageButton = new GUI::ButtonWidget(this, 15, 60, 100, 25, _("~D~rop Page"), 0, kDropCmd);
+ _dropPageButton = new GUI::ButtonWidget(this, 15, 60, 100, 25, _("~D~rop Page"), nullptr, kDropCmd);
// Myst ME only has maps
if (_vm->getFeatures() & GF_ME)
- _showMapButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("Show ~M~ap"), 0, kMapCmd);
+ _showMapButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("Show ~M~ap"), nullptr, kMapCmd);
else
- _showMapButton = 0;
+ _showMapButton = nullptr;
// Myst demo only has a menu
if (_vm->getFeatures() & GF_DEMO)
- _returnToMenuButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("Main Men~u~"), 0, kMenuCmd);
+ _returnToMenuButton = new GUI::ButtonWidget(this, 15, 95, 100, 25, _("Main Men~u~"), nullptr, kMenuCmd);
else
- _returnToMenuButton = 0;
+ _returnToMenuButton = nullptr;
}
MystOptionsDialog::~MystOptionsDialog() {
@@ -204,16 +204,19 @@ MystOptionsDialog::~MystOptionsDialog() {
void MystOptionsDialog::open() {
MohawkOptionsDialog::open();
- _dropPageButton->setEnabled(_vm->_gameState->_globals.heldPage != 0);
+ bool canDropPage = _vm->isInteractive() && _vm->_gameState->_globals.heldPage != kNoPage;
+ _dropPageButton->setEnabled(canDropPage);
- if (_showMapButton)
- _showMapButton->setEnabled(_vm->_scriptParser &&
- _vm->_scriptParser->getMap());
+ if (_showMapButton) {
+ bool canShowMap = _vm->isInteractive() && _vm->_scriptParser->getMap();
+ _showMapButton->setEnabled(canShowMap);
+ }
- // Return to menu button is not enabled on the menu
- if (_returnToMenuButton)
- _returnToMenuButton->setEnabled(_vm->_scriptParser &&
- _vm->getCurStack() != kDemoStack);
+ if (_returnToMenuButton) {
+ // Return to menu button is not enabled on the menu
+ bool canReturnToMenu = _vm->isInteractive() && _vm->getCurStack() != kDemoStack;
+ _returnToMenuButton->setEnabled(canReturnToMenu);
+ }
// Zip mode is disabled in the demo
if (_vm->getFeatures() & GF_DEMO)
@@ -266,8 +269,8 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui
RivenOptionsDialog::RivenOptionsDialog(MohawkEngine_Riven* vm) :
MohawkOptionsDialog(vm),
_vm(vm) {
- _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 220, 15, _("~Z~ip Mode Activated"), 0, kZipCmd);
- _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 220, 15, _("~W~ater Effect Enabled"), 0, kWaterCmd);
+ _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 220, 15, _("~Z~ip Mode Activated"), nullptr, kZipCmd);
+ _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 220, 15, _("~W~ater Effect Enabled"), nullptr, kWaterCmd);
_transitionModeCaption = new GUI::StaticTextWidget(this, 15, 50, 90, 20, _("Transitions:"), Graphics::kTextAlignRight);
_transitionModePopUp = new GUI::PopUpWidget(this, 115, 50, 120, 20);
diff --git a/engines/mohawk/dialogs.h b/engines/mohawk/dialogs.h
index efc1005737..9e892d768d 100644
--- a/engines/mohawk/dialogs.h
+++ b/engines/mohawk/dialogs.h
@@ -53,35 +53,35 @@ public:
void setInfoText(const Common::String &message);
- virtual void handleMouseDown(int x, int y, int button, int clickCount) {
+ void handleMouseDown(int x, int y, int button, int clickCount) override {
setResult(0);
close();
}
- virtual void handleKeyDown(Common::KeyState state) {
+ void handleKeyDown(Common::KeyState state) override {
setResult(state.ascii);
close();
}
- virtual void reflowLayout();
+ void reflowLayout() override;
};
class PauseDialog : public InfoDialog {
public:
PauseDialog(MohawkEngine* vm, const Common::String &message);
- virtual void handleKeyDown(Common::KeyState state);
+ void handleKeyDown(Common::KeyState state) override;
};
#if defined(ENABLE_MYST) || defined(ENABLE_RIVEN)
class MohawkOptionsDialog : public GUI::Dialog {
public:
- MohawkOptionsDialog(MohawkEngine *_vm);
- virtual ~MohawkOptionsDialog();
+ explicit MohawkOptionsDialog(MohawkEngine *_vm);
+ ~MohawkOptionsDialog() override;
- virtual void open() override;
- virtual void reflowLayout() override;
- virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
+ void open() override;
+ void reflowLayout() override;
+ void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
int getLoadSlot() const { return _loadSlot; }
int getSaveSlot() const { return _saveSlot; }
@@ -112,11 +112,11 @@ class MohawkEngine_Myst;
class MystOptionsDialog : public MohawkOptionsDialog {
public:
- MystOptionsDialog(MohawkEngine_Myst *vm);
- virtual ~MystOptionsDialog();
+ explicit MystOptionsDialog(MohawkEngine_Myst *vm);
+ ~MystOptionsDialog() override;
- virtual void open() override;
- virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ void open() override;
+ void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
private:
MohawkEngine_Myst *_vm;
@@ -137,11 +137,11 @@ class MohawkEngine_Riven;
class RivenOptionsDialog : public MohawkOptionsDialog {
public:
- RivenOptionsDialog(MohawkEngine_Riven *vm);
- virtual ~RivenOptionsDialog();
+ explicit RivenOptionsDialog(MohawkEngine_Riven *vm);
+ ~RivenOptionsDialog() override;
- virtual void open() override;
- virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
+ void open() override;
+ void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
private:
MohawkEngine_Riven *_vm;
diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp
index ea9b57ae17..fe675235c1 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -30,7 +30,7 @@
namespace Mohawk {
-MohawkSurface::MohawkSurface() : _surface(0), _palette(0) {
+MohawkSurface::MohawkSurface() : _surface(nullptr), _palette(nullptr) {
_offsetX = 0;
_offsetY = 0;
}
@@ -64,7 +64,7 @@ void MohawkSurface::convertToTrueColor() {
_surface->free();
delete _surface;
free(_palette);
- _palette = 0;
+ _palette = nullptr;
_surface = surface;
}
diff --git a/engines/mohawk/graphics.h b/engines/mohawk/graphics.h
index f9fdeea15f..797fc1c080 100644
--- a/engines/mohawk/graphics.h
+++ b/engines/mohawk/graphics.h
@@ -41,7 +41,7 @@ class MohawkBitmap;
class MohawkSurface {
public:
MohawkSurface();
- MohawkSurface(Graphics::Surface *surface, byte *palette = NULL, int offsetX = 0, int offsetY = 0);
+ explicit MohawkSurface(Graphics::Surface *surface, byte *palette = nullptr, int offsetX = 0, int offsetY = 0);
~MohawkSurface();
// getSurface() returns the surface in the current format
diff --git a/engines/mohawk/installer_archive.cpp b/engines/mohawk/installer_archive.cpp
index 0abc930683..62fc953f53 100644
--- a/engines/mohawk/installer_archive.cpp
+++ b/engines/mohawk/installer_archive.cpp
@@ -28,7 +28,7 @@
namespace Mohawk {
InstallerArchive::InstallerArchive() : Common::Archive() {
- _stream = 0;
+ _stream = nullptr;
}
InstallerArchive::~InstallerArchive() {
@@ -103,7 +103,7 @@ bool InstallerArchive::open(const Common::String &filename) {
}
void InstallerArchive::close() {
- delete _stream; _stream = 0;
+ delete _stream; _stream = nullptr;
_map.clear();
}
@@ -124,7 +124,7 @@ const Common::ArchiveMemberPtr InstallerArchive::getMember(const Common::String
Common::SeekableReadStream *InstallerArchive::createReadStreamForMember(const Common::String &name) const {
if (!_stream || !_map.contains(name))
- return 0;
+ return nullptr;
const FileEntry &entry = _map[name];
diff --git a/engines/mohawk/installer_archive.h b/engines/mohawk/installer_archive.h
index c3212d7f7c..19f6343b80 100644
--- a/engines/mohawk/installer_archive.h
+++ b/engines/mohawk/installer_archive.h
@@ -36,17 +36,17 @@ namespace Mohawk {
class InstallerArchive : public Common::Archive {
public:
InstallerArchive();
- ~InstallerArchive();
+ ~InstallerArchive() override;
bool open(const Common::String &filename);
void close();
- bool isOpen() const { return _stream != 0; }
+ bool isOpen() const { return _stream != nullptr; }
// Common::Archive API implementation
- bool hasFile(const Common::String &name) const;
- int listMembers(Common::ArchiveMemberList &list) const;
- const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
- Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+ bool hasFile(const Common::String &name) const override;
+ int listMembers(Common::ArchiveMemberList &list) const override;
+ const Common::ArchiveMemberPtr getMember(const Common::String &name) const override;
+ Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const override;
private:
struct FileEntry {
diff --git a/engines/mohawk/livingbooks.cpp b/engines/mohawk/livingbooks.cpp
index 95b4722d81..b9e54e4e20 100644
--- a/engines/mohawk/livingbooks.cpp
+++ b/engines/mohawk/livingbooks.cpp
@@ -837,6 +837,7 @@ void LBPage::loadBITL(uint16 resourceId) {
break;
default:
warning("Unknown item type %04x", type);
+ // fall through
case 3: // often used for buttons
res = new LBItem(_vm, this, rect);
break;
diff --git a/engines/mohawk/livingbooks.h b/engines/mohawk/livingbooks.h
index 4b87b6464f..4649b9f5c9 100644
--- a/engines/mohawk/livingbooks.h
+++ b/engines/mohawk/livingbooks.h
@@ -707,7 +707,7 @@ protected:
class MohawkEngine_LivingBooks : public MohawkEngine {
protected:
- Common::Error run();
+ Common::Error run() override;
public:
MohawkEngine_LivingBooks(OSystem *syst, const MohawkGameDescription *gamedesc);
@@ -725,7 +725,7 @@ public:
Common::SeekableSubReadStreamEndian *wrapStreamEndian(uint32 tag, uint16 id);
Common::String readString(Common::ReadStream *stream);
Common::Rect readRect(Common::ReadStreamEndian *stream);
- GUI::Debugger *getDebugger() { return _console; }
+ GUI::Debugger *getDebugger() override { return _console; }
void addArchive(Archive *archive);
void removeArchive(Archive *archive);
diff --git a/engines/mohawk/livingbooks_code.cpp b/engines/mohawk/livingbooks_code.cpp
index b5ea547414..7eb5a0cc3a 100644
--- a/engines/mohawk/livingbooks_code.cpp
+++ b/engines/mohawk/livingbooks_code.cpp
@@ -1349,14 +1349,17 @@ void LBCode::cmdSetPlayParams(const Common::Array<LBValue> &params) {
switch (params.size()) {
case 8:
target->_soundMode = params[7].integer;
+ // fall through
case 7:
target->_controlMode = params[6].integer;
+ // fall through
case 6:
// TODO: _relocPoint?
case 5:
// TODO: _periodMin/Max
case 4:
target->_timingMode = params[3].integer;
+ // fall through
case 3:
// TODO: _delayMin/Max
case 2:
diff --git a/engines/mohawk/mohawk.cpp b/engines/mohawk/mohawk.cpp
index 53481af8a7..52f73dbbb1 100644
--- a/engines/mohawk/mohawk.cpp
+++ b/engines/mohawk/mohawk.cpp
@@ -41,8 +41,8 @@ MohawkEngine::MohawkEngine(OSystem *syst, const MohawkGameDescription *gamedesc)
// Setup mixer
syncSoundSettings();
- _pauseDialog = 0;
- _cursor = 0;
+ _pauseDialog = nullptr;
+ _cursor = nullptr;
}
MohawkEngine::~MohawkEngine() {
@@ -70,7 +70,6 @@ Common::SeekableReadStream *MohawkEngine::getResource(uint32 tag, uint16 id) {
return _mhk[i]->getResource(tag, id);
error("Could not find a '%s' resource with ID %04x", tag2str(tag), id);
- return NULL;
}
bool MohawkEngine::hasResource(uint32 tag, uint16 id) {
@@ -95,7 +94,6 @@ uint32 MohawkEngine::getResourceOffset(uint32 tag, uint16 id) {
return _mhk[i]->getOffset(tag, id);
error("Could not find a '%s' resource with ID %04x", tag2str(tag), id);
- return 0;
}
uint16 MohawkEngine::findResourceID(uint32 tag, const Common::String &resName) {
@@ -104,7 +102,6 @@ uint16 MohawkEngine::findResourceID(uint32 tag, const Common::String &resName) {
return _mhk[i]->findResourceID(tag, resName);
error("Could not find a '%s' resource matching name '%s'", tag2str(tag), resName.c_str());
- return 0xFFFF;
}
Common::String MohawkEngine::getResourceName(uint32 tag, uint16 id) {
@@ -114,7 +111,6 @@ Common::String MohawkEngine::getResourceName(uint32 tag, uint16 id) {
}
error("Could not find a \'%s\' resource with ID %04x", tag2str(tag), id);
- return 0;
}
} // End of namespace Mohawk
diff --git a/engines/mohawk/mohawk.h b/engines/mohawk/mohawk.h
index c6781ae448..8184f46bad 100644
--- a/engines/mohawk/mohawk.h
+++ b/engines/mohawk/mohawk.h
@@ -49,14 +49,7 @@ enum MohawkGameType {
GType_MYST,
GType_MAKINGOF,
GType_RIVEN,
- GType_ZOOMBINI,
GType_CSTIME,
- GType_CSWORLD,
- GType_CSAMTRAK,
- GType_JAMESMATH,
- GType_TREEHOUSE,
- GType_1STDEGREE,
- GType_CSUSA,
GType_LIVINGBOOKSV1,
GType_LIVINGBOOKSV2,
GType_LIVINGBOOKSV3,
@@ -68,8 +61,7 @@ enum MohawkGameFeatures {
GF_ME = (1 << 0), // Myst Masterpiece Edition
GF_DVD = (1 << 1),
GF_DEMO = (1 << 2),
- GF_HASMIDI = (1 << 3),
- GF_LB_10 = (1 << 4) // very early Living Books 1.0 games
+ GF_LB_10 = (1 << 3) // very early Living Books 1.0 games
};
struct MohawkGameDescription;
@@ -80,23 +72,22 @@ class CursorManager;
class MohawkEngine : public ::Engine {
protected:
- virtual Common::Error run();
+ Common::Error run() override;
public:
MohawkEngine(OSystem *syst, const MohawkGameDescription *gamedesc);
- virtual ~MohawkEngine();
+ ~MohawkEngine() override;
// Detection related functions
const MohawkGameDescription *_gameDescription;
const char *getGameId() const;
uint32 getFeatures() const;
const char *getAppName() const;
- uint16 getVersion() const;
Common::Platform getPlatform() const;
uint8 getGameType() const;
Common::Language getLanguage() const;
- bool hasFeature(EngineFeature f) const;
+ bool hasFeature(EngineFeature f) const override;
CursorManager *_cursor;
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index 5baa89cea8..a01cfdd343 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -54,7 +54,8 @@
namespace Mohawk {
-MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) {
+MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription *gamedesc) :
+ MohawkEngine(syst, gamedesc) {
DebugMan.addDebugChannel(kDebugVariable, "Variable", "Track Variable Accesses");
DebugMan.addDebugChannel(kDebugSaveLoad, "SaveLoad", "Track Save/Load Function");
DebugMan.addDebugChannel(kDebugView, "View", "Track Card File (VIEW) Parsing");
@@ -69,7 +70,9 @@ MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription
_currentCursor = 0;
_mainCursor = kDefaultMystCursor;
_showResourceRects = false;
+ _curStack = 0;
_curCard = 0;
+ _lastSaveTime = 0;
_hoverResource = nullptr;
_activeResource = nullptr;
@@ -82,13 +85,20 @@ MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription
_scriptParser = nullptr;
_gameState = nullptr;
_optionsDialog = nullptr;
+ _rnd = nullptr;
_prevStack = nullptr;
_mouseClicked = false;
_mouseMoved = false;
_escapePressed = false;
- _interactive = true;
+ _waitingOnBlockingOperation = false;
+ _runExitScript = true;
+
+ _needsPageDrop = false;
+ _needsShowCredits = false;
+ _needsShowDemoMenu = false;
+ _needsShowMap = false;
}
MohawkEngine_Myst::~MohawkEngine_Myst() {
@@ -253,8 +263,40 @@ void MohawkEngine_Myst::playMovieBlocking(const Common::String &name, MystStack
waitUntilMovieEnds(video);
}
-void MohawkEngine_Myst::playFlybyMovie(const Common::String &name) {
- Common::String filename = wrapMovieFilename(name, kMasterpieceOnly);
+void MohawkEngine_Myst::playFlybyMovie(uint16 stack, uint16 card) {
+ static const uint16 kMasterpieceOnly = 0xFFFF;
+
+ // Play Flyby Entry Movie on Masterpiece Edition.
+ const char *flyby = nullptr;
+
+ switch (stack) {
+ case kSeleniticStack:
+ flyby = "selenitic flyby";
+ break;
+ case kStoneshipStack:
+ 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 (ConfMan.getBool("playmystflyby"))
+ flyby = "myst flyby";
+ break;
+ case kMechanicalStack:
+ flyby = "mech age flyby";
+ break;
+ case kChannelwoodStack:
+ flyby = "channelwood flyby";
+ break;
+ default:
+ break;
+ }
+
+ if (!flyby) {
+ return;
+ }
+
+ Common::String filename = wrapMovieFilename(flyby, kMasterpieceOnly);
VideoEntryPtr video = _video->playMovie(filename, Audio::Mixer::kSFXSoundType);
if (!video) {
error("Failed to open the '%s' movie", filename.c_str());
@@ -271,7 +313,7 @@ void MohawkEngine_Myst::waitUntilMovieEnds(const VideoEntryPtr &video) {
if (!video)
return;
- _interactive = false;
+ _waitingOnBlockingOperation = true;
// Sanity check
if (video->isLooping())
@@ -289,17 +331,17 @@ void MohawkEngine_Myst::waitUntilMovieEnds(const VideoEntryPtr &video) {
// Ensure it's removed
_video->removeEntry(video);
- _interactive = true;
+ _waitingOnBlockingOperation = false;
}
void MohawkEngine_Myst::playSoundBlocking(uint16 id) {
- _interactive = false;
+ _waitingOnBlockingOperation = true;
_sound->playEffect(id);
while (_sound->isEffectPlaying() && !shouldQuit()) {
doFrame();
}
- _interactive = true;
+ _waitingOnBlockingOperation = false;
}
Common::Error MohawkEngine_Myst::run() {
@@ -340,9 +382,6 @@ Common::Error MohawkEngine_Myst::run() {
_mhk.push_back(mhk);
}
- // Test Load Function...
- loadHelp(10000);
-
while (!shouldQuit()) {
doFrame();
}
@@ -353,10 +392,14 @@ Common::Error MohawkEngine_Myst::run() {
void MohawkEngine_Myst::doFrame() {
// Update any background videos
_video->updateMovies();
- if (!_scriptParser->isScriptRunning() && _interactive) {
- _interactive = false;
+ if (isInteractive()) {
+ _waitingOnBlockingOperation = true;
_scriptParser->runPersistentScripts();
- _interactive = true;
+ _waitingOnBlockingOperation = false;
+ }
+
+ if (shouldPerformAutoSave(_lastSaveTime)) {
+ tryAutoSaving();
}
Common::Event event;
@@ -410,9 +453,19 @@ void MohawkEngine_Myst::doFrame() {
}
if (_needsShowCredits) {
- _cursor->hideCursor();
- changeToStack(kCreditsStack, 10000, 0, 0);
- _needsShowCredits = false;
+ if (isInteractive()) {
+ // Attempt to autosave before exiting
+ tryAutoSaving();
+
+ _cursor->hideCursor();
+ changeToStack(kCreditsStack, 10000, 0, 0);
+ _needsShowCredits = false;
+ } else {
+ // Showing the credits in the middle of a script is not possible
+ // because it unloads the previous age, removing data needed by the
+ // rest of the script. Instead we just quit without showing the credits.
+ quitGame();
+ }
}
break;
case Common::KEYCODE_ESCAPE:
@@ -431,12 +484,17 @@ void MohawkEngine_Myst::doFrame() {
break;
}
break;
+ case Common::EVENT_QUIT:
+ case Common::EVENT_RTL:
+ // Attempt to autosave before exiting
+ tryAutoSaving();
+ break;
default:
break;
}
}
- if (!_scriptParser->isScriptRunning() && _interactive) {
+ if (isInteractive()) {
updateActiveResource();
checkCurrentResource();
}
@@ -448,7 +506,7 @@ void MohawkEngine_Myst::doFrame() {
}
bool MohawkEngine_Myst::wait(uint32 duration, bool skippable) {
- _interactive = false;
+ _waitingOnBlockingOperation = true;
uint32 end = getTotalPlayTime() + duration;
do {
@@ -460,7 +518,7 @@ bool MohawkEngine_Myst::wait(uint32 duration, bool skippable) {
}
} while (getTotalPlayTime() < end && !shouldQuit());
- _interactive = true;
+ _waitingOnBlockingOperation = false;
return false;
}
@@ -480,20 +538,27 @@ void MohawkEngine_Myst::pauseEngineIntern(bool pause) {
void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcSound, uint16 linkDstSound) {
debug(2, "changeToStack(%d)", stack);
- _curStack = stack;
-
// Fill screen with black and empty cursor
_cursor->setCursor(0);
_currentCursor = 0;
+ _sound->stopEffect();
+ _video->stopVideos();
+
+ // In Myst ME, play a fullscreen flyby movie, except when loading saves.
+ // Also play a flyby when first linking to Myst.
+ if (getFeatures() & GF_ME
+ && (_curStack != kIntroStack || (stack == kMystStack && card == 4134))) {
+ playFlybyMovie(stack, card);
+ }
+
+ _sound->stopBackground();
+
if (getFeatures() & GF_ME)
_system->fillScreen(_system->getScreenFormat().RGBToColor(0, 0, 0));
else
_gfx->clearScreenPalette();
- _sound->stopEffect();
- _sound->stopBackground();
- _video->stopVideos();
if (linkSrcSound)
playSoundBlocking(linkSrcSound);
@@ -503,20 +568,22 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
delete _prevStack;
_prevStack = _scriptParser;
+ _curStack = stack;
+
switch (_curStack) {
case kChannelwoodStack:
- _gameState->_globals.currentAge = 4;
+ _gameState->_globals.currentAge = kChannelwood;
_scriptParser = new MystStacks::Channelwood(this);
break;
case kCreditsStack:
_scriptParser = new MystStacks::Credits(this);
break;
case kDemoStack:
- _gameState->_globals.currentAge = 0;
+ _gameState->_globals.currentAge = kSelenitic;
_scriptParser = new MystStacks::Demo(this);
break;
case kDniStack:
- _gameState->_globals.currentAge = 6;
+ _gameState->_globals.currentAge = kDni;
_scriptParser = new MystStacks::Dni(this);
break;
case kIntroStack:
@@ -526,26 +593,26 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
_scriptParser = new MystStacks::MakingOf(this);
break;
case kMechanicalStack:
- _gameState->_globals.currentAge = 3;
+ _gameState->_globals.currentAge = kMechanical;
_scriptParser = new MystStacks::Mechanical(this);
break;
case kMystStack:
- _gameState->_globals.currentAge = 2;
+ _gameState->_globals.currentAge = kMystLibrary;
_scriptParser = new MystStacks::Myst(this);
break;
case kDemoPreviewStack:
_scriptParser = new MystStacks::Preview(this);
break;
case kSeleniticStack:
- _gameState->_globals.currentAge = 0;
+ _gameState->_globals.currentAge = kSelenitic;
_scriptParser = new MystStacks::Selenitic(this);
break;
case kDemoSlidesStack:
- _gameState->_globals.currentAge = 1;
+ _gameState->_globals.currentAge = kStoneship;
_scriptParser = new MystStacks::Slides(this);
break;
case kStoneshipStack:
- _gameState->_globals.currentAge = 1;
+ _gameState->_globals.currentAge = kStoneship;
_scriptParser = new MystStacks::Stoneship(this);
break;
default:
@@ -570,38 +637,6 @@ void MohawkEngine_Myst::changeToStack(uint16 stack, uint16 card, uint16 linkSrcS
_cache.clear();
_gfx->clearCache();
- if (getFeatures() & GF_ME) {
- // Play Flyby Entry Movie on Masterpiece Edition.
- const char *flyby = nullptr;
-
- switch (_curStack) {
- case kSeleniticStack:
- flyby = "selenitic flyby";
- break;
- case kStoneshipStack:
- 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 (ConfMan.getBool("playmystflyby") && card == 4134)
- flyby = "myst flyby";
- break;
- case kMechanicalStack:
- flyby = "mech age flyby";
- break;
- case kChannelwoodStack:
- flyby = "channelwood flyby";
- break;
- default:
- break;
- }
-
- if (flyby) {
- playFlybyMovie(flyby);
- }
- }
-
changeToCard(card, kTransitionCopy);
if (linkDstSound)
@@ -677,7 +712,7 @@ void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) {
// The demo resets the cursor at each card change except when in the library
if (getFeatures() & GF_DEMO
- && _gameState->_globals.currentAge != 2) {
+ && _gameState->_globals.currentAge != kMystLibrary) {
_cursor->setDefaultCursor();
}
@@ -724,7 +759,7 @@ void MohawkEngine_Myst::checkCurrentResource() {
}
for (uint16 i = 0; i < _resources.size(); i++) {
- if (_resources[i]->contains(mouse) && _resources[i]->type == kMystAreaHover
+ if (_resources[i]->contains(mouse) && _resources[i]->hasType(kMystAreaHover)
&& _hoverResource != _resources[i]) {
_hoverResource = static_cast<MystAreaHover *>(_resources[i]);
_hoverResource->handleMouseEnter();
@@ -955,50 +990,6 @@ void MohawkEngine_Myst::runExitScript() {
_scriptParser->runScript(script);
}
-void MohawkEngine_Myst::loadHelp(uint16 id) {
- // The original version did not have the help system
- if (!(getFeatures() & GF_ME))
- return;
-
- // TODO: Help File contains 5 cards i.e. VIEW, RLST, etc.
- // in addition to HELP resources.
- // These are Ids 9930 to 9934
- // Need to deal with loading and displaying these..
- // Current engine structure only supports display of
- // card from primary stack MHK
-
- debugC(kDebugHelp, "Loading Help System Data");
-
- Common::SeekableReadStream *helpStream = getResource(ID_HELP, id);
-
- uint16 count = helpStream->readUint16LE();
- uint16 *u0 = new uint16[count];
- Common::String helpText;
-
- debugC(kDebugHelp, "\tcount: %d", count);
-
- for (uint16 i = 0; i < count; i++) {
- u0[i] = helpStream->readUint16LE();
- debugC(kDebugHelp, "\tu0[%d]: %d", i, u0[i]);
- }
-
- // TODO: Previous values i.e. u0[0] to u0[count - 2]
- // appear to be resource ids in the help.dat file..
- if (u0[count - 1] != count)
- warning("loadHelp(): last u0 value is not equal to count");
-
- do {
- helpText += helpStream->readByte();
- } while (helpText.lastChar() != 0);
- helpText.deleteLastChar();
-
- debugC(kDebugHelp, "\thelpText: \"%s\"", helpText.c_str());
-
- delete[] u0;
-
- delete helpStream;
-}
-
void MohawkEngine_Myst::loadCursorHints() {
_cursorHints.clear();
@@ -1059,7 +1050,7 @@ 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 < _cursorHints.size(); i++)
- if (_resources[_cursorHints[i].id] == _activeResource && _activeResource->isEnabled()) {
+ if (_activeResource && _resources[_cursorHints[i].id] == _activeResource && _activeResource->isEnabled()) {
if (_cursorHints[i].cursor == -1) {
uint16 var_value = _scriptParser->getVar(_cursorHints[i].variableHint.var);
@@ -1107,7 +1098,7 @@ void MohawkEngine_Myst::redrawResource(MystAreaImageSwitch *resource, bool updat
void MohawkEngine_Myst::redrawArea(uint16 var, bool update) {
for (uint16 i = 0; i < _resources.size(); i++)
- if (_resources[i]->type == kMystAreaImageSwitch && _resources[i]->getImageSwitchVar() == var)
+ if (_resources[i]->hasType(kMystAreaImageSwitch) && _resources[i]->getImageSwitchVar() == var)
redrawResource(static_cast<MystAreaImageSwitch *>(_resources[i]), update);
}
@@ -1120,36 +1111,34 @@ MystArea *MohawkEngine_Myst::loadResource(Common::SeekableReadStream *rlstStream
switch (type) {
case kMystAreaAction:
- resource = new MystAreaAction(this, rlstStream, parent);
+ resource = new MystAreaAction(this, type, rlstStream, parent);
break;
case kMystAreaVideo:
- resource = new MystAreaVideo(this, rlstStream, parent);
+ resource = new MystAreaVideo(this, type, rlstStream, parent);
break;
case kMystAreaActionSwitch:
- resource = new MystAreaActionSwitch(this, rlstStream, parent);
+ resource = new MystAreaActionSwitch(this, type, rlstStream, parent);
break;
case kMystAreaImageSwitch:
- resource = new MystAreaImageSwitch(this, rlstStream, parent);
+ resource = new MystAreaImageSwitch(this, type, rlstStream, parent);
break;
case kMystAreaSlider:
- resource = new MystAreaSlider(this, rlstStream, parent);
+ resource = new MystAreaSlider(this, type, rlstStream, parent);
break;
case kMystAreaDrag:
- resource = new MystAreaDrag(this, rlstStream, parent);
+ resource = new MystAreaDrag(this, type, rlstStream, parent);
break;
case kMystVideoInfo:
- resource = new MystVideoInfo(this, rlstStream, parent);
+ resource = new MystVideoInfo(this, type, rlstStream, parent);
break;
case kMystAreaHover:
- resource = new MystAreaHover(this, rlstStream, parent);
+ resource = new MystAreaHover(this, type, rlstStream, parent);
break;
default:
- resource = new MystArea(this, rlstStream, parent);
+ resource = new MystArea(this, type, rlstStream, parent);
break;
}
- resource->type = type;
-
return resource;
}
@@ -1184,15 +1173,34 @@ Common::Error MohawkEngine_Myst::loadGameState(int slot) {
}
Common::Error MohawkEngine_Myst::saveGameState(int slot, const Common::String &desc) {
- return _gameState->save(slot, desc) ? Common::kNoError : Common::kUnknownError;
+ return _gameState->save(slot, desc, false) ? Common::kNoError : Common::kUnknownError;
+}
+
+void MohawkEngine_Myst::tryAutoSaving() {
+ if (!canSaveGameStateCurrently()) {
+ return; // Can't save right now, try again on the next frame
+ }
+
+ _lastSaveTime = _system->getMillis();
+
+ if (!_gameState->isAutoSaveAllowed()) {
+ return; // Can't autosave ever, try again after the next autosave delay
+ }
+
+ if (!_gameState->save(MystGameState::kAutoSaveSlot, "Autosave", true))
+ warning("Attempt to autosave has failed.");
}
bool MohawkEngine_Myst::hasGameSaveSupport() const {
return !(getFeatures() & GF_DEMO) && getGameType() != GType_MAKINGOF;
}
+bool MohawkEngine_Myst::isInteractive() {
+ return !_scriptParser->isScriptRunning() && !_waitingOnBlockingOperation;
+}
+
bool MohawkEngine_Myst::canLoadGameStateCurrently() {
- if (_scriptParser->isScriptRunning() || !_interactive) {
+ if (!isInteractive()) {
return false;
}
@@ -1229,8 +1237,8 @@ bool MohawkEngine_Myst::canSaveGameStateCurrently() {
}
void MohawkEngine_Myst::dropPage() {
- uint16 page = _gameState->_globals.heldPage;
- bool whitePage = page == 13;
+ HeldPage page = _gameState->_globals.heldPage;
+ bool whitePage = page == kWhitePage;
bool bluePage = page - 1 < 6;
bool redPage = page - 7 < 6;
@@ -1238,25 +1246,25 @@ void MohawkEngine_Myst::dropPage() {
_sound->playEffect(800);
// Drop page
- _gameState->_globals.heldPage = 0;
+ _gameState->_globals.heldPage = kNoPage;
// Redraw page area
- if (whitePage && _gameState->_globals.currentAge == 2) {
+ if (whitePage && _gameState->_globals.currentAge == kMystLibrary) {
_scriptParser->toggleVar(41);
redrawArea(41);
} else if (bluePage) {
- if (page == 6) {
- if (_gameState->_globals.currentAge == 2)
+ if (page == kBlueFirePlacePage) {
+ if (_gameState->_globals.currentAge == kMystLibrary)
redrawArea(24);
} else {
redrawArea(103);
}
} else if (redPage) {
- if (page == 12) {
- if (_gameState->_globals.currentAge == 2)
+ if (page == kRedFirePlacePage) {
+ if (_gameState->_globals.currentAge == kMystLibrary)
redrawArea(25);
- } else if (page == 10) {
- if (_gameState->_globals.currentAge == 1)
+ } else if (page == kRedStoneshipPage) {
+ if (_gameState->_globals.currentAge == kStoneship)
redrawArea(35);
} else {
redrawArea(102);
@@ -1277,9 +1285,9 @@ MystSoundBlock MohawkEngine_Myst::readSoundBlock(Common::ReadStream *stream) con
debugC(kDebugView, "\tSound: %d", soundBlock.sound);
soundBlock.soundVolume = stream->readUint16LE();
debugC(kDebugView, "\tVolume: %d", soundBlock.soundVolume);
- } else if (soundBlock.sound == kMystSoundActionContinue)
+ } else if (soundBlock.sound == kMystSoundActionContinue) {
debugC(kDebugView, "Continue current sound");
- else if (soundBlock.sound == kMystSoundActionChangeVolume) {
+ } else if (soundBlock.sound == kMystSoundActionChangeVolume) {
debugC(kDebugView, "Continue current sound, change volume");
soundBlock.soundVolume = stream->readUint16LE();
debugC(kDebugView, "\tVolume: %d", soundBlock.soundVolume);
@@ -1305,8 +1313,7 @@ MystSoundBlock MohawkEngine_Myst::readSoundBlock(Common::ReadStream *stream) con
soundBlock.soundList.push_back(sound);
}
} else {
- debugC(kDebugView, "Unknown");
- warning("Unknown sound control value '%d' in card '%d'", soundBlock.sound, _curCard);
+ error("Unknown sound control value '%d' in card '%d'", soundBlock.sound, _curCard);
}
return soundBlock;
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index 3f756faee0..64fee10fde 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -95,8 +95,6 @@ enum TransitionType {
kNoTransition = 999
};
-const uint16 kMasterpieceOnly = 0xFFFF;
-
struct MystCondition {
uint16 var;
Common::Array<uint16> values;
@@ -176,7 +174,7 @@ protected:
public:
MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription *gamedesc);
- virtual ~MohawkEngine_Myst();
+ ~MohawkEngine_Myst() override;
Common::SeekableReadStream *getResource(uint32 tag, uint16 id) override;
Common::Array<uint16> getResourceIDList(uint32 type) const;
@@ -229,17 +227,25 @@ public:
VideoEntryPtr playMovie(const Common::String &name, MystStack stack);
VideoEntryPtr findVideo(const Common::String &name, MystStack stack);
void playMovieBlocking(const Common::String &name, MystStack stack, uint16 x, uint16 y);
- void playFlybyMovie(const Common::String &name);
+ void playFlybyMovie(uint16 stack, uint16 card);
void waitUntilMovieEnds(const VideoEntryPtr &video);
void playSoundBlocking(uint16 id);
GUI::Debugger *getDebugger() override { return _console; }
+ /**
+ * Is the game currently interactive
+ *
+ * When the game is interactive, the user can interact with the game world
+ * and perform other operations such as loading saved games, ...
+ */
+ bool isInteractive();
bool canLoadGameStateCurrently() override;
bool canSaveGameStateCurrently() override;
Common::Error loadGameState(int slot) override;
Common::Error saveGameState(int slot, const Common::String &desc) override;
+ void tryAutoSaving();
bool hasFeature(EngineFeature f) const override;
private:
@@ -251,6 +257,7 @@ private:
uint16 _curStack;
uint16 _curCard;
+ uint32 _lastSaveTime;
MystView _view;
bool _runExitScript;
@@ -264,8 +271,6 @@ private:
void runInitScript();
void runExitScript();
- void loadHelp(uint16 id);
-
void loadResources();
void drawResourceRects();
void checkCurrentResource();
@@ -286,7 +291,7 @@ private:
bool _mouseClicked;
bool _mouseMoved;
bool _escapePressed;
- bool _interactive; // Is the game currently interactive
+ bool _waitingOnBlockingOperation;
Common::Array<MystCursorHint> _cursorHints;
void loadCursorHints();
diff --git a/engines/mohawk/myst_areas.cpp b/engines/mohawk/myst_areas.cpp
index 7cc39e97b2..eff51bf1c9 100644
--- a/engines/mohawk/myst_areas.cpp
+++ b/engines/mohawk/myst_areas.cpp
@@ -32,9 +32,10 @@
namespace Mohawk {
-MystArea::MystArea(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) {
- _vm = vm;
- _parent = parent;
+MystArea::MystArea(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ _vm(vm),
+ _parent(parent),
+ _type(type) {
if (parent == nullptr) {
_flags = rlstStream->readUint16LE();
@@ -77,7 +78,7 @@ void MystArea::handleMouseUp() {
uint16 opcode;
- switch (type) {
+ switch (_type) {
case kMystAreaForward:
opcode = 6;
break;
@@ -118,7 +119,7 @@ void MystArea::setEnabled(bool enabled) {
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());
+ _type, _rect.left, _rect.top, _rect.width(), _rect.height());
if (_dest != 0)
desc += Common::String::format(" dest: %4d", _dest);
@@ -137,8 +138,8 @@ void MystArea::drawBoundingRect() {
}
}
-MystAreaAction::MystAreaAction(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
- MystArea(vm, rlstStream, parent) {
+MystAreaAction::MystAreaAction(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystArea(vm, type, rlstStream, parent) {
debugC(kDebugResource, "\tResource Type 5 Script:");
_script = vm->_scriptParser->readScript(rlstStream, kMystScriptNormal);
@@ -175,8 +176,8 @@ Common::String MystAreaVideo::convertMystVideoName(const Common::String &name) {
return temp + ".mov";
}
-MystAreaVideo::MystAreaVideo(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
- MystAreaAction(vm, rlstStream, parent) {
+MystAreaVideo::MystAreaVideo(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaAction(vm, type, rlstStream, parent) {
char c = 0;
do {
@@ -195,12 +196,21 @@ MystAreaVideo::MystAreaVideo(MohawkEngine_Myst *vm, Common::SeekableReadStream *
// Position values require modulus 10000 to keep in sane range.
_left = rlstStream->readSint16LE() % 10000;
_top = rlstStream->readSint16LE() % 10000;
- _playOnCardChange = rlstStream->readUint16LE();
+ _playOnCardChange = rlstStream->readUint16LE() != 0;
_direction = rlstStream->readSint16LE();
_playBlocking = rlstStream->readUint16LE();
_loop = rlstStream->readUint16LE();
_playRate = rlstStream->readUint16LE();
+ // WORKAROUND: Myst v1.0 has playOnCardChange set to true
+ // for the Myst flyby video shown during the intro.
+ // This causes the flyby to play over the closed Myst book picture.
+ // Later releases of the game have that flag set to false.
+ // Here we apply a resource patch to match the newer releases.
+ if (_videoFile == "qtw/intro/intro2.mov") {
+ _playOnCardChange = false;
+ }
+
debugC(kDebugResource, "\tvideoFile: \"%s\"", _videoFile.c_str());
debugC(kDebugResource, "\tleft: %d", _left);
debugC(kDebugResource, "\ttop: %d", _top);
@@ -281,8 +291,8 @@ void MystAreaVideo::pauseMovie(bool pause) {
handle->pause(pause);
}
-MystAreaActionSwitch::MystAreaActionSwitch(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
- MystArea(vm, rlstStream, parent) {
+MystAreaActionSwitch::MystAreaActionSwitch(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystArea(vm, type, rlstStream, parent) {
_actionSwitchVar = rlstStream->readUint16LE();
uint16 numSubResources = rlstStream->readUint16LE();
debugC(kDebugResource, "\tactionSwitchVar: %d", _actionSwitchVar);
@@ -335,8 +345,8 @@ void MystAreaActionSwitch::handleMouseDown() {
doSwitch(&MystArea::handleMouseDown);
}
-MystAreaImageSwitch::MystAreaImageSwitch(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
- MystAreaActionSwitch(vm, rlstStream, parent) {
+MystAreaImageSwitch::MystAreaImageSwitch(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaActionSwitch(vm, type, rlstStream, parent) {
_imageSwitchVar = rlstStream->readUint16LE();
uint16 numSubImages = rlstStream->readUint16LE();
debugC(kDebugResource, "\tvar8: %d", _imageSwitchVar);
@@ -477,8 +487,8 @@ const Common::String MystAreaImageSwitch::describe() {
// No MystResourceType9!
-MystAreaSlider::MystAreaSlider(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
- MystAreaDrag(vm, rlstStream, parent) {
+MystAreaSlider::MystAreaSlider(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaDrag(vm, type, rlstStream, parent) {
_dragSound = rlstStream->readUint16LE();
debugC(kDebugResource, "\tdrag sound : %d", _dragSound);
@@ -643,8 +653,8 @@ void MystAreaSlider::updatePosition(const Common::Point &mouse) {
_vm->_sound->playEffect(_dragSound);
}
-MystAreaDrag::MystAreaDrag(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
- MystAreaImageSwitch(vm, rlstStream, parent) {
+MystAreaDrag::MystAreaDrag(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaImageSwitch(vm, type, rlstStream, parent) {
_flagHV = rlstStream->readUint16LE();
_minH = rlstStream->readUint16LE();
_maxH = rlstStream->readUint16LE();
@@ -748,8 +758,8 @@ uint16 MystAreaDrag::getList3(uint16 index) {
return (index < _lists[2].size()) ? _lists[2][index] : 0;
}
-MystVideoInfo::MystVideoInfo(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
- MystAreaDrag(vm, rlstStream, parent) {
+MystVideoInfo::MystVideoInfo(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystAreaDrag(vm, type, rlstStream, parent) {
_numFrames = rlstStream->readUint16LE();
_firstFrame = rlstStream->readUint16LE();
uint16 frameWidth = rlstStream->readUint16LE();
@@ -774,8 +784,8 @@ MystVideoInfo::~MystVideoInfo() {
}
void MystVideoInfo::drawFrame(uint16 frame) {
- _currentFrame = _firstFrame + frame;
- _vm->_gfx->copyImageToScreen(_currentFrame, _frameRect);
+ uint16 currentFrame = _firstFrame + frame;
+ _vm->_gfx->copyImageToScreen(currentFrame, _frameRect);
}
bool MystVideoInfo::pullLeverV() {
@@ -810,8 +820,8 @@ void MystVideoInfo::releaseLeverV() {
}
}
-MystAreaHover::MystAreaHover(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent) :
- MystArea(vm, rlstStream, parent) {
+MystAreaHover::MystAreaHover(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent) :
+ MystArea(vm, type, rlstStream, parent) {
_enterOpcode = rlstStream->readUint16LE();
_leaveOpcode = rlstStream->readUint16LE();
diff --git a/engines/mohawk/myst_areas.h b/engines/mohawk/myst_areas.h
index 32b6ca4f2f..b389f32ea1 100644
--- a/engines/mohawk/myst_areas.h
+++ b/engines/mohawk/myst_areas.h
@@ -58,12 +58,13 @@ enum {
class MystArea {
public:
- MystArea(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ MystArea(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent);
virtual ~MystArea();
virtual const Common::String describe();
void drawBoundingRect();
+ bool hasType(ResourceType type) const { return _type == type; }
bool contains(Common::Point point) { return _rect.contains(point); }
virtual void drawDataToScreen() {}
virtual void handleCardChange() {}
@@ -83,10 +84,10 @@ public:
virtual void handleMouseDrag() {}
MystArea *_parent;
- ResourceType type;
protected:
MohawkEngine_Myst *_vm;
+ ResourceType _type;
uint16 _flags;
Common::Rect _rect;
uint16 _dest;
@@ -94,7 +95,7 @@ protected:
class MystAreaAction : public MystArea {
public:
- MystAreaAction(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ MystAreaAction(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent);
void handleMouseUp() override;
const Common::String describe() override;
@@ -105,7 +106,7 @@ protected:
class MystAreaVideo : public MystAreaAction {
public:
- MystAreaVideo(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ MystAreaVideo(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent);
VideoEntryPtr playMovie();
VideoEntryPtr getVideo();
@@ -125,20 +126,20 @@ protected:
uint16 _loop;
int16 _direction; // 1 => forward, -1 => backwards
uint16 _playBlocking;
- uint16 _playOnCardChange;
+ bool _playOnCardChange;
uint16 _playRate; // percents
};
class MystAreaActionSwitch : public MystArea {
public:
- MystAreaActionSwitch(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
- virtual ~MystAreaActionSwitch();
+ MystAreaActionSwitch(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ ~MystAreaActionSwitch() override;
- virtual void drawDataToScreen() override;
- virtual void handleCardChange() override;
+ void drawDataToScreen() override;
+ void handleCardChange() override;
- virtual void handleMouseUp() override;
- virtual void handleMouseDown() override;
+ void handleMouseUp() override;
+ void handleMouseDown() override;
MystArea *getSubResource(uint16 index) { return _subResources[index]; }
protected:
@@ -152,16 +153,16 @@ protected:
class MystAreaImageSwitch : public MystAreaActionSwitch {
public:
- MystAreaImageSwitch(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
- virtual ~MystAreaImageSwitch();
+ MystAreaImageSwitch(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ ~MystAreaImageSwitch() override;
struct SubImage {
uint16 wdib;
Common::Rect rect;
};
- virtual const Common::String describe() override;
- virtual void drawDataToScreen() override;
+ const Common::String describe() override;
+ void drawDataToScreen() override;
void drawConditionalDataToScreen(uint16 state, bool update = true);
uint16 getImageSwitchVar() override;
@@ -175,14 +176,14 @@ protected:
class MystAreaDrag : public MystAreaImageSwitch {
public:
- MystAreaDrag(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
- virtual ~MystAreaDrag();
+ MystAreaDrag(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ ~MystAreaDrag() override;
const Common::String describe() override;
- virtual void handleMouseDown() override;
- virtual void handleMouseUp() override;
- virtual void handleMouseDrag() override;
+ void handleMouseDown() override;
+ void handleMouseUp() override;
+ void handleMouseDrag() override;
uint16 getList1(uint16 index);
uint16 getList2(uint16 index);
@@ -214,8 +215,8 @@ protected:
class MystAreaSlider : public MystAreaDrag {
public:
- MystAreaSlider(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
- virtual ~MystAreaSlider();
+ MystAreaSlider(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ ~MystAreaSlider() override;
void handleMouseDown() override;
void handleMouseUp() override;
@@ -235,8 +236,8 @@ protected:
class MystVideoInfo : public MystAreaDrag {
public:
- MystVideoInfo(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
- virtual ~MystVideoInfo();
+ MystVideoInfo(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ ~MystVideoInfo() override;
void drawFrame(uint16 frame);
bool pullLeverV();
@@ -247,14 +248,11 @@ protected:
uint16 _numFrames;
uint16 _firstFrame;
Common::Rect _frameRect;
-
-private:
- uint16 _currentFrame;
};
class MystAreaHover : public MystArea {
public:
- MystAreaHover(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystArea *parent);
+ MystAreaHover(MohawkEngine_Myst *vm, ResourceType type, Common::SeekableReadStream *rlstStream, MystArea *parent);
const Common::String describe() override;
diff --git a/engines/mohawk/myst_graphics.cpp b/engines/mohawk/myst_graphics.cpp
index 3f8d15cea5..6b43ea02bc 100644
--- a/engines/mohawk/myst_graphics.cpp
+++ b/engines/mohawk/myst_graphics.cpp
@@ -231,6 +231,15 @@ void MystGraphics::copyImageSectionToBackBuffer(uint16 image, Common::Rect src,
MohawkSurface *mhkSurface = findImage(image);
Graphics::Surface *surface = mhkSurface->getSurface();
+ if (image == 2258 && _vm->getFeatures() & GF_ME) {
+ // In Myst ME, the image for the open red page brother door
+ // when the special lights are on does not have the correct width.
+ // We work around this issue by tweaking the destination rectangle
+ // so it renders at the correct position.
+ // The original executable does the same hack.
+ dest.left += 49;
+ }
+
// Make sure the image is bottom aligned in the dest rect
dest.top = dest.bottom - MIN<int>(surface->h, dest.height());
diff --git a/engines/mohawk/myst_graphics.h b/engines/mohawk/myst_graphics.h
index 44669bd6dc..b8217f6cfc 100644
--- a/engines/mohawk/myst_graphics.h
+++ b/engines/mohawk/myst_graphics.h
@@ -40,8 +40,8 @@ enum RectState {
class MystGraphics : public GraphicsManager {
public:
- MystGraphics(MohawkEngine_Myst *vm);
- ~MystGraphics();
+ explicit MystGraphics(MohawkEngine_Myst *vm);
+ ~MystGraphics() override;
void copyImageSectionToScreen(uint16 image, Common::Rect src, Common::Rect dest);
void copyImageSectionToBackBuffer(uint16 image, Common::Rect src, Common::Rect dest);
@@ -51,7 +51,6 @@ public:
void runTransition(TransitionType type, Common::Rect rect, uint16 steps, uint16 delay);
void drawRect(Common::Rect rect, RectState state);
void drawLine(const Common::Point &p1, const Common::Point &p2, uint32 color);
- void enableDrawingTimeSimulation(bool enable);
void fadeToBlack();
void fadeFromBlack();
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index ba426505e1..c1a593b430 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -40,6 +40,7 @@ MystScriptEntry::MystScriptEntry() {
var = 0;
resourceId = 0;
u1 = 0;
+ opcode = 0;
}
const uint8 MystScriptParser::_stackMap[11] = {
@@ -79,8 +80,10 @@ MystScriptParser::MystScriptParser(MohawkEngine_Myst *vm) :
_invokingResource = nullptr;
_savedCardId = 0;
_savedCursorId = 0;
+ _savedMapCardId = 0;
_tempVar = 0;
_scriptNestingLevel = 0;
+ _startTime = 0;
}
MystScriptParser::~MystScriptParser() {
@@ -375,7 +378,7 @@ void MystScriptParser::o_takePage(uint16 var, const ArgumentsArray &args) {
cursorId = kDefaultMystCursor;
}
- uint16 oldPage = _globals.heldPage;
+ HeldPage oldPage = _globals.heldPage;
// Take / drop page
toggleVar(var);
@@ -385,7 +388,7 @@ void MystScriptParser::o_takePage(uint16 var, const ArgumentsArray &args) {
_vm->redrawArea(var);
// Set new cursor
- if (_globals.heldPage)
+ if (_globals.heldPage != kNoPage)
_vm->setMainCursor(cursorId);
else
_vm->setMainCursor(kDefaultMystCursor);
@@ -600,9 +603,11 @@ void MystScriptParser::o_copyImageToBackBuffer(uint16 var, const ArgumentsArray
Common::Rect dstRect = Common::Rect(args[5], args[6], 544, 333);
- if (dstRect.left == -1 || dstRect.top == -1) {
- // Interpreted as full screen
+ if (dstRect.left == -1) {
dstRect.left = 0;
+ }
+
+ if (dstRect.top == -1) {
dstRect.top = 0;
}
@@ -622,6 +627,8 @@ void MystScriptParser::o_copyImageToBackBuffer(uint16 var, const ArgumentsArray
}
void MystScriptParser::o_changeBackgroundSound(uint16 var, const ArgumentsArray &args) {
+ soundWaitStop();
+
// Used on Stoneship Card 2080
// Used on Channelwood Card 3225 with argc = 8 i.e. Conditional Sound List
Common::MemoryWriteStreamDynamic writeStream = Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
@@ -749,11 +756,11 @@ void MystScriptParser::o_changeCardPlaySoundDirectional(uint16 var, const Argume
debugC(kDebugScript, "\tdelay between steps: %d", delayBetweenSteps);
debugC(kDebugScript, "\tanimated update data size: %d", dataSize);
+ _vm->changeToCard(cardId, kNoTransition);
+
if (soundId)
_vm->_sound->playEffect(soundId);
- _vm->changeToCard(cardId, kNoTransition);
-
animatedUpdate(ArgumentsArray(args.begin() + 4, dataSize), delayBetweenSteps);
}
@@ -784,12 +791,16 @@ void MystScriptParser::o_soundWaitStop(uint16 var, const ArgumentsArray &args) {
// Used on Selenitic Card 1191 (Maze Runner)
// Used on Mechanical Card 6267 (Code Lock)
// Used when Button is pushed...
- while (_vm->_sound->isEffectPlaying())
+ soundWaitStop();
+}
+
+void MystScriptParser::soundWaitStop() const {
+ while (_vm->_sound->isEffectPlaying() && !Engine::shouldQuit())
_vm->doFrame();
}
void MystScriptParser::o_quit(uint16 var, const ArgumentsArray &args) {
- _vm->quitGame();
+ Engine::quitGame();
}
void MystScriptParser::showMap() {
@@ -800,6 +811,8 @@ void MystScriptParser::showMap() {
}
void MystScriptParser::o_exitMap(uint16 var, const ArgumentsArray &args) {
+ assert(_savedMapCardId);
+
_vm->changeToCard(_savedMapCardId, kTransitionCopy);
}
diff --git a/engines/mohawk/myst_scripts.h b/engines/mohawk/myst_scripts.h
index a336f0239a..a7a840b9d3 100644
--- a/engines/mohawk/myst_scripts.h
+++ b/engines/mohawk/myst_scripts.h
@@ -60,7 +60,7 @@ typedef Common::SharedPtr<Common::Array<MystScriptEntry> > MystScript;
class MystScriptParser {
public:
- MystScriptParser(MohawkEngine_Myst *vm);
+ explicit MystScriptParser(MohawkEngine_Myst *vm);
virtual ~MystScriptParser();
void runScript(MystScript script, MystArea *invokingResource = nullptr);
@@ -87,6 +87,7 @@ public:
void showMap();
void animatedUpdate(const ArgumentsArray &args, uint16 delay);
+ void soundWaitStop() const;
// Common opcodes
DECLARE_OPCODE(o_toggleVar);
diff --git a/engines/mohawk/myst_sound.h b/engines/mohawk/myst_sound.h
index 71df23df39..953017097d 100644
--- a/engines/mohawk/myst_sound.h
+++ b/engines/mohawk/myst_sound.h
@@ -39,7 +39,7 @@ class MohawkEngine_Myst;
class MystSound {
public:
- MystSound(MohawkEngine_Myst *vm);
+ explicit MystSound(MohawkEngine_Myst *vm);
~MystSound();
// Effect channel
diff --git a/engines/mohawk/myst_stacks/channelwood.cpp b/engines/mohawk/myst_stacks/channelwood.cpp
index 17df749c74..726b3d6526 100644
--- a/engines/mohawk/myst_stacks/channelwood.cpp
+++ b/engines/mohawk/myst_stacks/channelwood.cpp
@@ -37,7 +37,13 @@ namespace Mohawk {
namespace MystStacks {
Channelwood::Channelwood(MohawkEngine_Myst *vm) :
- MystScriptParser(vm), _state(vm->_gameState->_channelwood) {
+ MystScriptParser(vm),
+ _state(vm->_gameState->_channelwood),
+ _valveVar(0),
+ _siriusDrawerState(0),
+ _doorOpened(0),
+ _leverPulled(false),
+ _leverAction(nullptr) {
setupOpcodes();
}
@@ -181,7 +187,7 @@ uint16 Channelwood::getVar(uint16 var) {
}
case 102: // Sirrus's Desk Drawer / Red Page State
if (_siriusDrawerState) {
- if(!(_globals.redPagesInBook & 16) && (_globals.heldPage != 11))
+ if(!(_globals.redPagesInBook & 16) && (_globals.heldPage != kRedChannelwoodPage))
return 2; // Drawer Open, Red Page Present
else
return 1; // Drawer Open, Red Page Taken
@@ -189,7 +195,7 @@ uint16 Channelwood::getVar(uint16 var) {
return 0; // Drawer Closed
}
case 103: // Blue Page Present
- return !(_globals.bluePagesInBook & 16) && (_globals.heldPage != 5);
+ return !(_globals.bluePagesInBook & 16) && (_globals.heldPage != kBlueChannelwoodPage);
default:
return MystScriptParser::getVar(var);
}
@@ -208,18 +214,18 @@ void Channelwood::toggleVar(uint16 var) {
break;
case 102: // Red page
if (!(_globals.redPagesInBook & 16)) {
- if (_globals.heldPage == 11)
- _globals.heldPage = 0;
+ if (_globals.heldPage == kRedChannelwoodPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 11;
+ _globals.heldPage = kRedChannelwoodPage;
}
break;
case 103: // Blue page
if (!(_globals.bluePagesInBook & 16)) {
- if (_globals.heldPage == 5)
- _globals.heldPage = 0;
+ if (_globals.heldPage == kBlueChannelwoodPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 5;
+ _globals.heldPage = kBlueChannelwoodPage;
}
break;
default:
@@ -329,6 +335,7 @@ void Channelwood::o_pipeExtend(uint16 var, const ArgumentsArray &args) {
void Channelwood::o_drawImageChangeCardAndVolume(uint16 var, const ArgumentsArray &args) {
uint16 imageId = args[0];
uint16 cardId = args[1];
+ uint16 volume = args.size() == 3 ? args[2] : 0;
debugC(kDebugScript, "\timageId: %d", imageId);
debugC(kDebugScript, "\tcardId: %d", cardId);
@@ -338,8 +345,7 @@ void Channelwood::o_drawImageChangeCardAndVolume(uint16 var, const ArgumentsArra
_vm->changeToCard(cardId, kTransitionPartToLeft);
- if (args.size() == 3) {
- uint16 volume = args[2];
+ if (volume) {
_vm->_sound->changeBackgroundVolume(volume);
}
}
diff --git a/engines/mohawk/myst_stacks/channelwood.h b/engines/mohawk/myst_stacks/channelwood.h
index 6b8ba9dff7..3302a8e17b 100644
--- a/engines/mohawk/myst_stacks/channelwood.h
+++ b/engines/mohawk/myst_stacks/channelwood.h
@@ -37,8 +37,8 @@ namespace MystStacks {
class Channelwood : public MystScriptParser {
public:
- Channelwood(MohawkEngine_Myst *vm);
- ~Channelwood();
+ explicit Channelwood(MohawkEngine_Myst *vm);
+ ~Channelwood() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
@@ -49,7 +49,7 @@ private:
void toggleVar(uint16 var) override;
bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() override { return 9932; }
+ uint16 getMap() override { return 9932; }
DECLARE_OPCODE(o_bridgeToggle);
DECLARE_OPCODE(o_pipeExtend);
diff --git a/engines/mohawk/myst_stacks/credits.cpp b/engines/mohawk/myst_stacks/credits.cpp
index ba49ac2201..80ccf7fe9a 100644
--- a/engines/mohawk/myst_stacks/credits.cpp
+++ b/engines/mohawk/myst_stacks/credits.cpp
@@ -23,6 +23,7 @@
#include "mohawk/myst.h"
#include "mohawk/myst_areas.h"
#include "mohawk/myst_graphics.h"
+#include "mohawk/cursors.h"
#include "mohawk/sound.h"
#include "mohawk/video.h"
#include "mohawk/myst_stacks/credits.h"
@@ -34,9 +35,11 @@ namespace MystStacks {
// NOTE: Credits Start Card is 10000
-Credits::Credits(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+Credits::Credits(MohawkEngine_Myst *vm) :
+ MystScriptParser(vm),
+ _creditsRunning(false),
+ _curImage(0) {
setupOpcodes();
- _curImage = 0;
}
Credits::~Credits() {
@@ -80,13 +83,17 @@ uint16 Credits::getVar(uint16 var) {
case 0: // Credits Image Control
return _curImage;
case 1: // Credits Music Control (Good / bad ending)
- return _globals.ending != 4;
+ return _globals.ending != kBooksDestroyed;
default:
return MystScriptParser::getVar(var);
}
}
void Credits::o_runCredits(uint16 var, const ArgumentsArray &args) {
+ // The credits stack does not have all the cursors, reset to the default cursor.
+ _globals.heldPage = kNoPage;
+ _vm->setMainCursor(kDefaultMystCursor);
+
// Activate the credits
_creditsRunning = true;
_curImage = 0;
diff --git a/engines/mohawk/myst_stacks/credits.h b/engines/mohawk/myst_stacks/credits.h
index bea5381534..966d93068a 100644
--- a/engines/mohawk/myst_stacks/credits.h
+++ b/engines/mohawk/myst_stacks/credits.h
@@ -37,8 +37,8 @@ namespace MystStacks {
class Credits : public MystScriptParser {
public:
- Credits(MohawkEngine_Myst *vm);
- ~Credits();
+ explicit Credits(MohawkEngine_Myst *vm);
+ ~Credits() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
diff --git a/engines/mohawk/myst_stacks/demo.cpp b/engines/mohawk/myst_stacks/demo.cpp
index 7ae55686c5..d2ba70c198 100644
--- a/engines/mohawk/myst_stacks/demo.cpp
+++ b/engines/mohawk/myst_stacks/demo.cpp
@@ -30,10 +30,12 @@
namespace Mohawk {
namespace MystStacks {
-Demo::Demo(MohawkEngine_Myst *vm) : Intro(vm) {
+Demo::Demo(MohawkEngine_Myst *vm) :
+ Intro(vm),
+ _returnToMenuRunning(false),
+ _returnToMenuStep(0),
+ _returnToMenuNextTime(0) {
setupOpcodes();
-
- _returnToMenuStep = 0;
}
Demo::~Demo() {
diff --git a/engines/mohawk/myst_stacks/demo.h b/engines/mohawk/myst_stacks/demo.h
index 337ddaae98..acb224b6cf 100644
--- a/engines/mohawk/myst_stacks/demo.h
+++ b/engines/mohawk/myst_stacks/demo.h
@@ -37,8 +37,8 @@ namespace MystStacks {
class Demo : public Intro {
public:
- Demo(MohawkEngine_Myst *vm);
- ~Demo();
+ explicit Demo(MohawkEngine_Myst *vm);
+ ~Demo() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
@@ -52,8 +52,6 @@ private:
DECLARE_OPCODE(o_returnToMenu_init);
- DECLARE_OPCODE(opcode_300);
-
bool _returnToMenuRunning;
uint16 _returnToMenuStep; // 42
uint32 _returnToMenuNextTime; // 6
diff --git a/engines/mohawk/myst_stacks/dni.cpp b/engines/mohawk/myst_stacks/dni.cpp
index ba53c70037..a38b5d3857 100644
--- a/engines/mohawk/myst_stacks/dni.cpp
+++ b/engines/mohawk/myst_stacks/dni.cpp
@@ -34,9 +34,15 @@ namespace Mohawk {
namespace MystStacks {
Dni::Dni(MohawkEngine_Myst *vm) :
- MystScriptParser(vm) {
+ MystScriptParser(vm),
+ _notSeenAtrus(true),
+ _atrusRunning(false),
+ _waitForLoop(false),
+ _atrusLeft(false),
+ _atrusLeftTime(0),
+ _loopStart(0),
+ _loopEnd(0) {
setupOpcodes();
- _notSeenAtrus = true;
}
Dni::~Dni() {
@@ -74,16 +80,16 @@ void Dni::runPersistentScripts() {
uint16 Dni::getVar(uint16 var) {
switch(var) {
case 0: // Atrus Gone (from across room)
- return _globals.ending == 2;
+ return _globals.ending == kAtrusLeaves;
case 1: // Myst Book Status
- if (_globals.ending != 4)
- return _globals.ending == 3;
+ if (_globals.ending != kBooksDestroyed)
+ return _globals.ending == kForgotPage;
else
return 2; // Linkable
case 2: // Music Type
if (_notSeenAtrus) {
_notSeenAtrus = false;
- return _globals.ending != 4 && _globals.heldPage != 13;
+ return _globals.ending != kBooksDestroyed && _globals.heldPage != kWhitePage;
} else
return 2;
default:
@@ -98,9 +104,9 @@ void Dni::o_handPage(uint16 var, const ArgumentsArray &args) {
VideoEntryPtr atrus = _vm->findVideo(_video, kDniStack);
// Good ending and Atrus asked to give page
- if (_globals.ending == 1 && atrus && atrus->getTime() > (uint)Audio::Timestamp(0, 6801, 600).msecs()) {
- _globals.ending = 2;
- _globals.heldPage = 0;
+ if (_globals.ending == kAtrusWantsPage && atrus && atrus->getTime() > (uint)Audio::Timestamp(0, 6801, 600).msecs()) {
+ _globals.ending = kAtrusLeaves;
+ _globals.heldPage = kNoPage;
_vm->setMainCursor(kDefaultMystCursor);
// Play movie end (atrus leaving)
@@ -121,12 +127,13 @@ void Dni::atrusLeft_run() {
atrus->moveTo(_videoPos.x, _videoPos.y);
atrus->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 98000, 600));
+ _atrusRunning = false;
_waitForLoop = true;
_loopStart = 73095;
_loopEnd = 98000;
// Good ending
- _globals.ending = 4;
+ _globals.ending = kBooksDestroyed;
_globals.bluePagesInBook = 63;
_globals.redPagesInBook = 63;
@@ -146,10 +153,10 @@ void Dni::loopVideo_run() {
}
void Dni::atrus_run() {
- if (_globals.ending == 2) {
+ if (_globals.ending == kAtrusLeaves) {
// Wait for atrus to come back
_atrusLeft = true;
- } else if (_globals.ending == 1) {
+ } else if (_globals.ending == kAtrusWantsPage) {
// Atrus asking for page
if (!_vm->_video->isVideoPlaying()) {
_video = "atr1page";
@@ -159,8 +166,8 @@ void Dni::atrus_run() {
atrus->setLooping(true);
atrus->setBounds(Audio::Timestamp(0, 7388, 600), Audio::Timestamp(0, 14700, 600));
}
- } else if (_globals.ending != 3 && _globals.ending != 4) {
- if (_globals.heldPage == 13) {
+ } else if (_globals.ending != kForgotPage && _globals.ending != kBooksDestroyed) {
+ if (_globals.heldPage == kWhitePage) {
_video = "atr1page";
_videoPos = Common::Point(215, 76);
VideoEntryPtr atrus = _vm->playMovie(_video, kDniStack);
@@ -172,7 +179,7 @@ void Dni::atrus_run() {
_loopEnd = 14700;
// Wait for page
- _globals.ending = 1;
+ _globals.ending = kAtrusWantsPage;
} else {
_video = "atr1nopg";
@@ -181,12 +188,13 @@ void Dni::atrus_run() {
atrus->moveTo(_videoPos.x, _videoPos.y);
atrus->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 46175, 600));
+ _atrusRunning = false;
_waitForLoop = true;
_loopStart = 30656;
_loopEnd = 46175;
// Bad ending
- _globals.ending = 3;
+ _globals.ending = kForgotPage;
}
} else if (!_vm->_video->isVideoPlaying()) {
VideoEntryPtr atrus = _vm->playMovie("atrwrite", kDniStack);
diff --git a/engines/mohawk/myst_stacks/dni.h b/engines/mohawk/myst_stacks/dni.h
index 7ba49b1936..30c9329fe6 100644
--- a/engines/mohawk/myst_stacks/dni.h
+++ b/engines/mohawk/myst_stacks/dni.h
@@ -37,8 +37,8 @@ namespace MystStacks {
class Dni : public MystScriptParser {
public:
- Dni(MohawkEngine_Myst *vm);
- ~Dni();
+ explicit Dni(MohawkEngine_Myst *vm);
+ ~Dni() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
diff --git a/engines/mohawk/myst_stacks/intro.cpp b/engines/mohawk/myst_stacks/intro.cpp
index 2b431e834a..9e03713b0f 100644
--- a/engines/mohawk/myst_stacks/intro.cpp
+++ b/engines/mohawk/myst_stacks/intro.cpp
@@ -31,7 +31,12 @@
namespace Mohawk {
namespace MystStacks {
-Intro::Intro(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+Intro::Intro(MohawkEngine_Myst *vm) :
+ MystScriptParser(vm),
+ _introMoviesRunning(false),
+ _introStep(0),
+ _linkBookRunning(false),
+ _linkBookMovie(nullptr) {
setupOpcodes();
}
@@ -66,7 +71,7 @@ void Intro::runPersistentScripts() {
uint16 Intro::getVar(uint16 var) {
switch(var) {
case 0:
- if (_globals.currentAge == 9 || _globals.currentAge == 10)
+ if (_globals.currentAge == kSirrusEnding || _globals.currentAge == kAchenarEnding)
return 2;
else
return _globals.currentAge;
diff --git a/engines/mohawk/myst_stacks/intro.h b/engines/mohawk/myst_stacks/intro.h
index 938a30e691..ec78199802 100644
--- a/engines/mohawk/myst_stacks/intro.h
+++ b/engines/mohawk/myst_stacks/intro.h
@@ -38,8 +38,8 @@ namespace MystStacks {
class Intro : public MystScriptParser {
public:
- Intro(MohawkEngine_Myst *vm);
- ~Intro();
+ explicit Intro(MohawkEngine_Myst *vm);
+ ~Intro() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
diff --git a/engines/mohawk/myst_stacks/makingof.cpp b/engines/mohawk/myst_stacks/makingof.cpp
index 2907c53231..4e0ce516b8 100644
--- a/engines/mohawk/myst_stacks/makingof.cpp
+++ b/engines/mohawk/myst_stacks/makingof.cpp
@@ -30,7 +30,8 @@
namespace Mohawk {
namespace MystStacks {
-MakingOf::MakingOf(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+MakingOf::MakingOf(MohawkEngine_Myst *vm) :
+ MystScriptParser(vm) {
setupOpcodes();
}
diff --git a/engines/mohawk/myst_stacks/makingof.h b/engines/mohawk/myst_stacks/makingof.h
index cdc64d2991..f65c9696c3 100644
--- a/engines/mohawk/myst_stacks/makingof.h
+++ b/engines/mohawk/myst_stacks/makingof.h
@@ -37,8 +37,8 @@ namespace MystStacks {
class MakingOf : public MystScriptParser {
public:
- MakingOf(MohawkEngine_Myst *vm);
- ~MakingOf();
+ explicit MakingOf(MohawkEngine_Myst *vm);
+ ~MakingOf() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
diff --git a/engines/mohawk/myst_stacks/mechanical.cpp b/engines/mohawk/myst_stacks/mechanical.cpp
index bd5406a4f1..a58e278590 100644
--- a/engines/mohawk/myst_stacks/mechanical.cpp
+++ b/engines/mohawk/myst_stacks/mechanical.cpp
@@ -36,23 +36,53 @@ namespace Mohawk {
namespace MystStacks {
Mechanical::Mechanical(MohawkEngine_Myst *vm) :
- MystScriptParser(vm), _state(vm->_gameState->_mechanical) {
+ MystScriptParser(vm),
+ _state(vm->_gameState->_mechanical) {
setupOpcodes();
_elevatorGoingMiddle = false;
_elevatorPosition = 0;
+ _elevatorGoingDown = 0;
+ _elevatorRotationSpeed = 0;
+ _elevatorRotationGearPosition = 0;
+ _elevatorRotationSoundId = 0;
+ _elevatorRotationLeverMoving = false;
+ _elevatorTooLate = false;
+ _elevatorInCabin = false;
+ _elevatorTopCounter = 0;
+ _elevatorNextTime = 0;
_crystalLit = 0;
_mystStaircaseState = false;
_fortressPosition = 0;
- _fortressRotationSpeed = 0;
- _fortressSimulationSpeed = 0;
_gearsWereRunning = false;
_fortressRotationShortMovieWorkaround = false;
_fortressRotationShortMovieCount = 0;
_fortressRotationShortMovieLast = 0;
+
+ _fortressRotationRunning = false;
+ _fortressRotationSpeed = 0;
+ _fortressRotationBrake = 0;
+ _fortressRotationGears = nullptr;
+
+ _fortressSimulationRunning = false;
+ _fortressSimulationInit = false;
+ _fortressSimulationSpeed = 0;
+ _fortressSimulationBrake = 0;
+ _fortressSimulationStartSound1 = 0;
+ _fortressSimulationStartSound2 = 0;
+ _fortressSimulationHolo = nullptr;
+ _fortressSimulationStartup = nullptr;
+ _fortressSimulationHoloRate = 0;
+
+ _birdSinging = false;
+ _birdCrankStartTime = 0;
+ _birdSingEndTime = 0;
+ _bird = nullptr;
+
+ _snakeBox = nullptr;
}
Mechanical::~Mechanical() {
@@ -140,12 +170,12 @@ uint16 Mechanical::getVar(uint16 var) {
return _state.sirrusPanelState;
case 2: // Achenar's Secret Room Crate Lid Open and Blue Page Present
if (_state.achenarCrateOpened) {
- if (_globals.bluePagesInBook & 4 || _globals.heldPage == 3)
+ if (_globals.bluePagesInBook & 4 || _globals.heldPage == kBlueMechanicalPage)
return 2;
else
return 3;
} else {
- return _globals.bluePagesInBook & 4 || _globals.heldPage == 3;
+ return _globals.bluePagesInBook & 4 || _globals.heldPage == kBlueMechanicalPage;
}
case 3: // Achenar's Secret Room Crate State
return _state.achenarCrateOpened;
@@ -193,9 +223,9 @@ uint16 Mechanical::getVar(uint16 var) {
case 22: // Crystal Lit Flag - Red
return _crystalLit == 2;
case 102: // Red page
- return !(_globals.redPagesInBook & 4) && (_globals.heldPage != 9);
+ return !(_globals.redPagesInBook & 4) && (_globals.heldPage != kRedMechanicalPage);
case 103: // Blue page
- return !(_globals.bluePagesInBook & 4) && (_globals.heldPage != 3);
+ return !(_globals.bluePagesInBook & 4) && (_globals.heldPage != kBlueMechanicalPage);
default:
return MystScriptParser::getVar(var);
}
@@ -229,18 +259,18 @@ void Mechanical::toggleVar(uint16 var) {
break;
case 102: // Red page
if (!(_globals.redPagesInBook & 4)) {
- if (_globals.heldPage == 9)
- _globals.heldPage = 0;
+ if (_globals.heldPage == kRedMechanicalPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 9;
+ _globals.heldPage = kRedMechanicalPage;
}
break;
case 103: // Blue page
if (!(_globals.bluePagesInBook & 4)) {
- if (_globals.heldPage == 3)
- _globals.heldPage = 0;
+ if (_globals.heldPage == kBlueMechanicalPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 3;
+ _globals.heldPage = kBlueMechanicalPage;
}
break;
default:
diff --git a/engines/mohawk/myst_stacks/mechanical.h b/engines/mohawk/myst_stacks/mechanical.h
index 46cfe687a0..52cd7e7732 100644
--- a/engines/mohawk/myst_stacks/mechanical.h
+++ b/engines/mohawk/myst_stacks/mechanical.h
@@ -37,8 +37,8 @@ namespace MystStacks {
class Mechanical : public MystScriptParser {
public:
- Mechanical(MohawkEngine_Myst *vm);
- ~Mechanical();
+ explicit Mechanical(MohawkEngine_Myst *vm);
+ ~Mechanical() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
@@ -49,7 +49,7 @@ private:
void toggleVar(uint16 var) override;
bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() override { return 9931; }
+ uint16 getMap() override { return 9931; }
void birdSing_run();
void elevatorRotation_run();
diff --git a/engines/mohawk/myst_stacks/myst.cpp b/engines/mohawk/myst_stacks/myst.cpp
index dbc4ff55b8..4adee5fc20 100644
--- a/engines/mohawk/myst_stacks/myst.cpp
+++ b/engines/mohawk/myst_stacks/myst.cpp
@@ -37,7 +37,9 @@ namespace Mohawk {
namespace MystStacks {
Myst::Myst(MohawkEngine_Myst *vm) :
- MystScriptParser(vm), _state(_vm->_gameState->_myst) {
+ MystScriptParser(vm),
+ _state(_vm->_gameState->_myst),
+ _towerRotationCenter(Common::Point(383, 124)) {
setupOpcodes();
// Card ID preinitialized by the engine for use by opcode 18
@@ -45,22 +47,112 @@ Myst::Myst(MohawkEngine_Myst *vm) :
_savedCardId = 4329;
_towerRotationBlinkLabel = false;
+ _towerRotationBlinkLabelCount = 0;
+ _towerRotationSpeed = 0;
+ _towerRotationMapInitialized = 0;
+ _towerRotationMapRunning = false;
+ _towerRotationMapClicked = false;
+ _towerRotationMapTower = nullptr;
+ _towerRotationMapLabel = nullptr;
+ _towerRotationOverSpot = false;
+
_libraryBookcaseChanged = false;
+ _libraryBookcaseMoving = false;
+ _libraryBookcaseMovie = nullptr;
+ _libraryBookcaseSoundId = 0;
+
+ _libraryBookPagesTurning = false;
+ _libraryBookNumPages = 0;
+ _libraryBookBaseImage = 0;
+ _libraryBookSound1 = 0;
+ _libraryBookSound2 = 0;
+
+ _libraryCombinationBookPagesTurning = false;
+
+ for (uint i = 0; i < ARRAYSIZE(_fireplaceLines); i++) {
+ _fireplaceLines[i] = 0;
+ }
+
_dockVaultState = 0;
+
_cabinDoorOpened = 0;
_cabinHandleDown = 0;
_cabinMatchState = 2;
_cabinGaugeMovieEnabled = false;
+
+ _boilerPressureIncreasing = false;
+ _boilerPressureDecreasing = false;
+ _basementPressureIncreasing = false;
+ _basementPressureDecreasing = false;
+
_matchBurning = false;
+ _matchGoOutCnt = 0;
+ _matchGoOutTime = 0;
+
_tree = nullptr;
_treeAlcove = nullptr;
_treeStopped = false;
_treeMinPosition = 0;
+ _treeMinAccessiblePosition = 0;
+ _treeMaxAccessiblePosition = 0;
+
+ _imagerRunning = false;
+ _imagerRedButton = nullptr;
+ _imagerMovie = nullptr;
+ _imagerValidationRunning = false;
+ _imagerValidationCard = 0;
_imagerValidationStep = 0;
- _observatoryCurrentSlider = nullptr;
+ for (uint i = 0; i < ARRAYSIZE(_imagerSound); i++) {
+ _imagerSound[i] = 0;
+ }
+
_butterfliesMoviePlayed = false;
_state.treeLastMoveTime = _vm->_system->getMillis();
+
_rocketPianoSound = 0;
+ _rocketSlider1 = nullptr;
+ _rocketSlider2 = nullptr;
+ _rocketSlider3 = nullptr;
+ _rocketSlider4 = nullptr;
+ _rocketSlider5 = nullptr;
+ _rocketSliderSound = 0;
+ _rocketLeverPosition = 0;
+
+ _generatorControlRoomRunning = false;
+ _generatorVoltage = _state.generatorVoltage;
+
+ _observatoryRunning = false;
+ _observatoryMonthChanging = false;
+ _observatoryDayChanging = false;
+ _observatoryYearChanging = false;
+ _observatoryTimeChanging = false;
+ _observatoryVisualizer = nullptr;
+ _observatoryGoButton = nullptr;
+ _observatoryCurrentSlider = nullptr;
+ _observatoryDaySlider = nullptr;
+ _observatoryMonthSlider = nullptr;
+ _observatoryYearSlider = nullptr;
+ _observatoryTimeSlider = nullptr;
+ _observatoryLastTime = 0;
+ _observatoryNotInitialized = true;
+ _observatoryIncrement = 0;
+
+ _greenBookRunning = false;
+
+ _gullsFlying1 = false;
+ _gullsFlying2 = false;
+ _gullsFlying3 = false;
+ _gullsNextTime = 0;
+
+ _courtyardBoxSound = 0;
+
+ _clockTurningWheel = 0;
+ _clockWeightPosition = 0;
+ _clockMiddleGearMovedAlone = false;
+ _clockLeverPulled = false;
+ for (uint i = 0; i < ARRAYSIZE(_clockGearsPositions); i++) {
+ _clockGearsPositions[i] = 0;
+ }
}
Myst::~Myst() {
@@ -149,6 +241,8 @@ void Myst::setupOpcodes() {
REGISTER_OPCODE(175, Myst, o_observatoryYearSliderEndMove);
REGISTER_OPCODE(176, Myst, o_observatoryTimeSliderStartMove);
REGISTER_OPCODE(177, Myst, o_observatoryTimeSliderEndMove);
+ REGISTER_OPCODE(178, Myst, o_libraryBookPageTurnStartLeft);
+ REGISTER_OPCODE(179, Myst, o_libraryBookPageTurnStartRight);
REGISTER_OPCODE(180, Myst, o_libraryCombinationBookStop);
REGISTER_OPCODE(181, Myst, NOP);
REGISTER_OPCODE(182, Myst, o_cabinMatchLight);
@@ -211,6 +305,7 @@ void Myst::setupOpcodes() {
void Myst::disablePersistentScripts() {
_libraryBookcaseMoving = false;
_generatorControlRoomRunning = false;
+ _libraryBookPagesTurning = false;
_libraryCombinationBookPagesTurning = false;
_clockTurningWheel = 0;
_towerRotationMapRunning = false;
@@ -242,6 +337,9 @@ void Myst::runPersistentScripts() {
if (_libraryCombinationBookPagesTurning)
libraryCombinationBook_run();
+ if (_libraryBookPagesTurning)
+ libraryBook_run();
+
if (_libraryBookcaseMoving)
libraryBookcaseTransform_run();
@@ -308,7 +406,7 @@ uint16 Myst::getVar(uint16 var) {
case 0: // Myst Library Bookcase Closed
return _state.libraryBookcaseDoor;
case 1:
- if (_globals.ending != 4)
+ if (_globals.ending != kBooksDestroyed)
return _state.libraryBookcaseDoor != 1;
else if (_state.libraryBookcaseDoor == 1)
return 2;
@@ -389,13 +487,13 @@ uint16 Myst::getVar(uint16 var) {
&& _fireplaceLines[4] == 204
&& _fireplaceLines[5] == 250;
case 24: // Fireplace Blue Page Present
- if (_globals.ending != 4)
- return !(_globals.bluePagesInBook & 32) && (_globals.heldPage != 6);
+ if (_globals.ending != kBooksDestroyed)
+ return !(_globals.bluePagesInBook & 32) && (_globals.heldPage != kBlueFirePlacePage);
else
return 0;
case 25: // Fireplace Red Page Present
- if (_globals.ending != 4)
- return !(_globals.redPagesInBook & 32) && (_globals.heldPage != 12);
+ if (_globals.ending != kBooksDestroyed)
+ return !(_globals.redPagesInBook & 32) && (_globals.heldPage != kRedFirePlacePage);
else
return 0;
case 26: // Courtyard Image Box - Cross
@@ -536,25 +634,41 @@ uint16 Myst::getVar(uint16 var) {
return 10;
case 79: // Stellar Observatory Date - Year #4 (Right)
return (_state.observatoryYearSetting / 1) % 10;
- case 80: // Stellar Observatory Hour #1 - Left ( Number 1 (0) or Blank (10))
+ case 80: // Stellar Observatory Hour #1 - Left ( Hour digits can be 10 (Blank), or 0-2)
+ uint32 observatoryLeftMinutes;
if (!observatoryIsDDMMYYYY2400()) {
- if (_state.observatoryTimeSetting % (12 * 60) < (10 * 60))
+ // 12 Hour Format
+ observatoryLeftMinutes = _state.observatoryTimeSetting % (12 * 60);
+ if (observatoryLeftMinutes > 59 && observatoryLeftMinutes < (10 * 60))
return 10;
else
return 1;
} else {
- if (_state.observatoryTimeSetting < (10 * 60))
- return 10;
- else if (_state.observatoryTimeSetting < (20 * 60))
+ // 24 Hour Format
+ observatoryLeftMinutes = _state.observatoryTimeSetting;
+ if (observatoryLeftMinutes < (10 * 60))
+ return 0;
+ else if (observatoryLeftMinutes < (20 * 60))
return 1;
else
return 2;
}
case 81: // Stellar Observatory Hour #2 - Right
- if (!observatoryIsDDMMYYYY2400())
- return ((_state.observatoryTimeSetting % (12 * 60)) / 60) % 10;
- else
- return (_state.observatoryTimeSetting / 60) % 10;
+ uint32 observatoryRightMinutes,observatoryRightHour;
+ if (!observatoryIsDDMMYYYY2400()) {
+ // 12 Hour Format
+ observatoryRightMinutes = _state.observatoryTimeSetting % (12 * 60);
+ observatoryRightHour = observatoryRightMinutes / 60;
+ if (observatoryRightHour % 12 == 0)
+ return 2;
+ else
+ return observatoryRightHour % 10;
+ } else {
+ // 24 Hour Format
+ observatoryRightMinutes = _state.observatoryTimeSetting;
+ observatoryRightHour = observatoryRightMinutes / 60;
+ return observatoryRightHour % 10;
+ }
case 82: // Stellar Observatory Minutes #1 - Left
return (_state.observatoryTimeSetting % 60) / 10;
case 83: // Stellar Observatory Minutes #2 - Right
@@ -592,13 +706,13 @@ uint16 Myst::getVar(uint16 var) {
case 99: // Cabin Boiler Gas Valve Position
return _state.cabinValvePosition % 6;
case 102: // Red page
- if (_globals.ending != 4)
- return !(_globals.redPagesInBook & 1) && (_globals.heldPage != 7);
+ if (_globals.ending != kBooksDestroyed)
+ return !(_globals.redPagesInBook & 1) && (_globals.heldPage != kRedLibraryPage);
else
return 0;
case 103: // Blue page
- if (_globals.ending != 4)
- return !(_globals.bluePagesInBook & 1) && (_globals.heldPage != 1);
+ if (_globals.ending != kBooksDestroyed)
+ return !(_globals.bluePagesInBook & 1) && (_globals.heldPage != kBlueLibraryPage);
else
return 0;
case 300: // Rocket Ship Music Puzzle Slider State
@@ -656,19 +770,19 @@ void Myst::toggleVar(uint16 var) {
_state.rocketshipMarkerSwitch = (_state.rocketshipMarkerSwitch + 1) % 2;
break;
case 24: // Fireplace Blue Page
- if (_globals.ending != 4 && !(_globals.bluePagesInBook & 32)) {
- if (_globals.heldPage == 6)
- _globals.heldPage = 0;
+ if (_globals.ending != kBooksDestroyed && !(_globals.bluePagesInBook & 32)) {
+ if (_globals.heldPage == kBlueFirePlacePage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 6;
+ _globals.heldPage = kBlueFirePlacePage;
}
break;
case 25: // Fireplace Red page
- if (_globals.ending != 4 && !(_globals.redPagesInBook & 32)) {
- if (_globals.heldPage == 12)
- _globals.heldPage = 0;
+ if (_globals.ending != kBooksDestroyed && !(_globals.redPagesInBook & 32)) {
+ if (_globals.heldPage == kRedFirePlacePage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 12;
+ _globals.heldPage = kRedFirePlacePage;
}
break;
case 26: // Courtyard Image Box - Cross
@@ -688,30 +802,30 @@ void Myst::toggleVar(uint16 var) {
}
break;
case 41: // Vault white page
- if (_globals.ending != 4) {
+ if (_globals.ending != kBooksDestroyed) {
if (_dockVaultState == 1) {
_dockVaultState = 2;
- _globals.heldPage = 0;
+ _globals.heldPage = kNoPage;
} else if (_dockVaultState == 2) {
_dockVaultState = 1;
- _globals.heldPage = 13;
+ _globals.heldPage = kWhitePage;
}
}
break;
case 102: // Red page
- if (_globals.ending != 4 && !(_globals.redPagesInBook & 1)) {
- if (_globals.heldPage == 7)
- _globals.heldPage = 0;
+ if (_globals.ending != kBooksDestroyed && !(_globals.redPagesInBook & 1)) {
+ if (_globals.heldPage == kRedLibraryPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 7;
+ _globals.heldPage = kRedLibraryPage;
}
break;
case 103: // Blue page
- if (_globals.ending != 4 && !(_globals.bluePagesInBook & 1)) {
- if (_globals.heldPage == 1)
- _globals.heldPage = 0;
+ if (_globals.ending != kBooksDestroyed && !(_globals.bluePagesInBook & 1)) {
+ if (_globals.heldPage == kBlueLibraryPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 1;
+ _globals.heldPage = kBlueLibraryPage;
}
break;
default:
@@ -812,6 +926,10 @@ uint16 Myst::bookCountPages(uint16 var) {
}
void Myst::o_libraryBookPageTurnLeft(uint16 var, const ArgumentsArray &args) {
+ libraryBookPageTurnLeft();
+}
+
+void Myst::libraryBookPageTurnLeft() {
if (_libraryBookPage - 1 >= 0) {
_libraryBookPage--;
@@ -826,6 +944,10 @@ void Myst::o_libraryBookPageTurnLeft(uint16 var, const ArgumentsArray &args) {
}
void Myst::o_libraryBookPageTurnRight(uint16 var, const ArgumentsArray &args) {
+ libraryBookPageTurnRight();
+}
+
+void Myst::libraryBookPageTurnRight() {
if (_libraryBookPage + 1 < _libraryBookNumPages) {
_libraryBookPage++;
@@ -900,10 +1022,9 @@ void Myst::o_towerRotationStart(uint16 var, const ArgumentsArray &args) {
_vm->_cursor->setCursor(700);
- const Common::Point center = Common::Point(383, 124);
- Common::Point end = towerRotationMapComputeCoords(center, _state.towerRotationAngle);
+ Common::Point end = towerRotationMapComputeCoords(_state.towerRotationAngle);
towerRotationMapComputeAngle();
- towerRotationMapDrawLine(center, end);
+ towerRotationMapDrawLine(end, true);
_vm->_sound->playEffect(5378, true);
}
@@ -974,7 +1095,7 @@ void Myst::o_dockVaultOpen(uint16 var, const ArgumentsArray &args) {
(_state.observatoryMarkerSwitch == 1) &&
(_state.poolMarkerSwitch == 1) &&
(_state.rocketshipMarkerSwitch == 1)) {
- if (_globals.heldPage != 13 && _globals.ending != 4)
+ if (_globals.heldPage != kWhitePage && _globals.ending != kBooksDestroyed)
_dockVaultState = 2;
else
_dockVaultState = 1;
@@ -1017,50 +1138,48 @@ void Myst::o_bookGivePage(uint16 var, const ArgumentsArray &args) {
debugC(kDebugScript, "Card Id (Book Cover): %d", cardIdBookCover);
debugC(kDebugScript, "SoundId (Add Page): %d", soundIdAddPage);
- // No page or white page
- if (!_globals.heldPage || _globals.heldPage == 13) {
- _vm->changeToCard(cardIdBookCover, kTransitionDissolve);
- return;
- }
-
uint16 bookVar = 101;
uint16 mask = 0;
switch (_globals.heldPage) {
- case 7:
+ case kNoPage:
+ case kWhitePage:
+ _vm->changeToCard(cardIdBookCover, kTransitionDissolve);
+ return;
+ case kRedLibraryPage:
bookVar = 100;
// fallthrough
- case 1:
+ case kBlueLibraryPage:
mask = 1;
break;
- case 8:
+ case kRedSeleniticPage:
bookVar = 100;
// fallthrough
- case 2:
+ case kBlueSeleniticPage:
mask = 2;
break;
- case 9:
+ case kRedMechanicalPage:
bookVar = 100;
// fallthrough
- case 3:
+ case kBlueMechanicalPage:
mask = 4;
break;
- case 10:
+ case kRedStoneshipPage:
bookVar = 100;
// fallthrough
- case 4:
+ case kBlueStoneshipPage:
mask = 8;
break;
- case 11:
+ case kRedChannelwoodPage:
bookVar = 100;
// fallthrough
- case 5:
+ case kBlueChannelwoodPage:
mask = 16;
break;
- case 12:
+ case kRedFirePlacePage:
bookVar = 100;
// fallthrough
- case 6:
+ case kBlueFirePlacePage:
mask = 32;
break;
}
@@ -1082,16 +1201,16 @@ void Myst::o_bookGivePage(uint16 var, const ArgumentsArray &args) {
_globals.bluePagesInBook |= mask;
// Remove page from hand
- _globals.heldPage = 0;
+ _globals.heldPage = kNoPage;
_vm->_cursor->showCursor();
if (mask == 32) {
// You lose!
if (var == 100)
- _globals.currentAge = 9;
+ _globals.currentAge = kSirrusEnding;
else
- _globals.currentAge = 10;
+ _globals.currentAge = kAchenarEnding;
_vm->changeToCard(cardIdLose, kTransitionDissolve);
} else {
@@ -1521,6 +1640,7 @@ void Myst::observatoryIncrementMonth(int16 increment) {
}
_vm->_sound->playEffect(8500);
+ _vm->wait(20);
}
void Myst::observatoryMonthChange_run() {
@@ -1587,6 +1707,7 @@ void Myst::observatoryIncrementDay(int16 increment) {
}
_vm->_sound->playEffect(8500);
+ _vm->wait(20);
}
void Myst::observatoryDayChange_run() {
@@ -1647,6 +1768,7 @@ void Myst::observatoryIncrementYear(int16 increment) {
}
_vm->_sound->playEffect(8500);
+ _vm->wait(20);
}
void Myst::observatoryYearChange_run() {
@@ -1712,6 +1834,7 @@ void Myst::observatoryIncrementTime(int16 increment) {
}
_vm->_sound->playEffect(8500);
+ _vm->wait(20);
}
void Myst::observatoryTimeChange_run() {
@@ -2260,7 +2383,7 @@ void Myst::o_rocketPianoMove(uint16 var, const ArgumentsArray &args) {
if (piano.contains(mouse)) {
MystArea *resource = _vm->forceUpdateClickedResource();
- if (resource && resource->type == kMystAreaDrag) {
+ if (resource && resource->hasType(kMystAreaDrag)) {
// Press new key
key = static_cast<MystAreaDrag *>(resource);
src = key->getSubImage(1).rect;
@@ -2336,7 +2459,7 @@ void Myst::o_rocketLeverMove(uint16 var, const ArgumentsArray &args) {
uint16 soundId = lever->getList2(0);
if (soundId)
- _vm->_sound->playEffect(soundId);
+ _vm->playSoundBlocking(soundId);
// If rocket correctly powered
if (_state.generatorVoltage == 59 && !_state.generatorBreakers)
@@ -2407,6 +2530,7 @@ void Myst::observatoryUpdateMonth() {
_state.observatoryMonthSetting = month;
_state.observatoryMonthSlider = _observatoryMonthSlider->_pos.y;
_vm->_sound->playEffect(8500);
+ _vm->wait(20);
// Redraw digits
_vm->redrawArea(73);
@@ -2434,6 +2558,7 @@ void Myst::observatoryUpdateDay() {
_state.observatoryDaySetting = day;
_state.observatoryDaySlider = _observatoryDaySlider->_pos.y;
_vm->_sound->playEffect(8500);
+ _vm->wait(20);
// Redraw digits
_vm->redrawArea(75);
@@ -2462,6 +2587,7 @@ void Myst::observatoryUpdateYear() {
_state.observatoryYearSetting = year;
_state.observatoryYearSlider = _observatoryYearSlider->_pos.y;
_vm->_sound->playEffect(8500);
+ _vm->wait(20);
// Redraw digits
_vm->redrawArea(79);
@@ -2492,6 +2618,7 @@ void Myst::observatoryUpdateTime() {
_state.observatoryTimeSetting = time;
_state.observatoryTimeSlider = _observatoryTimeSlider->_pos.y;
_vm->_sound->playEffect(8500);
+ _vm->wait(20);
// Redraw digits
_vm->redrawArea(80);
@@ -2505,7 +2632,35 @@ void Myst::observatoryUpdateTime() {
}
}
+void Myst::o_libraryBookPageTurnStartLeft(uint16 var, const ArgumentsArray &args) {
+ _tempVar = -1;
+ libraryBookPageTurnLeft();
+ _startTime = _vm->_system->getMillis();
+ _libraryBookPagesTurning = true;
+}
+
+void Myst::o_libraryBookPageTurnStartRight(uint16 var, const ArgumentsArray &args) {
+ _tempVar = 1;
+ libraryBookPageTurnRight();
+ _startTime = _vm->_system->getMillis();
+ _libraryBookPagesTurning = true;
+}
+
+void Myst::libraryBook_run() {
+ uint32 time = _vm->_system->getMillis();
+ if (time >= _startTime + 500) {
+ if (_tempVar > 0) {
+ libraryBookPageTurnRight();
+ _startTime = time;
+ } else if (_tempVar < 0) {
+ libraryBookPageTurnLeft();
+ _startTime = time;
+ }
+ }
+}
+
void Myst::o_libraryCombinationBookStop(uint16 var, const ArgumentsArray &args) {
+ _libraryBookPagesTurning = false;
_libraryCombinationBookPagesTurning = false;
}
@@ -3021,7 +3176,7 @@ void Myst::towerRotationMap_run() {
} else {
// Stop blinking label
_towerRotationBlinkLabel = false;
- _towerRotationMapLabel->drawConditionalDataToScreen(0);
+ towerRotationMapRedraw();
// Blink tower
_startTime = time + 500;
@@ -3087,18 +3242,18 @@ uint16 Myst::towerRotationMapComputeAngle() {
return angle;
}
-Common::Point Myst::towerRotationMapComputeCoords(const Common::Point &center, uint16 angle) {
+Common::Point Myst::towerRotationMapComputeCoords(uint16 angle) {
Common::Point end;
// Polar to rect coords
double radians = angle * M_PI / 180.0;
- end.x = (int16)(center.x + cos(radians) * 310.0);
- end.y = (int16)(center.y + sin(radians) * 310.0);
+ end.x = (int16)(_towerRotationCenter.x + cos(radians) * 310.0);
+ end.y = (int16)(_towerRotationCenter.y + sin(radians) * 310.0);
return end;
}
-void Myst::towerRotationMapDrawLine(const Common::Point &center, const Common::Point &end) {
+void Myst::towerRotationMapDrawLine(const Common::Point &end, bool rotationLabelVisible) {
uint32 color;
if (_vm->getFeatures() & GF_ME) {
@@ -3133,18 +3288,22 @@ void Myst::towerRotationMapDrawLine(const Common::Point &center, const Common::P
_towerRotationMapTower->drawConditionalDataToScreen(0, false);
// Draw label
- _towerRotationMapLabel->drawConditionalDataToScreen(1, false);
+ _towerRotationMapLabel->drawConditionalDataToScreen(rotationLabelVisible ? 1 : 0, false);
// Draw line
- _vm->_gfx->drawLine(center, end, color);
+ _vm->_gfx->drawLine(_towerRotationCenter, end, color);
_vm->_gfx->copyBackBufferToScreen(rect);
}
void Myst::towerRotationMapRotate() {
- const Common::Point center = Common::Point(383, 124);
uint16 angle = towerRotationMapComputeAngle();
- Common::Point end = towerRotationMapComputeCoords(center, angle);
- towerRotationMapDrawLine(center, end);
+ Common::Point end = towerRotationMapComputeCoords(angle);
+ towerRotationMapDrawLine(end, true);
+}
+
+void Myst::towerRotationMapRedraw() {
+ Common::Point end = towerRotationMapComputeCoords(_state.towerRotationAngle);
+ towerRotationMapDrawLine(end, false);
}
void Myst::o_forechamberDoor_init(uint16 var, const ArgumentsArray &args) {
@@ -3559,7 +3718,7 @@ void Myst::greenBook_run() {
VideoEntryPtr book = _vm->playMovie(videoName, kMystStack);
book->moveTo(314, 76);
- if (_globals.ending != 4) {
+ if (_globals.ending != kBooksDestroyed) {
_tempVar = 2;
} else {
book->setBounds(Audio::Timestamp(0, loopStart, 600), Audio::Timestamp(0, loopEnd, 600));
diff --git a/engines/mohawk/myst_stacks/myst.h b/engines/mohawk/myst_stacks/myst.h
index 210012616f..ee89af115d 100644
--- a/engines/mohawk/myst_stacks/myst.h
+++ b/engines/mohawk/myst_stacks/myst.h
@@ -37,11 +37,11 @@ namespace MystStacks {
class Myst : public MystScriptParser {
public:
- Myst(MohawkEngine_Myst *vm);
- ~Myst();
+ explicit Myst(MohawkEngine_Myst *vm);
+ ~Myst() override;
- virtual void disablePersistentScripts() override;
- virtual void runPersistentScripts() override;
+ void disablePersistentScripts() override;
+ void runPersistentScripts() override;
protected:
void setupOpcodes();
@@ -49,12 +49,13 @@ protected:
void toggleVar(uint16 var) override;
bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() override { return 9934; }
+ uint16 getMap() override { return 9934; }
void towerRotationMap_run();
virtual void libraryBookcaseTransform_run();
void generatorControlRoom_run();
void libraryCombinationBook_run();
+ void libraryBook_run();
void clockWheel_run();
void matchBurn_run();
void boilerPressureIncrease_run();
@@ -137,6 +138,8 @@ protected:
DECLARE_OPCODE(o_observatoryYearSliderEndMove);
DECLARE_OPCODE(o_observatoryTimeSliderStartMove);
DECLARE_OPCODE(o_observatoryTimeSliderEndMove);
+ DECLARE_OPCODE(o_libraryBookPageTurnStartLeft);
+ DECLARE_OPCODE(o_libraryBookPageTurnStartRight);
DECLARE_OPCODE(o_libraryCombinationBookStop);
DECLARE_OPCODE(o_cabinMatchLight);
DECLARE_OPCODE(o_courtyardBoxEnter);
@@ -207,6 +210,7 @@ protected:
uint16 _rocketLeverPosition; // 296
VideoEntryPtr _rocketLinkBook; // 268
+ bool _libraryBookPagesTurning;
bool _libraryCombinationBookPagesTurning;
int16 _libraryBookPage; // 86
uint16 _libraryBookNumPages; // 88
@@ -259,6 +263,7 @@ protected:
uint16 _towerRotationSpeed; // 124
bool _towerRotationMapClicked; // 132
bool _towerRotationOverSpot; // 136
+ const Common::Point _towerRotationCenter;
bool _matchBurning;
uint16 _matchGoOutCnt;
@@ -309,6 +314,8 @@ protected:
uint16 rocketSliderGetSound(uint16 pos);
void rocketCheckSolution();
+ void libraryBookPageTurnLeft();
+ void libraryBookPageTurnRight();
void libraryCombinationBookTurnRight();
void libraryCombinationBookTurnLeft();
@@ -326,10 +333,11 @@ protected:
void clockResetGear(uint16 gear);
void towerRotationMapRotate();
+ void towerRotationMapRedraw();
void towerRotationDrawBuildings();
uint16 towerRotationMapComputeAngle();
- Common::Point towerRotationMapComputeCoords(const Common::Point &center, uint16 angle);
- void towerRotationMapDrawLine(const Common::Point &center, const Common::Point &end);
+ Common::Point towerRotationMapComputeCoords(uint16 angle);
+ void towerRotationMapDrawLine(const Common::Point &end, bool rotationLabelVisible);
void boilerFireInit();
void boilerFireUpdate(bool init);
diff --git a/engines/mohawk/myst_stacks/preview.cpp b/engines/mohawk/myst_stacks/preview.cpp
index bc0dd04360..348a195dea 100644
--- a/engines/mohawk/myst_stacks/preview.cpp
+++ b/engines/mohawk/myst_stacks/preview.cpp
@@ -34,9 +34,18 @@
namespace Mohawk {
namespace MystStacks {
-Preview::Preview(MohawkEngine_Myst *vm) : Myst(vm) {
+Preview::Preview(MohawkEngine_Myst *vm) :
+ Myst(vm) {
setupOpcodes();
_vm->_cursor->hideCursor();
+
+ _libraryState = 0;
+ _library = nullptr;
+
+ _speechRunning = false;
+ _speechStep = 0;
+ _currentCue = 0;
+ _speechNextTime = 0;
}
Preview::~Preview() {
@@ -84,7 +93,7 @@ void Preview::o_stayHere(uint16 var, const ArgumentsArray &args) {
void Preview::o_speechStop(uint16 var, const ArgumentsArray &args) {
_vm->_sound->stopSpeech();
_speechRunning = false;
- _globals.currentAge = 2;
+ _globals.currentAge = kMystLibrary;
}
void Preview::speechUpdateCue() {
@@ -196,7 +205,7 @@ void Preview::speech_run() {
_vm->changeToCard(4329, kTransitionDissolve);
_speechRunning = false;
- _globals.currentAge = 2;
+ _globals.currentAge = kMystLibrary;
_vm->_cursor->showCursor();
break;
diff --git a/engines/mohawk/myst_stacks/preview.h b/engines/mohawk/myst_stacks/preview.h
index 6c0fe83b42..a27fec7cd1 100644
--- a/engines/mohawk/myst_stacks/preview.h
+++ b/engines/mohawk/myst_stacks/preview.h
@@ -39,8 +39,8 @@ namespace MystStacks {
class Preview : public Myst {
public:
- Preview(MohawkEngine_Myst *vm);
- ~Preview();
+ explicit Preview(MohawkEngine_Myst *vm);
+ ~Preview() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
diff --git a/engines/mohawk/myst_stacks/selenitic.cpp b/engines/mohawk/myst_stacks/selenitic.cpp
index 0f1949f128..239030645c 100644
--- a/engines/mohawk/myst_stacks/selenitic.cpp
+++ b/engines/mohawk/myst_stacks/selenitic.cpp
@@ -36,15 +36,48 @@ namespace Mohawk {
namespace MystStacks {
Selenitic::Selenitic(MohawkEngine_Myst *vm) :
- MystScriptParser(vm), _state(vm->_gameState->_selenitic) {
+ MystScriptParser(vm),
+ _state(vm->_gameState->_selenitic) {
setupOpcodes();
+
_mazeRunnerPosition = 288;
_mazeRunnerDirection = 8;
_mazeRunnerDoorOpened = false;
+ _mazeRunnerWindow = nullptr;
+ _mazeRunnerCompass = nullptr;
+ _mazeRunnerLight = nullptr;
+ _mazeRunnerRightButton = nullptr;
+ _mazeRunnerLeftButton = nullptr;
+ _soundReceiverRunning = false;
_soundReceiverDirection = 0;
_soundReceiverStartTime = 0;
_soundReceiverNearBlinkCounter = 0;
+ _soundReceiverSigmaPressed = false;
+
+ for (uint i = 0; i < ARRAYSIZE(_soundReceiverSources); i++) {
+ _soundReceiverSources[i] = nullptr;
+ }
+
+ _soundReceiverCurrentSource = nullptr;
+ _soundReceiverPosition = nullptr;
+ _soundReceiverSpeed = kSoundReceiverSpeedStill;
+ _soundReceiverViewer = nullptr;
+ _soundReceiverRightButton = nullptr;
+ _soundReceiverLeftButton = nullptr;
+ _soundReceiverAngle1 = nullptr;
+ _soundReceiverAngle2 = nullptr;
+ _soundReceiverAngle3 = nullptr;
+ _soundReceiverAngle4 = nullptr;
+ _soundReceiverSigmaButton = nullptr;
+
+ _soundLockSoundId = 0;
+ _soundLockSlider1 = nullptr;
+ _soundLockSlider2 = nullptr;
+ _soundLockSlider3 = nullptr;
+ _soundLockSlider4 = nullptr;
+ _soundLockSlider5 = nullptr;
+ _soundLockButton = nullptr;
}
Selenitic::~Selenitic() {
@@ -157,9 +190,9 @@ uint16 Selenitic::getVar(uint16 var) {
case 33: // Maze runner at entry
return _mazeRunnerPosition != 288;
case 102: // Red page
- return !(_globals.redPagesInBook & 2) && (_globals.heldPage != 8);
+ return !(_globals.redPagesInBook & 2) && (_globals.heldPage != kRedSeleniticPage);
case 103: // Blue page
- return !(_globals.bluePagesInBook & 2) && (_globals.heldPage != 2);
+ return !(_globals.bluePagesInBook & 2) && (_globals.heldPage != kBlueSeleniticPage);
default:
return MystScriptParser::getVar(var);
}
@@ -190,18 +223,18 @@ void Selenitic::toggleVar(uint16 var) {
break;
case 102: // Red page
if (!(_globals.redPagesInBook & 2)) {
- if (_globals.heldPage == 8)
- _globals.heldPage = 0;
+ if (_globals.heldPage == kRedSeleniticPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 8;
+ _globals.heldPage = kRedSeleniticPage;
}
break;
case 103: // Blue page
if (!(_globals.bluePagesInBook & 2)) {
- if (_globals.heldPage == 2)
- _globals.heldPage = 0;
+ if (_globals.heldPage == kBlueSeleniticPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 2;
+ _globals.heldPage = kBlueSeleniticPage;
}
break;
default:
@@ -636,7 +669,7 @@ void Selenitic::soundReceiverLeftRight(uint direction) {
_vm->_sound->stopEffect();
_soundReceiverDirection = direction;
- _soundReceiverSpeed = 1;
+ _soundReceiverSpeed = kSoundReceiverSpeedSlow;
_soundReceiverStartTime = _vm->_system->getMillis();
soundReceiverUpdate();
@@ -918,7 +951,7 @@ void Selenitic::soundReceiver_run() {
if (_soundReceiverDirection) {
uint32 currentTime = _vm->_system->getMillis();
- if (_soundReceiverSpeed == 50 && currentTime > _soundReceiverStartTime + 500) {
+ if (_soundReceiverSpeed == kSoundReceiverSpeedFast && currentTime > _soundReceiverStartTime + 500) {
soundReceiverIncreaseSpeed();
_soundReceiverStartTime = currentTime;
} else if (currentTime > _soundReceiverStartTime + 1000) {
@@ -926,8 +959,9 @@ void Selenitic::soundReceiver_run() {
_soundReceiverStartTime = currentTime;
}
- if (currentTime > _soundReceiverStartTime + 100)
+ if (_soundReceiverSpeed > kSoundReceiverSpeedSlow || currentTime > _soundReceiverStartTime + 100) {
soundReceiverUpdate();
+ }
} else if (!_soundReceiverSigmaPressed) {
soundReceiverUpdateSound();
}
@@ -936,14 +970,20 @@ void Selenitic::soundReceiver_run() {
void Selenitic::soundReceiverIncreaseSpeed() {
switch (_soundReceiverSpeed) {
- case 1:
- _soundReceiverSpeed = 10;
+ case kSoundReceiverSpeedStill:
+ // Should not happen
break;
- case 10:
- _soundReceiverSpeed = 50;
+ case kSoundReceiverSpeedSlow:
+ _soundReceiverSpeed = kSoundReceiverSpeedNormal;
+ break;
+ case kSoundReceiverSpeedNormal:
+ _soundReceiverSpeed = kSoundReceiverSpeedFast;
+ break;
+ case kSoundReceiverSpeedFast:
+ _soundReceiverSpeed = kSoundReceiverSpeedFaster;
break;
- case 50:
- _soundReceiverSpeed = 100;
+ case kSoundReceiverSpeedFaster:
+ // Can't go faster
break;
}
}
@@ -990,7 +1030,7 @@ uint16 Selenitic::soundReceiverCurrentSound(uint16 source, uint16 position) {
if (sourceEnabled) {
if (position == solution) {
soundId = soundIdGood;
- } else if (position > solution && position <= solution + 50) {
+ } else if (position > solution && position < solution + 50) {
_soundReceiverNearBlinkCounter++;
if (_soundReceiverNearBlinkCounter % 2) {
_soundReceiverLeftButton->drawConditionalDataToScreen(2);
@@ -998,7 +1038,7 @@ uint16 Selenitic::soundReceiverCurrentSound(uint16 source, uint16 position) {
_soundReceiverLeftButton->drawConditionalDataToScreen(0);
}
soundId = soundIdNear;
- } else if (position < solution && position >= solution - 50) {
+ } else if (position < solution && position > solution - 50) {
_soundReceiverNearBlinkCounter++;
if (_soundReceiverNearBlinkCounter % 2) {
_soundReceiverRightButton->drawConditionalDataToScreen(2);
@@ -1072,7 +1112,7 @@ void Selenitic::o_soundReceiver_init(uint16 var, const ArgumentsArray &args) {
void Selenitic::o_soundLock_init(uint16 var, const ArgumentsArray &args) {
for (uint i = 0; i < _vm->_resources.size(); i++) {
- if (_vm->_resources[i]->type == kMystAreaSlider) {
+ if (_vm->_resources[i]->hasType(kMystAreaSlider)) {
switch (_vm->_resources[i]->getImageSwitchVar()) {
case 20:
_soundLockSlider1 = _vm->getViewResource<MystAreaSlider>(i);
@@ -1095,7 +1135,7 @@ void Selenitic::o_soundLock_init(uint16 var, const ArgumentsArray &args) {
_soundLockSlider5->setStep(_state.soundLockSliderPositions[4]);
break;
}
- } else if (_vm->_resources[i]->type == kMystAreaImageSwitch && _vm->_resources[i]->getImageSwitchVar() == 28) {
+ } else if (_vm->_resources[i]->hasType(kMystAreaImageSwitch) && _vm->_resources[i]->getImageSwitchVar() == 28) {
_soundLockButton = _vm->getViewResource<MystAreaImageSwitch>(i);
}
}
diff --git a/engines/mohawk/myst_stacks/selenitic.h b/engines/mohawk/myst_stacks/selenitic.h
index 341886d20b..fc20006165 100644
--- a/engines/mohawk/myst_stacks/selenitic.h
+++ b/engines/mohawk/myst_stacks/selenitic.h
@@ -38,8 +38,8 @@ namespace MystStacks {
class Selenitic : public MystScriptParser {
public:
- Selenitic(MohawkEngine_Myst *vm);
- ~Selenitic();
+ explicit Selenitic(MohawkEngine_Myst *vm);
+ ~Selenitic() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
@@ -50,7 +50,7 @@ private:
void toggleVar(uint16 var) override;
bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() override { return 9930; }
+ uint16 getMap() override { return 9930; }
DECLARE_OPCODE(o_mazeRunnerMove);
DECLARE_OPCODE(o_mazeRunnerSoundRepeat);
@@ -74,6 +74,14 @@ private:
DECLARE_OPCODE(o_mazeRunnerRight_init);
DECLARE_OPCODE(o_mazeRunnerLeft_init);
+ enum SoundReceiverSpeed {
+ kSoundReceiverSpeedStill = 0,
+ kSoundReceiverSpeedSlow = 1,
+ kSoundReceiverSpeedNormal = 5, // The original has this at 10
+ kSoundReceiverSpeedFast = 10, // The original has this at 50 too fast!
+ kSoundReceiverSpeedFaster = 13 // The original has this at 100, way too fast!
+ };
+
void soundReceiver_run();
MystGameState::Selenitic &_state;
@@ -84,7 +92,7 @@ private:
MystAreaImageSwitch *_soundReceiverCurrentSource; // 112
uint16 *_soundReceiverPosition; // 116
uint16 _soundReceiverDirection; // 120
- uint16 _soundReceiverSpeed; // 122
+ SoundReceiverSpeed _soundReceiverSpeed; // 122
uint32 _soundReceiverStartTime; //124
uint _soundReceiverNearBlinkCounter;
MystAreaImageSwitch *_soundReceiverViewer; // 128
diff --git a/engines/mohawk/myst_stacks/slides.cpp b/engines/mohawk/myst_stacks/slides.cpp
index f8c388d7bc..25d5cf480d 100644
--- a/engines/mohawk/myst_stacks/slides.cpp
+++ b/engines/mohawk/myst_stacks/slides.cpp
@@ -33,9 +33,15 @@
namespace Mohawk {
namespace MystStacks {
-Slides::Slides(MohawkEngine_Myst *vm) : MystScriptParser(vm) {
+Slides::Slides(MohawkEngine_Myst *vm) :
+ MystScriptParser(vm) {
setupOpcodes();
+
_vm->_cursor->hideCursor();
+
+ _cardSwapEnabled = false;
+ _nextCardID = 0;
+ _nextCardTime = 0;
}
Slides::~Slides() {
diff --git a/engines/mohawk/myst_stacks/slides.h b/engines/mohawk/myst_stacks/slides.h
index 63fd9c823e..6970c3b3f0 100644
--- a/engines/mohawk/myst_stacks/slides.h
+++ b/engines/mohawk/myst_stacks/slides.h
@@ -37,8 +37,8 @@ namespace MystStacks {
class Slides : public MystScriptParser {
public:
- Slides(MohawkEngine_Myst *vm);
- ~Slides();
+ explicit Slides(MohawkEngine_Myst *vm);
+ ~Slides() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
diff --git a/engines/mohawk/myst_stacks/stoneship.cpp b/engines/mohawk/myst_stacks/stoneship.cpp
index 534efe7197..cd1db68d44 100644
--- a/engines/mohawk/myst_stacks/stoneship.cpp
+++ b/engines/mohawk/myst_stacks/stoneship.cpp
@@ -37,10 +37,14 @@ namespace Mohawk {
namespace MystStacks {
Stoneship::Stoneship(MohawkEngine_Myst *vm) :
- MystScriptParser(vm), _state(vm->_gameState->_stoneship) {
+ MystScriptParser(vm),
+ _state(vm->_gameState->_stoneship) {
setupOpcodes();
_tunnelRunning = false;
+ _tunnelNextTime = 0;
+ _tunnelAlarmSound = 0;
+ _tunnelImagesCount = 0;
_state.lightState = 0;
_state.generatorDepletionTime = 0;
@@ -61,6 +65,31 @@ Stoneship::Stoneship(MohawkEngine_Myst *vm) :
_state.generatorPowerAvailable = 2;
else
_state.generatorPowerAvailable = 0;
+
+ _batteryCharging = false;
+ _batteryDepleting = false;
+ _batteryNextTime = 0;
+ _batteryLastCharge = 0;
+ _batteryGaugeRunning = false;
+ _batteryGauge = nullptr;
+
+ _hologramTurnedOn = 0;
+ _hologramDisplay = nullptr;
+ _hologramSelection = nullptr;
+ _hologramDisplayPos = 0;
+
+ _telescopeRunning = false;
+ _telescopePosition = 0;
+ _telescopePanorama = 0;
+ _telescopeOldMouse = 0;
+ _telescopeLighthouseOff = 0;
+ _telescopeLighthouseOn = 0;
+ _telescopeLighthouseState = false;
+ _telescopeNexTime = 0;
+
+ _cloudOrbMovie = nullptr;
+ _cloudOrbSound = 0;
+ _cloudOrbStopSound = 0;
}
Stoneship::~Stoneship() {
@@ -251,9 +280,9 @@ uint16 Stoneship::getVar(uint16 var) {
return 0; // Closed
}
case 102: // Red page
- return !(_globals.redPagesInBook & 8) && (_globals.heldPage != 10);
+ return !(_globals.redPagesInBook & 8) && (_globals.heldPage != kRedStoneshipPage);
case 103: // Blue page
- return !(_globals.bluePagesInBook & 8) && (_globals.heldPage != 4);
+ return !(_globals.bluePagesInBook & 8) && (_globals.heldPage != kBlueStoneshipPage);
default:
return MystScriptParser::getVar(var);
}
@@ -305,18 +334,18 @@ void Stoneship::toggleVar(uint16 var) {
break;
case 102: // Red page
if (!(_globals.redPagesInBook & 8)) {
- if (_globals.heldPage == 10)
- _globals.heldPage = 0;
+ if (_globals.heldPage == kRedStoneshipPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 10;
+ _globals.heldPage = kRedStoneshipPage;
}
break;
case 103: // Blue page
if (!(_globals.bluePagesInBook & 8)) {
- if (_globals.heldPage == 4)
- _globals.heldPage = 0;
+ if (_globals.heldPage == kBlueStoneshipPage)
+ _globals.heldPage = kNoPage;
else
- _globals.heldPage = 4;
+ _globals.heldPage = kBlueStoneshipPage;
}
break;
default:
@@ -399,7 +428,7 @@ void Stoneship::o_pumpTurnOff(uint16 var, const ArgumentsArray &args) {
for (uint i = 0; i < _vm->_resources.size(); i++) {
MystArea *resource = _vm->_resources[i];
- if (resource->type == kMystAreaImageSwitch && resource->getImageSwitchVar() == buttonVar) {
+ if (resource->hasType(kMystAreaImageSwitch) && resource->getImageSwitchVar() == buttonVar) {
static_cast<MystAreaImageSwitch *>(resource)->drawConditionalDataToScreen(0, true);
break;
}
diff --git a/engines/mohawk/myst_stacks/stoneship.h b/engines/mohawk/myst_stacks/stoneship.h
index dca7ce8fd3..64f58ec427 100644
--- a/engines/mohawk/myst_stacks/stoneship.h
+++ b/engines/mohawk/myst_stacks/stoneship.h
@@ -37,8 +37,8 @@ namespace MystStacks {
class Stoneship : public MystScriptParser {
public:
- Stoneship(MohawkEngine_Myst *vm);
- ~Stoneship();
+ explicit Stoneship(MohawkEngine_Myst *vm);
+ ~Stoneship() override;
void disablePersistentScripts() override;
void runPersistentScripts() override;
@@ -49,7 +49,7 @@ private:
void toggleVar(uint16 var) override;
bool setVarValue(uint16 var, uint16 value) override;
- virtual uint16 getMap() override { return 9933; }
+ uint16 getMap() override { return 9933; }
DECLARE_OPCODE(o_pumpTurnOff);
DECLARE_OPCODE(o_brotherDoorOpen);
diff --git a/engines/mohawk/myst_state.cpp b/engines/mohawk/myst_state.cpp
index 213a976413..c65ece55d5 100644
--- a/engines/mohawk/myst_state.cpp
+++ b/engines/mohawk/myst_state.cpp
@@ -41,10 +41,11 @@ MystSaveMetadata::MystSaveMetadata() {
saveHour = 0;
saveMinute = 0;
totalPlayTime = 0;
+ autoSave = false;
}
bool MystSaveMetadata::sync(Common::Serializer &s) {
- static const Common::Serializer::Version kCurrentVersion = 1;
+ static const Common::Serializer::Version kCurrentVersion = 2;
if (!s.syncVersion(kCurrentVersion)) {
return false;
@@ -57,10 +58,13 @@ bool MystSaveMetadata::sync(Common::Serializer &s) {
s.syncAsByte(saveMinute);
s.syncString(saveDescription);
s.syncAsUint32LE(totalPlayTime);
+ s.syncAsByte(autoSave, 2);
return true;
}
+const int MystGameState::kAutoSaveSlot = 0;
+
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));
@@ -78,8 +82,10 @@ MystGameState::MystGameState(MohawkEngine_Myst *vm, Common::SaveFileManager *sav
// Unknown
_globals.u0 = 2;
// Current Age / Stack - Start in Myst
- _globals.currentAge = 7;
+ _globals.currentAge = kMystStart;
+ _globals.heldPage = kNoPage;
_globals.u1 = 1;
+ _globals.ending = kDniNotVisited;
// Library Bookcase Door - Default to Up
_myst.libraryBookcaseDoor = 1;
@@ -121,13 +127,13 @@ bool MystGameState::load(int slot) {
// Set our default cursor
_vm->_cursor->showCursor();
- if (_globals.heldPage == 0 || _globals.heldPage > 13)
+ if (_globals.heldPage == kNoPage)
_vm->setMainCursor(kDefaultMystCursor);
- else if (_globals.heldPage < 7)
+ else if (_globals.heldPage < kRedLibraryPage) //A blue page is held
_vm->setMainCursor(kBluePageCursor);
- else if (_globals.heldPage < 13)
+ else if (_globals.heldPage < kWhitePage) //A red page is held
_vm->setMainCursor(kRedPageCursor);
- else // if (globals.heldPage == 13)
+ else
_vm->setMainCursor(kWhitePageCursor);
return true;
@@ -178,12 +184,12 @@ void MystGameState::loadMetadata(int slot) {
delete metadataFile;
}
-bool MystGameState::save(int slot, const Common::String &desc) {
+bool MystGameState::save(int slot, const Common::String &desc, bool autoSave) {
if (!saveState(slot)) {
return false;
}
- updateMetadateForSaving(desc);
+ updateMetadateForSaving(desc, autoSave);
return saveMetadata(slot);
}
@@ -214,7 +220,7 @@ Common::String MystGameState::buildMetadataFilename(int slot) {
return Common::String::format("myst-%03d.mym", slot);
}
-void MystGameState::updateMetadateForSaving(const Common::String &desc) {
+void MystGameState::updateMetadateForSaving(const Common::String &desc, bool autoSave) {
// Update save creation info
TimeDate t;
g_system->getTimeAndDate(t);
@@ -225,6 +231,7 @@ void MystGameState::updateMetadateForSaving(const Common::String &desc) {
_metadata.saveMinute = t.tm_min;
_metadata.saveDescription = desc;
_metadata.totalPlayTime = _vm->getTotalPlayTime();
+ _metadata.autoSave = autoSave;
}
bool MystGameState::saveMetadata(int slot) {
@@ -249,12 +256,43 @@ bool MystGameState::saveMetadata(int slot) {
return true;
}
+bool MystGameState::isAutoSaveAllowed() {
+ // Open autosave slot and see if it an autosave
+ // Autosaving will be enabled if it is an autosave or if there is no save in that slot
+
+ Common::String dataFilename = buildSaveFilename(kAutoSaveSlot);
+ Common::ScopedPtr<Common::InSaveFile> dataFile(g_system->getSavefileManager()->openForLoading(dataFilename));
+ if (!dataFile) { // Cannot load non-meta file, enable autosave
+ return true;
+ }
+
+ Common::String metaFilename = buildMetadataFilename(kAutoSaveSlot);
+ Common::ScopedPtr<Common::InSaveFile> metadataFile(g_system->getSavefileManager()->openForLoading(metaFilename));
+ if (!metadataFile) { // Can load non-meta file, but not metafile, could be a save from the original, disable autosave
+ return false;
+ }
+
+ Common::Serializer m(metadataFile.get(), nullptr);
+
+ // Read the metadata file
+ Mohawk::MystSaveMetadata metadata;
+ if (!metadata.sync(m)) { // the save in the autosave slot is corrupted, enable autosave
+ return true;
+ }
+
+ return metadata.autoSave;
+}
+
SaveStateDescriptor MystGameState::querySaveMetaInfos(int slot) {
// Open the metadata file
Common::String filename = buildMetadataFilename(slot);
Common::InSaveFile *metadataFile = g_system->getSavefileManager()->openForLoading(filename);
+
+ SaveStateDescriptor desc;
+ desc.setWriteProtectedFlag(slot == kAutoSaveSlot);
+
if (!metadataFile) {
- return SaveStateDescriptor();
+ return desc;
}
Common::Serializer m(metadataFile, nullptr);
@@ -263,16 +301,23 @@ SaveStateDescriptor MystGameState::querySaveMetaInfos(int slot) {
Mohawk::MystSaveMetadata metadata;
if (!metadata.sync(m)) {
delete metadataFile;
- return SaveStateDescriptor();
+ return desc;
}
// Set the save description
- SaveStateDescriptor desc;
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));
+ if (metadata.autoSave) // Allow non-saves to be deleted, but not autosaves
+ desc.setDeletableFlag(slot != kAutoSaveSlot);
+
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*metadataFile, thumbnail)) {
+ delete metadataFile;
+ return desc;
+ }
+ desc.setThumbnail(thumbnail);
delete metadataFile;
diff --git a/engines/mohawk/myst_state.h b/engines/mohawk/myst_state.h
index 7d5f3f7102..28bbf60d63 100644
--- a/engines/mohawk/myst_state.h
+++ b/engines/mohawk/myst_state.h
@@ -47,14 +47,61 @@ struct MystSaveMetadata {
uint32 totalPlayTime;
+ bool autoSave;
+
Common::String saveDescription;
MystSaveMetadata();
bool sync(Common::Serializer &s);
};
+// Page being held
+enum HeldPage {
+ kNoPage = 0,
+ kBlueLibraryPage = 1,
+ kBlueSeleniticPage = 2,
+ kBlueMechanicalPage = 3,
+ kBlueStoneshipPage = 4,
+ kBlueChannelwoodPage = 5,
+ kBlueFirePlacePage = 6,
+ kRedLibraryPage = 7,
+ kRedSeleniticPage = 8,
+ kRedMechanicalPage = 9,
+ kRedStoneshipPage = 10,
+ kRedChannelwoodPage = 11,
+ kRedFirePlacePage = 12,
+ kWhitePage = 13
+};
+
+// Age the player is in
+enum ActiveAge {
+ kSelenitic = 0,
+ kStoneship = 1,
+ kMystLibrary = 2,
+ kMechanical = 3,
+ kChannelwood = 4,
+ kIntro = 5,
+ kDni = 6,
+ kMystStart = 7,
+ kCredits = 8,
+ kSirrusEnding = 9,
+ kAchenarEnding = 10
+};
+
+// Various states that Atrus can be in when in Dni
+enum DniEnding {
+ kDniNotVisited = 0, // Player hasn't been to Dni/K'veer yet
+ kAtrusWantsPage = 1, // Player is in Dni with the white page
+ kAtrusLeaves = 2, // Atrus leaves Dni after receiving the white page
+ kForgotPage = 3, // Player has entered Dni without bringing the white page
+ kBooksDestroyed = 4 // Atrus returns to Dni after previously leaving
+ // and destroying the books of his sons
+};
+
class MystGameState {
public:
+ static const int kAutoSaveSlot;
+
MystGameState(MohawkEngine_Myst*, Common::SaveFileManager*);
~MystGameState();
@@ -62,7 +109,8 @@ public:
static Common::String querySaveDescription(int slot);
bool load(int slot);
- bool save(int slot, const Common::String &desc);
+ bool save(int slot, const Common::String &desc, bool autoSave);
+ bool isAutoSaveAllowed();
static void deleteSave(int slot);
void addZipDest(uint16 stack, uint16 view);
@@ -80,14 +128,14 @@ public:
*/
struct Globals {
uint16 u0;
- uint16 currentAge;
- uint16 heldPage;
+ ActiveAge currentAge;
+ HeldPage heldPage;
uint16 u1;
uint16 transitions;
uint16 zipMode;
uint16 redPagesInBook;
uint16 bluePagesInBook;
- uint16 ending;
+ DniEnding ending;
} _globals;
/* 50 Myst Specific Variables :
@@ -297,7 +345,7 @@ private:
bool loadState(int slot);
void loadMetadata(int slot);
bool saveState(int slot);
- void updateMetadateForSaving(const Common::String &desc);
+ void updateMetadateForSaving(const Common::String &desc, bool autoSave);
bool saveMetadata(int slot);
// The values in these regions are lists of VIEW resources
diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp
index b0ae8dd6ea..ea44ca7879 100644
--- a/engines/mohawk/resource.cpp
+++ b/engines/mohawk/resource.cpp
@@ -32,7 +32,7 @@ namespace Mohawk {
// Base Archive code
Archive::Archive() {
- _stream = 0;
+ _stream = nullptr;
}
Archive::~Archive() {
@@ -57,7 +57,7 @@ bool Archive::openFile(const Common::String &fileName) {
void Archive::close() {
_types.clear();
- delete _stream; _stream = 0;
+ delete _stream; _stream = nullptr;
}
bool Archive::hasResource(uint32 tag, uint16 id) const {
diff --git a/engines/mohawk/resource.h b/engines/mohawk/resource.h
index 12c5a139e4..809c55da1d 100644
--- a/engines/mohawk/resource.h
+++ b/engines/mohawk/resource.h
@@ -93,10 +93,6 @@ namespace Mohawk {
#define ID_BMAP MKTAG('B','M','A','P') // Old Mohawk Bitmap
#define ID_BCOD MKTAG('B','C','O','D') // Book Code
-// JamesMath Resource FourCC's
-#define ID_TANM MKTAG('t','A','N','M') // Animation?
-#define ID_TMFO MKTAG('t','M','F','O') // ???
-
// CSTime Resource FourCC's
#define ID_CINF MKTAG('C','I','N','F') // Case Info
#define ID_CONV MKTAG('C','O','N','V') // Conversation
@@ -112,10 +108,6 @@ namespace Mohawk {
#define ID_DATA MKTAG('D','a','t','a') // Game Sound Chunk
#define ID_CUE MKTAG('C','u','e','#') // Game Sound Chunk
-// Mohawk MIDI Tags
-#define ID_MIDI MKTAG('M','I','D','I') // Game Sound (Third Tag), instead of WAVE
-#define ID_PRG MKTAG('P','r','g','#') // MIDI Patch
-
// Common Resource FourCC's
#define ID_TBMP MKTAG('t','B','M','P') // Standard Mohawk Bitmap
#define ID_TWAV MKTAG('t','W','A','V') // Standard Mohawk Sound
@@ -170,25 +162,25 @@ protected:
class MohawkArchive : public Archive {
public:
MohawkArchive() : Archive() {}
- ~MohawkArchive() {}
+ ~MohawkArchive() override {}
- bool openStream(Common::SeekableReadStream *stream);
+ bool openStream(Common::SeekableReadStream *stream) override;
};
class LivingBooksArchive_v1 : public Archive {
public:
LivingBooksArchive_v1() : Archive() {}
- ~LivingBooksArchive_v1() {}
+ ~LivingBooksArchive_v1() override {}
- bool openStream(Common::SeekableReadStream *stream);
+ bool openStream(Common::SeekableReadStream *stream) override;
};
class DOSArchive_v2 : public Archive {
public:
DOSArchive_v2() : Archive() {}
- ~DOSArchive_v2() {}
+ ~DOSArchive_v2() override {}
- bool openStream(Common::SeekableReadStream *stream);
+ bool openStream(Common::SeekableReadStream *stream) override;
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/resource_cache.cpp b/engines/mohawk/resource_cache.cpp
index 0c19934278..ab1758b673 100644
--- a/engines/mohawk/resource_cache.cpp
+++ b/engines/mohawk/resource_cache.cpp
@@ -64,7 +64,7 @@ void ResourceCache::add(uint32 tag, uint16 id, Common::SeekableReadStream *data)
// Returns NULL if not found
Common::SeekableReadStream *ResourceCache::search(uint32 tag, uint16 id) {
if (!enabled)
- return NULL;
+ return nullptr;
debugC(kDebugCache, "Searching for tag 0x%04X id %d", tag, id);
@@ -79,7 +79,7 @@ Common::SeekableReadStream *ResourceCache::search(uint32 tag, uint16 id) {
}
debugC(kDebugCache, "tag 0x%04X id %d not found", tag, id);
- return NULL;
+ return nullptr;
}
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 0bf4024057..8139c1a92f 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -71,6 +71,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
_optionsDialog = nullptr;
_card = nullptr;
_inventory = nullptr;
+ _lastSaveTime = 0;
DebugMan.addDebugChannel(kRivenDebugScript, "Script", "Track Script Execution");
DebugMan.addDebugChannel(kRivenDebugPatches, "Patches", "Track Script Patching");
@@ -240,6 +241,12 @@ void MohawkEngine_Riven::doFrame() {
loadGameStateAndDisplayError(_optionsDialog->getLoadSlot());
if (_optionsDialog->getSaveSlot() >= 0)
saveGameStateAndDisplayError(_optionsDialog->getSaveSlot(), _optionsDialog->getSaveDescription());
+
+ if (hasGameEnded()) {
+ // Attempt to autosave before exiting
+ tryAutoSaving();
+ }
+
_gfx->setTransitionMode((RivenTransitionMode) _vars["transitionmode"]);
_card->initializeZipMode();
break;
@@ -281,6 +288,11 @@ void MohawkEngine_Riven::doFrame() {
break;
}
break;
+ case Common::EVENT_QUIT:
+ case Common::EVENT_RTL:
+ // Attempt to autosave before exiting
+ tryAutoSaving();
+ break;
default:
break;
}
@@ -294,6 +306,10 @@ void MohawkEngine_Riven::doFrame() {
_scriptMan->runQueuedScripts();
}
+ if (shouldPerformAutoSave(_lastSaveTime)) {
+ tryAutoSaving();
+ }
+
_inventory->onFrame();
// Update the screen once per frame
@@ -575,7 +591,7 @@ void MohawkEngine_Riven::loadGameStateAndDisplayError(int slot) {
}
Common::Error MohawkEngine_Riven::saveGameState(int slot, const Common::String &desc) {
- return _saveLoad->saveGame(slot, desc);
+ return _saveLoad->saveGame(slot, desc, false);
}
void MohawkEngine_Riven::saveGameStateAndDisplayError(int slot, const Common::String &desc) {
@@ -589,6 +605,23 @@ void MohawkEngine_Riven::saveGameStateAndDisplayError(int slot, const Common::St
}
}
+void MohawkEngine_Riven::tryAutoSaving() {
+ if (!canSaveGameStateCurrently()) {
+ return; // Can't save right now, try again on the next frame
+ }
+
+ _lastSaveTime = _system->getMillis();
+
+ if (!_saveLoad->isAutoSaveAllowed()) {
+ return; // Can't autosave ever, try again after the next autosave delay
+ }
+
+ Common::Error saveError = _saveLoad->saveGame(RivenSaveLoad::kAutoSaveSlot, "Autosave", true);
+ if (saveError.getCode() != Common::kNoError)
+ warning("Attempt to autosave has failed.");
+}
+
+
void MohawkEngine_Riven::addZipVisitedCard(uint16 cardId, uint16 cardNameId) {
Common::String cardName = getStack()->getName(kCardNames, cardNameId);
if (cardName.empty())
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index 86a431170f..3dc19c7ee4 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -79,11 +79,11 @@ typedef Common::HashMap<Common::String, uint32, Common::IgnoreCase_Hash, Common:
class MohawkEngine_Riven : public MohawkEngine {
protected:
- Common::Error run();
+ Common::Error run() override;
public:
MohawkEngine_Riven(OSystem *syst, const MohawkGameDescription *gamedesc);
- virtual ~MohawkEngine_Riven();
+ ~MohawkEngine_Riven() override;
RivenVideoManager *_video;
RivenSoundManager *_sound;
@@ -95,13 +95,13 @@ public:
// Display debug rectangles around the hotspots
bool _showHotspots;
- GUI::Debugger *getDebugger();
+ GUI::Debugger *getDebugger() override;
- 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;
void doFrame();
@@ -121,6 +121,7 @@ private:
RivenStack *_stack;
bool _gameEnded;
+ uint32 _lastSaveTime;
// Variables
void initVars();
@@ -152,6 +153,7 @@ public:
// Save / Load
void runLoadDialog();
void runSaveDialog();
+ void tryAutoSaving();
void loadGameStateAndDisplayError(int slot);
void saveGameStateAndDisplayError(int slot, const Common::String &desc);
diff --git a/engines/mohawk/riven_card.cpp b/engines/mohawk/riven_card.cpp
index 7a5cd617a6..031a88163b 100644
--- a/engines/mohawk/riven_card.cpp
+++ b/engines/mohawk/riven_card.cpp
@@ -72,8 +72,18 @@ void RivenCard::loadCardResource(uint16 id) {
void RivenCard::applyPatches(uint16 id) {
uint32 globalId = _vm->getStack()->getCardGlobalId(id);
- // Apply properties patches
+ applyPropertiesPatch8EB7(globalId);
+ applyPropertiesPatch2E76(globalId);
+ // Apply script patches
+ for (uint i = 0; i < _scripts.size(); i++) {
+ _scripts[i].script->applyCardPatches(_vm, globalId, _scripts[i].type, 0xFFFF);
+ }
+
+ applyPropertiesPatch22118(globalId);
+}
+
+void RivenCard::applyPropertiesPatch8EB7(uint32 globalId) {
// On Jungle Island on the back side of the "beetle" gate, the forward hotspot
// is always enabled, preventing keyboard navigation from automatically opening
// the gate.
@@ -138,7 +148,9 @@ void RivenCard::applyPatches(uint16 id) {
debugC(kRivenDebugPatches, "Applied fix always enabled forward hotspot in card %x", globalId);
}
+}
+void RivenCard::applyPropertiesPatch2E76(uint32 globalId) {
// In Gehn's office, after having encountered him once before and coming back
// with the trap book, the draw update script of card 1 tries to switch to
// card 2 while still loading card 1. Switching cards is not allowed during
@@ -179,7 +191,7 @@ void RivenCard::applyPatches(uint16 id) {
// activatePLST(6);
// break;
// }
- // break;
+ // break;
// case 2:
// activatePLST(5);
// break;
@@ -243,10 +255,138 @@ void RivenCard::applyPatches(uint16 id) {
debugC(kRivenDebugPatches, "Applied invalid card change during screen update (1/2) to card %x", globalId);
// The second part of this patch is in the script patches
}
+}
- // Apply script patches
- for (uint i = 0; i < _scripts.size(); i++) {
- _scripts[i].script->applyCardPatches(_vm, globalId, _scripts[i].type, 0xFFFF);
+void RivenCard::applyPropertiesPatch22118(uint32 globalId) {
+ // On Temple Island, near the steam valve closest to the bridge to Boiler island,
+ // the background sound on the view offering a view to the bridge does
+ // not properly reflect the valve's position.
+ //
+ // The sound is always that of steam going through the pipe when the bridge is
+ // down. When the valve points up, the sound should be that of steam escaping
+ // through the top of the pipe.
+ //
+ // Script before patch:
+ // == Script 0 ==
+ // type: CardLoad
+ // switch (bbigbridge) {
+ // case 0:
+ // switch (tbookvalve) {
+ // case 0:
+ // activatePLST(2);
+ // activateSLST(1);
+ // break;
+ // }
+ // break;
+ // }
+ // switch (bbigbridge) {
+ // case 0:
+ // switch (tbookvalve) {
+ // case 1:
+ // activatePLST(2);
+ // activateSLST(2);
+ // break;
+ // }
+ // break;
+ // }
+ // switch (bbigbridge) {
+ // case 1:
+ // switch (tbookvalve) {
+ // case 0:
+ // activatePLST(1);
+ // activateSLST(2);
+ // break;
+ // }
+ // break;
+ // }
+ // switch (bbigbridge) {
+ // case 1:
+ // switch (tbookvalve) {
+ // case 1:
+ // activatePLST(1);
+ // activateSLST(2);
+ // break;
+ // }
+ // break;
+ // }
+ //
+ //
+ // Script after patch:
+ // == Script 0 ==
+ // type: CardLoad
+ // switch (bbigbridge) {
+ // case 0:
+ // switch (tbookvalve) {
+ // case 0:
+ // activatePLST(2);
+ // break;
+ // }
+ // break;
+ // }
+ // switch (bbigbridge) {
+ // case 0:
+ // switch (tbookvalve) {
+ // case 1:
+ // activatePLST(2);
+ // break;
+ // }
+ // break;
+ // }
+ // switch (bbigbridge) {
+ // case 1:
+ // switch (tbookvalve) {
+ // case 0:
+ // activatePLST(1);
+ // break;
+ // }
+ // break;
+ // }
+ // switch (bbigbridge) {
+ // case 1:
+ // switch (tbookvalve) {
+ // case 1:
+ // activatePLST(1);
+ // break;
+ // }
+ // break;
+ // }
+ // switch (tbookvalve) {
+ // case 0:
+ // activateSLST(1);
+ // break;
+ // case 1:
+ // activateSLST(2);
+ // break;
+ // }
+ if (globalId == 0x22118) {
+ uint16 tBookValveVariable = _vm->getStack()->getIdFromName(kVariableNames, "tbookvalve");
+ uint16 patchData[] = {
+ 1, // Command count in script
+ kRivenCommandSwitch,
+ 2, // Unused
+ tBookValveVariable,
+ 2, // Branches count
+
+ 0, // tbookvalve == 0 branch (steam escaping at the top of the pipe)
+ 1, // Command count in sub-script
+ kRivenCommandActivateSLST,
+ 1, // Argument count
+ 1, // Steam leaking sound id
+
+ 1, // tbookvalve == 1 branch (steam going to the left pipe)
+ 1, // Command count in sub-script
+ kRivenCommandActivateSLST,
+ 1, // Argument count
+ 2, // Steam in pipe sound id
+ };
+
+ RivenScriptPtr patchScript = _vm->_scriptMan->readScriptFromData(patchData, ARRAYSIZE(patchData));
+
+ // Append the patch to the existing script
+ RivenScriptPtr loadScript = getScript(kCardLoadScript);
+ loadScript += patchScript;
+
+ debugC(kRivenDebugPatches, "Applied incorrect steam sounds (2/2) to card %x", globalId);
}
}
diff --git a/engines/mohawk/riven_card.h b/engines/mohawk/riven_card.h
index b11363c916..2b6a8d41bf 100644
--- a/engines/mohawk/riven_card.h
+++ b/engines/mohawk/riven_card.h
@@ -152,6 +152,9 @@ private:
void loadCardHotspotEnableList(uint16 id);
void loadCardWaterEffectList(uint16 id);
void applyPatches(uint16 id);
+ void applyPropertiesPatch8EB7(uint32 globalId);
+ void applyPropertiesPatch2E76(uint32 globalId);
+ void applyPropertiesPatch22118(uint32 globalId);
void setCurrentCardVariable();
RivenScriptPtr getScript(uint16 scriptType) const;
diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp
index d0a5c05636..d4ea8fc703 100644
--- a/engines/mohawk/riven_graphics.cpp
+++ b/engines/mohawk/riven_graphics.cpp
@@ -101,7 +101,7 @@ public:
_lastCopyArea = makeDirectionalInitalArea();
}
- virtual bool drawFrame(uint32 elapsed) override {
+ bool drawFrame(uint32 elapsed) override {
Common::Rect copyArea;
switch (_type) {
case kRivenTransitionWipeLeft:
@@ -162,7 +162,7 @@ public:
complete = false;
}
- virtual bool drawFrame(uint32 elapsed) override {
+ bool drawFrame(uint32 elapsed) override {
Common::Rect newArea;
switch (_type) {
case kRivenTransitionPanLeft:
@@ -264,7 +264,7 @@ public:
_timeBased = false;
}
- virtual bool drawFrame(uint32 elapsed) override {
+ bool drawFrame(uint32 elapsed) override {
assert(_effectScreen->format == _mainScreen->format);
assert(_effectScreen->format == _system->getScreenFormat());
@@ -303,7 +303,22 @@ public:
}
};
-RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm) {
+RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) :
+ GraphicsManager(),
+ _vm(vm),
+ _screenUpdateNesting(0),
+ _screenUpdateRunning(false),
+ _enableCardUpdateScript(true),
+ _scheduledTransition(kRivenTransitionNone),
+ _dirtyScreen(false),
+ _creditsImage(302),
+ _creditsPos(0),
+ _transitionMode(kRivenTransitionModeFastest),
+ _transitionOffset(-1),
+ _waterEffect(nullptr),
+ _fliesEffect(nullptr),
+ _transitionFrames(0),
+ _transitionDuration(0) {
_bitmapDecoder = new MohawkBitmap();
// Restrict ourselves to a single pixel format to simplify the effects implementation
@@ -317,20 +332,6 @@ RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm
_effectScreen = new Graphics::Surface();
_effectScreen->create(608, 392, _pixelFormat);
-
- _screenUpdateNesting = 0;
- _screenUpdateRunning = false;
- _enableCardUpdateScript = true;
- _scheduledTransition = kRivenTransitionNone;
- _dirtyScreen = false;
-
- _creditsImage = 302;
- _creditsPos = 0;
-
- _transitionMode = kRivenTransitionModeFastest;
- _transitionOffset = -1;
- _waterEffect = nullptr;
- _fliesEffect = nullptr;
}
RivenGraphics::~RivenGraphics() {
@@ -339,7 +340,8 @@ RivenGraphics::~RivenGraphics() {
_mainScreen->free();
delete _mainScreen;
delete _bitmapDecoder;
- delete _fliesEffect;
+ clearFliesEffect();
+ clearWaterEffect();
}
MohawkSurface *RivenGraphics::decodeImage(uint16 id) {
diff --git a/engines/mohawk/riven_graphics.h b/engines/mohawk/riven_graphics.h
index 31ab84038c..7b831c5609 100644
--- a/engines/mohawk/riven_graphics.h
+++ b/engines/mohawk/riven_graphics.h
@@ -54,8 +54,8 @@ enum RivenTransitionMode {
class RivenGraphics : public GraphicsManager {
public:
- RivenGraphics(MohawkEngine_Riven *vm);
- ~RivenGraphics();
+ explicit RivenGraphics(MohawkEngine_Riven *vm);
+ ~RivenGraphics() override;
// Screen updates
void beginScreenUpdate();
@@ -94,11 +94,11 @@ public:
// Credits
void beginCredits();
void updateCredits();
- uint getCurCreditsImage() { return _creditsImage; }
+ uint getCurCreditsImage() const { return _creditsImage; }
protected:
- MohawkSurface *decodeImage(uint16 id);
- MohawkEngine *getVM() { return (MohawkEngine *)_vm; }
+ MohawkSurface *decodeImage(uint16 id) override;
+ MohawkEngine *getVM() override { return (MohawkEngine *)_vm; }
private:
MohawkEngine_Riven *_vm;
diff --git a/engines/mohawk/riven_inventory.h b/engines/mohawk/riven_inventory.h
index 7c75b48374..8ce5f7ebd2 100644
--- a/engines/mohawk/riven_inventory.h
+++ b/engines/mohawk/riven_inventory.h
@@ -36,7 +36,7 @@ class MohawkEngine_Riven;
*/
class RivenInventory {
public:
- RivenInventory(MohawkEngine_Riven *vm);
+ explicit RivenInventory(MohawkEngine_Riven *vm);
virtual ~RivenInventory();
/** Handle a click event in the inventory area */
diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index 7165166d8f..e8d29a0c24 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -38,10 +38,11 @@ RivenSaveMetadata::RivenSaveMetadata() {
saveHour = 0;
saveMinute = 0;
totalPlayTime = 0;
+ autoSave = false;
}
bool RivenSaveMetadata::sync(Common::Serializer &s) {
- static const Common::Serializer::Version kCurrentVersion = 1;
+ static const Common::Serializer::Version kCurrentVersion = 2;
if (!s.syncVersion(kCurrentVersion)) {
return false;
@@ -54,10 +55,13 @@ bool RivenSaveMetadata::sync(Common::Serializer &s) {
s.syncAsByte(saveMinute);
s.syncString(saveDescription);
s.syncAsUint32BE(totalPlayTime);
+ s.syncAsByte(autoSave, 2);
return true;
}
+const int RivenSaveLoad::kAutoSaveSlot = 0;
+
RivenSaveLoad::RivenSaveLoad(MohawkEngine_Riven *vm, Common::SaveFileManager *saveFileMan) : _vm(vm), _saveFileMan(saveFileMan) {
}
@@ -105,22 +109,25 @@ Common::String RivenSaveLoad::querySaveDescription(const int slot) {
SaveStateDescriptor RivenSaveLoad::querySaveMetaInfos(const int slot) {
Common::String filename = buildSaveFilename(slot);
Common::InSaveFile *loadFile = g_system->getSavefileManager()->openForLoading(filename);
+ SaveStateDescriptor descriptor;
+ descriptor.setWriteProtectedFlag(slot == kAutoSaveSlot);
+
if (!loadFile) {
- return SaveStateDescriptor();
+ return descriptor;
}
MohawkArchive mhk;
if (!mhk.openStream(loadFile)) {
- return SaveStateDescriptor();
+ return descriptor;
}
if (!mhk.hasResource(ID_META, 1)) {
- return SaveStateDescriptor();
+ return descriptor;
}
Common::SeekableReadStream *metaStream = mhk.getResource(ID_META, 1);
if (!metaStream) {
- return SaveStateDescriptor();
+ return descriptor;
}
Common::Serializer serializer = Common::Serializer(metaStream, nullptr);
@@ -128,14 +135,15 @@ SaveStateDescriptor RivenSaveLoad::querySaveMetaInfos(const int slot) {
RivenSaveMetadata metadata;
if (!metadata.sync(serializer)) {
delete metaStream;
- return SaveStateDescriptor();
+ return descriptor;
}
- SaveStateDescriptor descriptor;
descriptor.setDescription(metadata.saveDescription);
descriptor.setPlayTime(metadata.totalPlayTime);
descriptor.setSaveDate(metadata.saveYear, metadata.saveMonth, metadata.saveDay);
descriptor.setSaveTime(metadata.saveHour, metadata.saveMinute);
+ if (metadata.autoSave) // Allow non-saves to be deleted, but not autosaves
+ descriptor.setDeletableFlag(slot != kAutoSaveSlot);
delete metaStream;
@@ -148,13 +156,51 @@ SaveStateDescriptor RivenSaveLoad::querySaveMetaInfos(const int slot) {
return descriptor;
}
- descriptor.setThumbnail(Graphics::loadThumbnail(*thmbStream));
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*thmbStream, thumbnail)) {
+ return descriptor;
+ }
+ descriptor.setThumbnail(thumbnail);
delete thmbStream;
return descriptor;
}
+bool RivenSaveLoad::isAutoSaveAllowed() {
+ // Open autosave slot and see if it an autosave
+ // Autosaving will be enabled if it is an autosave or if there is no save in that slot
+
+ Common::String filename = buildSaveFilename(kAutoSaveSlot);
+ Common::InSaveFile *loadFile = g_system->getSavefileManager()->openForLoading(filename);
+ if (!loadFile) {
+ return true; // There is no save in the autosave slot, enable autosave
+ }
+
+ MohawkArchive mhk;
+ if (!mhk.openStream(loadFile)) {
+ return true; // Corrupt save, enable autosave
+ }
+
+ if (!mhk.hasResource(ID_META, 1)) {
+ return false; // don't autosave over saves that don't have a meta section (like saves from the original)
+ }
+
+ Common::ScopedPtr<Common::SeekableReadStream> metaStream(mhk.getResource(ID_META, 1));
+ if (!metaStream) {
+ return true; // corrupt save, enable autosave
+ }
+
+ Common::Serializer serializer = Common::Serializer(metaStream.get(), nullptr);
+
+ RivenSaveMetadata metadata;
+ if (!metadata.sync(serializer)) {
+ return true; // corrupt save, enable autosave
+ }
+
+ return metadata.autoSave;
+}
+
Common::Error RivenSaveLoad::loadGame(const int slot) {
if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo
return Common::kNoError;
@@ -375,7 +421,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genTHMBSection() const {
return stream;
}
-Common::MemoryWriteStreamDynamic *RivenSaveLoad::genMETASection(const Common::String &desc) const {
+Common::MemoryWriteStreamDynamic *RivenSaveLoad::genMETASection(const Common::String &desc, bool autoSave) const {
Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
Common::Serializer serializer = Common::Serializer(nullptr, stream);
@@ -390,12 +436,13 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genMETASection(const Common::St
metadata.saveMinute = t.tm_min;
metadata.saveDescription = desc;
metadata.totalPlayTime = _vm->getTotalPlayTime();
+ metadata.autoSave = autoSave;
metadata.sync(serializer);
return stream;
}
-Common::Error RivenSaveLoad::saveGame(const int slot, const Common::String &description) {
+Common::Error RivenSaveLoad::saveGame(const int slot, const Common::String &description, bool autoSave) {
// NOTE: This code is designed to only output a Mohawk archive
// for a Riven saved game. It's hardcoded to do this because
// (as of right now) this is the only place in the engine
@@ -411,7 +458,7 @@ Common::Error RivenSaveLoad::saveGame(const int slot, const Common::String &desc
debug (0, "Saving game to \'%s\'", filename.c_str());
- Common::MemoryWriteStreamDynamic *metaSection = genMETASection(description);
+ Common::MemoryWriteStreamDynamic *metaSection = genMETASection(description, autoSave);
Common::MemoryWriteStreamDynamic *nameSection = genNAMESection();
Common::MemoryWriteStreamDynamic *thmbSection = genTHMBSection();
Common::MemoryWriteStreamDynamic *varsSection = genVARSSection();
diff --git a/engines/mohawk/riven_saveload.h b/engines/mohawk/riven_saveload.h
index 34bfbdc434..1432505b02 100644
--- a/engines/mohawk/riven_saveload.h
+++ b/engines/mohawk/riven_saveload.h
@@ -49,6 +49,8 @@ struct RivenSaveMetadata {
uint32 totalPlayTime;
+ bool autoSave;
+
Common::String saveDescription;
RivenSaveMetadata();
@@ -57,11 +59,14 @@ struct RivenSaveMetadata {
class RivenSaveLoad {
public:
+ static const int kAutoSaveSlot;
+
RivenSaveLoad(MohawkEngine_Riven*, Common::SaveFileManager*);
~RivenSaveLoad();
Common::Error loadGame(const int slot);
- Common::Error saveGame(const int slot, const Common::String &description);
+ Common::Error saveGame(const int slot, const Common::String &description, bool autoSave);
+ bool isAutoSaveAllowed();
static void deleteSave(const int slot);
static SaveStateDescriptor querySaveMetaInfos(const int slot);
@@ -74,7 +79,7 @@ private:
static Common::String buildSaveFilename(const int slot);
Common::MemoryWriteStreamDynamic *genNAMESection();
- Common::MemoryWriteStreamDynamic *genMETASection(const Common::String &desc) const;
+ Common::MemoryWriteStreamDynamic *genMETASection(const Common::String &desc, bool autoSave) const;
Common::MemoryWriteStreamDynamic *genTHMBSection() const;
Common::MemoryWriteStreamDynamic *genVARSSection();
Common::MemoryWriteStreamDynamic *genVERSSection();
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index 18a3597086..c12989bca6 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -345,6 +345,24 @@ void RivenScript::applyCardPatches(MohawkEngine_Riven *vm, uint32 cardGlobalId,
debugC(kRivenDebugPatches, "Applied invalid card change during screen update (2/2) to card %x", cardGlobalId);
}
+ // First part of the patch to fix the invalid steam sounds
+ // when looking at the Boiler island bridge from Temple island.
+ // The second part is in the card patches.
+ if (cardGlobalId == 0x22118 && scriptType == kCardLoadScript) {
+ shouldApplyPatches = true;
+
+ // Remove all the activateSLST calls.
+ // Fixed calls will be added back in the second part of the patch.
+ for (uint i = 0; i < _commands.size(); i++) {
+ if (_commands[i]->getType() == kRivenCommandActivateSLST) {
+ _commands.remove_at(i);
+ break;
+ }
+ }
+
+ debugC(kRivenDebugPatches, "Applied incorrect steam sounds (1/2) to card %x", cardGlobalId);
+ }
+
if (shouldApplyPatches) {
for (uint i = 0; i < _commands.size(); i++) {
_commands[i]->applyCardPatches(cardGlobalId, scriptType, hotspotId);
diff --git a/engines/mohawk/riven_sound.h b/engines/mohawk/riven_sound.h
index ce2ddbcbe8..fd14dee151 100644
--- a/engines/mohawk/riven_sound.h
+++ b/engines/mohawk/riven_sound.h
@@ -65,7 +65,7 @@ struct SLSTRecord {
*/
class RivenSoundManager {
public:
- RivenSoundManager(MohawkEngine_Riven *vm);
+ explicit RivenSoundManager(MohawkEngine_Riven *vm);
~RivenSoundManager();
/**
diff --git a/engines/mohawk/riven_stacks/jspit.cpp b/engines/mohawk/riven_stacks/jspit.cpp
index eeff81005b..b1f15a10c0 100644
--- a/engines/mohawk/riven_stacks/jspit.cpp
+++ b/engines/mohawk/riven_stacks/jspit.cpp
@@ -369,7 +369,7 @@ int JSpit::jspitElevatorLoop() {
return 1;
}
}
-
+
return 0;
}
diff --git a/engines/mohawk/riven_stacks/pspit.cpp b/engines/mohawk/riven_stacks/pspit.cpp
index a3134754b4..3c8b4306e4 100644
--- a/engines/mohawk/riven_stacks/pspit.cpp
+++ b/engines/mohawk/riven_stacks/pspit.cpp
@@ -83,7 +83,22 @@ void PSpit::catherineIdleTimer() {
void PSpit::xpisland990_elevcombo(const ArgumentArray &args) {
// Play button sound based on args[0]
_vm->_sound->playSound(args[0] + 5);
+ _vm->_cursor->hideCursor();
_vm->delay(500);
+ _vm->_cursor->showCursor();
+
+ // If the user released the mouse button during the wait time, the mouse up event
+ // is not forwarded to the game script handler. The button appears to be down
+ // until the user moves the mouse outside of the button hotspot.
+ // This happens with the original engine as well.
+ // To work around this issue we run the mouse up script if the mouse is not
+ // pressed anymore at this point.
+ if (!mouseIsDown()) {
+ Common::String buttonName = Common::String::format("combo%d", args[0]);
+ RivenHotspot *button = _vm->getCard()->getHotspotByName(buttonName);
+ RivenScriptPtr mouseUpScript = button->getScript(kMouseUpScript);
+ _vm->_scriptMan->runScript(mouseUpScript, false);
+ }
// It is impossible to get here if Gehn is not trapped. However,
// the original also disallows brute forcing the ending if you have
diff --git a/engines/mohawk/riven_video.h b/engines/mohawk/riven_video.h
index 5b5bf30fd2..ae5a266e04 100644
--- a/engines/mohawk/riven_video.h
+++ b/engines/mohawk/riven_video.h
@@ -130,7 +130,7 @@ private:
class RivenVideoManager {
public:
- RivenVideoManager(MohawkEngine_Riven *vm);
+ explicit RivenVideoManager(MohawkEngine_Riven *vm);
~RivenVideoManager();
void updateMovies();
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index 81d83fc7b9..7bd6c63539 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -158,11 +158,16 @@ Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *s
// The sound in the CD version of Riven is encoded in Intel DVI ADPCM
// The sound in the DVD version of Riven is encoded in MPEG-2 Layer II or Intel DVI ADPCM
if (dataChunk.encoding == kCodecRaw) {
- byte flags = Audio::FLAG_UNSIGNED;
+ byte flags = 0;
if (dataChunk.channels == 2)
flags |= Audio::FLAG_STEREO;
+ if (dataChunk.bitsPerSample == 16)
+ flags |= Audio::FLAG_16BITS;
+ else
+ flags |= Audio::FLAG_UNSIGNED;
+
return Audio::makeRawStream(dataChunk.audioData, dataChunk.sampleRate, flags);
} else if (dataChunk.encoding == kCodecADPCM) {
uint32 blockAlign = dataChunk.channels * dataChunk.bitsPerSample / 8;
@@ -180,51 +185,18 @@ Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *s
return nullptr;
}
-Sound::Sound(MohawkEngine* vm) : _vm(vm) {
- _midiDriver = NULL;
- _midiParser = NULL;
- _midiData = NULL;
- initMidi();
+Sound::Sound(MohawkEngine* vm) :
+ _vm(vm) {
}
Sound::~Sound() {
stopSound();
-
- if (_midiParser) {
- _midiParser->unloadMusic();
- delete _midiParser;
- }
-
- if (_midiDriver) {
- _midiDriver->close();
- delete _midiDriver;
- }
-
- if (_midiData)
- delete[] _midiData;
-}
-
-void Sound::initMidi() {
- if (!(_vm->getFeatures() & GF_HASMIDI))
- return;
-
- // Let's get our MIDI parser/driver
- _midiParser = MidiParser::createParser_SMF();
- _midiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB|MDT_MIDI));
-
- // Set up everything!
- _midiDriver->open();
- _midiParser->setMidiDriver(_midiDriver);
- _midiParser->setTimerRate(_midiDriver->getBaseTempo());
}
Audio::RewindableAudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
- Audio::RewindableAudioStream *audStream = NULL;
+ Audio::RewindableAudioStream *audStream = nullptr;
switch (_vm->getGameType()) {
- case GType_ZOOMBINI:
- audStream = makeMohawkWaveStream(_vm->getResource(ID_SND, id));
- break;
case GType_LIVINGBOOKSV1:
audStream = makeLivingBooksWaveStream_v1(_vm->getResource(ID_WAV, id));
break;
@@ -261,55 +233,7 @@ Audio::SoundHandle *Sound::playSound(uint16 id, byte volume, bool loop, CueList
return &handle->handle;
}
- return NULL;
-}
-
-void Sound::playMidi(uint16 id) {
- uint32 idTag;
- if (!(_vm->getFeatures() & GF_HASMIDI)) {
- warning ("Attempting to play MIDI in a game without MIDI");
- return;
- }
-
- assert(_midiDriver && _midiParser);
-
- _midiParser->unloadMusic();
- if (_midiData)
- delete[] _midiData;
-
- Common::SeekableReadStream *midi = _vm->getResource(ID_TMID, id);
-
- idTag = midi->readUint32BE();
- assert(idTag == ID_MHWK);
- midi->readUint32BE(); // Skip size
- idTag = midi->readUint32BE();
- assert(idTag == ID_MIDI);
-
- _midiData = new byte[midi->size() - 12]; // Enough to cover MThd/Prg#/MTrk
-
- // Read the MThd Data
- midi->read(_midiData, 14);
-
- // TODO: Load patches from the Prg# section... skip it for now.
- idTag = midi->readUint32BE();
- assert(idTag == ID_PRG);
- midi->skip(midi->readUint32BE());
-
- // Read the MTrk Data
- uint32 mtrkSize = midi->size() - midi->pos();
- midi->read(_midiData + 14, mtrkSize);
-
- delete midi;
-
- // Now, play it :)
- if (!_midiParser->loadMusic(_midiData, 14 + mtrkSize))
- error ("Could not play MIDI music from tMID %04x\n", id);
-
- _midiDriver->setTimerCallback(_midiParser, MidiParser::timerCallback);
-}
-
-void Sound::stopMidi() {
- _midiParser->unloadMusic();
+ return nullptr;
}
Audio::RewindableAudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) {
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index 11fd004513..15ee249177 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -102,13 +102,11 @@ class MohawkEngine;
class Sound {
public:
- Sound(MohawkEngine *vm);
+ explicit Sound(MohawkEngine *vm);
~Sound();
// Generic sound functions
Audio::SoundHandle *playSound(uint16 id, byte volume = Audio::Mixer::kMaxChannelVolume, bool loop = false, CueList *cueList = NULL);
- void playMidi(uint16 id);
- void stopMidi();
void stopSound();
void stopSound(uint16 id);
bool isPlaying(uint16 id);
@@ -117,17 +115,12 @@ public:
private:
MohawkEngine *_vm;
- MidiDriver *_midiDriver;
- MidiParser *_midiParser;
- byte *_midiData;
static Audio::RewindableAudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream);
- void initMidi();
Common::Array<SndHandle> _handles;
SndHandle *getHandle();
- Audio::RewindableAudioStream *makeAudioStream(uint16 id, CueList *cueList = NULL);
- uint16 convertMystID(uint16 id);
+ Audio::RewindableAudioStream *makeAudioStream(uint16 id, CueList *cueList = nullptr);
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp
index 994e219b03..ae20a59370 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -38,7 +38,7 @@
namespace Mohawk {
-VideoEntry::VideoEntry() : _video(0), _id(-1), _x(0), _y(0), _loop(false), _enabled(true) {
+VideoEntry::VideoEntry() : _video(nullptr), _id(-1), _x(0), _y(0), _loop(false), _enabled(true) {
}
VideoEntry::VideoEntry(Video::VideoDecoder *video, const Common::String &fileName) : _video(video), _fileName(fileName), _id(-1), _x(0), _y(0), _loop(false), _enabled(true) {
@@ -53,7 +53,7 @@ VideoEntry::~VideoEntry() {
void VideoEntry::close() {
delete _video;
- _video = 0;
+ _video = nullptr;
}
bool VideoEntry::endOfVideo() const {
@@ -230,7 +230,7 @@ bool VideoManager::drawNextFrame(VideoEntryPtr videoEntry) {
return false;
}
- Graphics::Surface *convertedFrame = 0;
+ Graphics::Surface *convertedFrame = nullptr;
Graphics::PixelFormat pixelFormat = _vm->_system->getScreenFormat();
if (frame->format != pixelFormat) {
diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h
index 1f8b93d467..fdc55a51ab 100644
--- a/engines/mohawk/video.h
+++ b/engines/mohawk/video.h
@@ -237,7 +237,7 @@ typedef Common::SharedPtr<VideoEntry> VideoEntryPtr;
class VideoManager {
public:
- VideoManager(MohawkEngine *vm);
+ explicit VideoManager(MohawkEngine *vm);
virtual ~VideoManager();
// Generic movie functions
diff --git a/engines/mohawk/view.cpp b/engines/mohawk/view.cpp
index 70d20270a5..ec73723971 100644
--- a/engines/mohawk/view.cpp
+++ b/engines/mohawk/view.cpp
@@ -63,10 +63,10 @@ void Feature::setNodeDefaults(Feature *prev, Feature *next) {
_prev = prev;
_next = next;
- _moveProc = NULL;
- _drawProc = NULL;
- _doneProc = NULL;
- _frameProc = NULL;
+ _moveProc = nullptr;
+ _drawProc = nullptr;
+ _doneProc = nullptr;
+ _frameProc = nullptr;
_data.bounds = Common::Rect();
_data.clipRect = Common::Rect();
@@ -333,7 +333,7 @@ void NewFeature::finishResetFeatureScript() {
}
View::View(MohawkEngine *vm) : _vm(vm) {
- _currentModule = NULL;
+ _currentModule = nullptr;
_backgroundId = 0xffff;
@@ -393,7 +393,7 @@ void View::setModule(Module *module) {
delete _currentModule;
}
- _currentModule = NULL;
+ _currentModule = nullptr;
if (module) {
_currentModule = module;
@@ -572,7 +572,7 @@ Feature *View::getFeaturePtr(uint16 id) {
return node;
}
- return NULL;
+ return nullptr;
}
uint16 View::getNewFeatureId() {
@@ -591,8 +591,8 @@ void View::removeFeature(Feature *feature, bool free) {
feature->_prev->_next = feature->_next;
feature->_next->_prev = feature->_prev;
- feature->_next = NULL;
- feature->_prev = NULL;
+ feature->_next = nullptr;
+ feature->_prev = nullptr;
if (free)
delete feature;
@@ -619,21 +619,21 @@ Feature *View::pointOnFeature(bool topdown, uint32 flags, Common::Point pos) {
else
curr = curr->_next;
}
- return NULL;
+ return nullptr;
}
void View::sortView() {
Feature *base = _rootNode;
Feature *next = base->_next;
- Feature *otherRoot = NULL;
- Feature *otherBase = NULL;
- Feature *objectRoot = NULL;
- Feature *objectBase = NULL;
- Feature *staticRoot = NULL;
- Feature *staticBase = NULL;
+ Feature *otherRoot = nullptr;
+ Feature *otherBase = nullptr;
+ Feature *objectRoot = nullptr;
+ Feature *objectBase = nullptr;
+ Feature *staticRoot = nullptr;
+ Feature *staticBase = nullptr;
// Remove all features.
- base->_next = NULL;
+ base->_next = nullptr;
// Iterate through all the previous features, placing them in the appropriate list.
while (next) {
@@ -645,33 +645,33 @@ void View::sortView() {
// so we insert this node directly after the current base.
base->_next = curr;
curr->_prev = base;
- curr->_next = NULL;
+ curr->_next = nullptr;
base = base->_next;
} else if (curr->_flags & kFeatureSortStatic) {
// Insert this node into the list of static objects.
if (staticBase) {
staticBase->_next = curr;
curr->_prev = staticBase;
- curr->_next = NULL;
+ curr->_next = nullptr;
staticBase = curr;
} else {
staticBase = curr;
staticRoot = curr;
- curr->_prev = NULL;
- curr->_next = NULL;
+ curr->_prev = nullptr;
+ curr->_next = nullptr;
}
} else if (curr->_flags & kFeatureObjectMask) { // This is == 1 or == 2 in old code.
// Insert this node into the list of objects.
if (objectRoot) {
objectBase->_next = curr;
curr->_prev = objectBase;
- curr->_next = NULL;
+ curr->_next = nullptr;
objectBase = curr;
} else {
objectBase = curr;
objectRoot = curr;
- curr->_prev = NULL;
- curr->_next = NULL;
+ curr->_prev = nullptr;
+ curr->_next = nullptr;
}
} else {
if (!(curr->_flags & kFeatureOldSortForeground))
@@ -681,13 +681,13 @@ void View::sortView() {
if (otherRoot) {
otherBase->_next = curr;
curr->_prev = otherBase;
- curr->_next = NULL;
+ curr->_next = nullptr;
otherBase = curr;
} else {
otherBase = curr;
otherRoot = curr;
- curr->_prev = NULL;
- curr->_next = NULL;
+ curr->_prev = nullptr;
+ curr->_next = nullptr;
}
}
}
@@ -700,7 +700,7 @@ void View::sortView() {
base->_next = prev;
prev->_prev = base;
base = base->_next;
- base->_next = NULL;
+ base->_next = nullptr;
}
// Add the other features on top..
@@ -711,12 +711,12 @@ void View::sortView() {
Feature *View::sortOneList(Feature *root) {
if (!root)
- return NULL;
+ return nullptr;
// Save the next feature and then clear the list.
Feature *curr = root->_next;
- root->_next = NULL;
- root->_prev = NULL;
+ root->_next = nullptr;
+ root->_prev = nullptr;
// Iterate over all the features.
while (curr) {
@@ -735,7 +735,7 @@ Feature *View::sortOneList(Feature *root) {
// This is the end of the list: add ourselves there.
check->_next = prev;
prev->_prev = check;
- prev->_next = NULL;
+ prev->_next = nullptr;
break;
}
} else {
@@ -779,7 +779,7 @@ Feature *View::mergeLists(Feature *root, Feature *mergeRoot) {
check = check->_next;
check->_next = prev;
prev->_prev = check;
- prev->_next = NULL;
+ prev->_next = nullptr;
continue;
}
@@ -802,7 +802,7 @@ Feature *View::mergeLists(Feature *root, Feature *mergeRoot) {
// We're at the end of the list, so we have to go here.
check->_next = prev;
prev->_prev = check;
- prev->_next = NULL;
+ prev->_next = nullptr;
base = prev;
break;
}
diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h
index 42d70fcb37..5d00547f4e 100644
--- a/engines/mortevielle/mortevielle.h
+++ b/engines/mortevielle/mortevielle.h
@@ -33,7 +33,6 @@
#include "common/random.h"
#include "common/rect.h"
#include "common/stack.h"
-#include "engines/advancedDetector.h"
#include "engines/engine.h"
#include "common/error.h"
#include "graphics/surface.h"
diff --git a/engines/mortevielle/saveload.cpp b/engines/mortevielle/saveload.cpp
index 3065d6c551..078338a0b5 100644
--- a/engines/mortevielle/saveload.cpp
+++ b/engines/mortevielle/saveload.cpp
@@ -92,8 +92,10 @@ bool SavegameManager::loadSavegame(const Common::String &filename) {
if (!strncmp(&buffer[0], &SAVEGAME_ID[0], 4)) {
// Yes, it is, so skip over the savegame header
SavegameHeader header;
- readSavegameHeader(stream, header);
- delete header.thumbnail;
+ if (!readSavegameHeader(stream, header)) {
+ delete stream;
+ return false;
+ }
} else {
stream->seek(0);
}
@@ -208,9 +210,7 @@ void SavegameManager::writeSavegameHeader(Common::OutSaveFile *out, const Common
out->writeSint16LE(td.tm_min);
}
-bool SavegameManager::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) {
- header.thumbnail = NULL;
-
+WARN_UNUSED_RESULT bool SavegameManager::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail) {
// Get the savegame version
header.version = in->readByte();
@@ -221,9 +221,9 @@ bool SavegameManager::readSavegameHeader(Common::InSaveFile *in, SavegameHeader
header.saveName += ch;
// Get the thumbnail
- header.thumbnail = Graphics::loadThumbnail(*in);
- if (!header.thumbnail)
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
header.saveYear = in->readSint16LE();
@@ -240,7 +240,6 @@ SaveStateList SavegameManager::listSaves(const Common::String &target) {
pattern += ".###";
Common::StringArray files = g_system->getSavefileManager()->listSavefiles(pattern);
- sort(files.begin(), files.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
for (Common::StringArray::const_iterator file = files.begin(); file != files.end(); ++file) {
@@ -264,7 +263,6 @@ SaveStateList SavegameManager::listSaves(const Common::String &target) {
validFlag = readSavegameHeader(in, header);
if (validFlag) {
- delete header.thumbnail;
saveDescription = header.saveName;
}
} else if (file->size() == 497) {
@@ -282,6 +280,7 @@ SaveStateList SavegameManager::listSaves(const Common::String &target) {
}
}
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
@@ -311,7 +310,10 @@ SaveStateDescriptor SavegameManager::querySaveMetaInfos(const Common::String &fi
} else {
// Get the savegame header information
SavegameHeader header;
- readSavegameHeader(f, header);
+ if (!readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
delete f;
// Create the return descriptor
diff --git a/engines/mortevielle/saveload.h b/engines/mortevielle/saveload.h
index a0de05b920..18042d9fb4 100644
--- a/engines/mortevielle/saveload.h
+++ b/engines/mortevielle/saveload.h
@@ -33,6 +33,7 @@
#include "graphics/palette.h"
#include "graphics/scaler.h"
#include "graphics/thumbnail.h"
+#include "engines/savestate.h"
#define SAVEGAME_VERSION 1
@@ -65,7 +66,7 @@ public:
Common::Error saveGame(int slot);
void writeSavegameHeader(Common::OutSaveFile *out, const Common::String &saveName);
- static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail = true);
static SaveStateList listSaves(const Common::String &target);
static SaveStateDescriptor querySaveMetaInfos(const Common::String &fileName);
};
diff --git a/engines/neverhood/detection.cpp b/engines/neverhood/detection.cpp
index 46605bb2f7..920d149659 100644
--- a/engines/neverhood/detection.cpp
+++ b/engines/neverhood/detection.cpp
@@ -271,7 +271,7 @@ SaveStateList NeverhoodMetaEngine::listSaves(const char *target) const {
if (slotNum >= 0 && slotNum <= 999) {
Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
if (in) {
- if (Neverhood::NeverhoodEngine::readSaveHeader(in, false, header) == Neverhood::NeverhoodEngine::kRSHENoError) {
+ if (Neverhood::NeverhoodEngine::readSaveHeader(in, header) == Neverhood::NeverhoodEngine::kRSHENoError) {
saveList.push_back(SaveStateDescriptor(slotNum, header.description));
}
delete in;
@@ -302,7 +302,7 @@ SaveStateDescriptor NeverhoodMetaEngine::querySaveMetaInfos(const char *target,
Neverhood::NeverhoodEngine::SaveHeader header;
Neverhood::NeverhoodEngine::kReadSaveHeaderError error;
- error = Neverhood::NeverhoodEngine::readSaveHeader(in, true, header);
+ error = Neverhood::NeverhoodEngine::readSaveHeader(in, header, false);
delete in;
if (error == Neverhood::NeverhoodEngine::kRSHENoError) {
diff --git a/engines/neverhood/menumodule.cpp b/engines/neverhood/menumodule.cpp
index e3996a2507..b64f4dcdd2 100644
--- a/engines/neverhood/menumodule.cpp
+++ b/engines/neverhood/menumodule.cpp
@@ -291,7 +291,7 @@ void MenuModule::loadSavegameList() {
if (slotNum >= 0 && slotNum <= 999) {
Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
if (in) {
- if (Neverhood::NeverhoodEngine::readSaveHeader(in, false, header) == Neverhood::NeverhoodEngine::kRSHENoError) {
+ if (Neverhood::NeverhoodEngine::readSaveHeader(in, header) == Neverhood::NeverhoodEngine::kRSHENoError) {
SavegameItem savegameItem;
savegameItem.slotNum = slotNum;
savegameItem.description = header.description;
diff --git a/engines/neverhood/neverhood.h b/engines/neverhood/neverhood.h
index 4c5f9c3303..90055eeb9d 100644
--- a/engines/neverhood/neverhood.h
+++ b/engines/neverhood/neverhood.h
@@ -129,7 +129,7 @@ public:
bool loadgame(const char *filename);
const char *getSavegameFilename(int num);
static Common::String getSavegameFilename(const Common::String &target, int num);
- static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header);
+ WARN_UNUSED_RESULT static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail = true);
GameState& gameState() { return _gameState; }
GameModule *gameModule() { return _gameModule; }
diff --git a/engines/neverhood/saveload.cpp b/engines/neverhood/saveload.cpp
index 8fe6c9a155..d7e6f1ebfe 100644
--- a/engines/neverhood/saveload.cpp
+++ b/engines/neverhood/saveload.cpp
@@ -32,7 +32,7 @@ namespace Neverhood {
#define NEVERHOOD_SAVEGAME_VERSION 0
-NeverhoodEngine::kReadSaveHeaderError NeverhoodEngine::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) {
+WARN_UNUSED_RESULT NeverhoodEngine::kReadSaveHeaderError NeverhoodEngine::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail) {
header.version = in->readUint32LE();
if (header.version > NEVERHOOD_SAVEGAME_VERSION)
@@ -43,10 +43,8 @@ NeverhoodEngine::kReadSaveHeaderError NeverhoodEngine::readSaveHeader(Common::Se
while (descriptionLen--)
header.description += (char)in->readByte();
- if (loadThumbnail) {
- header.thumbnail = Graphics::loadThumbnail(*in);
- } else {
- Graphics::skipThumbnail(*in);
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
+ return kRSHEIoError;
}
// Not used yet, reserved for future usage
@@ -110,7 +108,7 @@ bool NeverhoodEngine::loadgame(const char *filename) {
SaveHeader header;
- kReadSaveHeaderError errorCode = readSaveHeader(in, false, header);
+ kReadSaveHeaderError errorCode = readSaveHeader(in, header);
if (errorCode != kRSHENoError) {
warning("Error loading savegame '%s'", filename);
diff --git a/engines/obsolete.cpp b/engines/obsolete.cpp
index d65fb13ec1..ea96cff42e 100644
--- a/engines/obsolete.cpp
+++ b/engines/obsolete.cpp
@@ -55,7 +55,7 @@ void upgradeTargetIfNecessary(const ObsoleteGameID *obsoleteList) {
}
}
-GameDescriptor findGameID(
+PlainGameDescriptor findGameID(
const char *gameid,
const PlainGameDescriptor *gameids,
const ObsoleteGameID *obsoleteList
@@ -63,7 +63,7 @@ GameDescriptor findGameID(
// First search the list of supported gameids for a match.
const PlainGameDescriptor *g = findPlainGameDescriptor(gameid, gameids);
if (g)
- return GameDescriptor(*g);
+ return *g;
// If we didn't find the gameid in the main list, check if it
// is an obsolete game id.
@@ -73,16 +73,16 @@ GameDescriptor findGameID(
if (0 == scumm_stricmp(gameid, o->from)) {
g = findPlainGameDescriptor(o->to, gameids);
if (g && g->description)
- return GameDescriptor(gameid, "Obsolete game ID (" + Common::String(g->description) + ")");
+ return PlainGameDescriptor::of(gameid, g->description);
else
- return GameDescriptor(gameid, "Obsolete game ID");
+ return PlainGameDescriptor::of(gameid, "Obsolete game ID");
}
o++;
}
}
// No match found
- return GameDescriptor();
+ return PlainGameDescriptor::empty();
}
} // End of namespace Engines
diff --git a/engines/obsolete.h b/engines/obsolete.h
index be0963a7dc..7c7249e52b 100644
--- a/engines/obsolete.h
+++ b/engines/obsolete.h
@@ -66,7 +66,7 @@ void upgradeTargetIfNecessary(const ObsoleteGameID *obsoleteList);
* Optionally can take a list of obsolete game ids into account in order
* to support obsolete gameids.
*/
-GameDescriptor findGameID(
+PlainGameDescriptor findGameID(
const char *gameid,
const PlainGameDescriptor *gameids,
const ObsoleteGameID *obsoleteList = 0
diff --git a/engines/pegasus/items/biochips/pegasuschip.h b/engines/pegasus/items/biochips/pegasuschip.h
index b81df94b39..31cd778d98 100644
--- a/engines/pegasus/items/biochips/pegasuschip.h
+++ b/engines/pegasus/items/biochips/pegasuschip.h
@@ -36,7 +36,7 @@ public:
PegasusChip(const ItemID, const NeighborhoodID, const RoomID, const DirectionConstant);
virtual ~PegasusChip();
- void select();
+ void select() override;
void takeSharedArea() override;
diff --git a/engines/plumbers/console.cpp b/engines/plumbers/console.cpp
index f005b60769..730a74e2e7 100644
--- a/engines/plumbers/console.cpp
+++ b/engines/plumbers/console.cpp
@@ -27,7 +27,7 @@
namespace Plumbers {
-Console::Console(Plumbers::PlumbersGame *vm) : _vm(vm) {
+Console::Console() {
_allowSkip = false;
registerCmd("allowSkip", WRAP_METHOD(Console, Cmd_allowSkip));
}
diff --git a/engines/plumbers/console.h b/engines/plumbers/console.h
index c849678419..cb50834f36 100644
--- a/engines/plumbers/console.h
+++ b/engines/plumbers/console.h
@@ -30,13 +30,10 @@ namespace Plumbers {
class PlumbersGame;
class Console : public GUI::Debugger {
-private:
- PlumbersGame *_vm;
-
public:
bool _allowSkip;
- explicit Console(Plumbers::PlumbersGame *vm);
+ explicit Console();
virtual ~Console(void) {}
bool Cmd_allowSkip(int argc, const char** argv);
diff --git a/engines/plumbers/plumbers.cpp b/engines/plumbers/plumbers.cpp
index f0445e51eb..5491f81c65 100644
--- a/engines/plumbers/plumbers.cpp
+++ b/engines/plumbers/plumbers.cpp
@@ -89,7 +89,8 @@ static const byte cursorPalette[] = {
Common::Error PlumbersGame::run() {
initGraphics(640, 480);
- _console = new Console(this);
+ _console = new Console();
+ _image = new Image::BitmapDecoder();
CursorMan.replaceCursor(MOUSECURSOR_SCI, 11, 16, 0, 0, 0);
CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
@@ -178,17 +179,11 @@ Common::Error PlumbersGame::run() {
void PlumbersGame::loadImage(const Common::String &dirname, const Common::String &filename) {
Common::String name = dirname + "/" + filename;
debugC(1, kDebugGeneral, "%s : %s", __FUNCTION__, name.c_str());
- Common::File *file = new Common::File();
- if (!file->open(name))
+ Common::File file;
+ if (!file.open(name))
error("unable to load image %s", name.c_str());
- if (_image)
- delete _image;
-
- _image = new Image::BitmapDecoder();
- _image->loadStream(*file);
- file->close();
- delete file;
+ _image->loadStream(file);
}
void PlumbersGame::drawScreen() {
@@ -362,7 +357,6 @@ void PlumbersGame::readTables(const Common::String &fileName) {
file.read(buf, kMaxName);
_bitmaps[i]._filename = Common::String(buf);
}
- file.close();
}
int PlumbersGame::getSceneNumb(int sNo) {
diff --git a/engines/plumbers/plumbers.h b/engines/plumbers/plumbers.h
index 56b27fb745..430c696c6d 100644
--- a/engines/plumbers/plumbers.h
+++ b/engines/plumbers/plumbers.h
@@ -25,7 +25,6 @@
#include "common/scummsys.h"
#include "common/config-manager.h"
-#include "engines/advancedDetector.h"
#include "common/error.h"
#include "engines/engine.h"
@@ -44,6 +43,8 @@
#include "plumbers/console.h"
+struct ADGameDescription;
+
namespace Plumbers {
enum PlumbersDebugChannels {
kDebugGeneral = 1 << 0
@@ -110,7 +111,7 @@ private:
};
Common::Queue<Action> _actions;
-
+
void loadImage(const Common::String &dirname, const Common::String &filename);
void drawScreen();
diff --git a/engines/prince/archive.cpp b/engines/prince/archive.cpp
index 984c078bfb..0ed6e8c753 100644
--- a/engines/prince/archive.cpp
+++ b/engines/prince/archive.cpp
@@ -55,8 +55,8 @@ bool PtcArchive::open(const Common::String &filename) {
uint32 fileTableOffset = _stream->readUint32LE() ^ 0x4D4F4B2D; // MOK-
uint32 fileTableSize = _stream->readUint32LE() ^ 0x534F4654; // SOFT
- //debug("fileTableOffset : %08X", fileTableOffset);
- //debug("fileTableSize: %08X", fileTableSize);
+ debug(8, "fileTableOffset : %08X", fileTableOffset);
+ debug(8, "fileTableSize: %08X", fileTableSize);
_stream->seek(fileTableOffset);
@@ -70,7 +70,7 @@ bool PtcArchive::open(const Common::String &filename) {
Common::String name = (const char*)fileItem;
item._offset = READ_LE_UINT32(fileItem + 24);
item._size = READ_LE_UINT32(fileItem + 28);
- //debug("%12s %8X %d", name.c_str(), item._offset, item._size);
+ debug(8, "%12s %8X %d", name.c_str(), item._offset, item._size);
_items[name] = item;
}
@@ -135,6 +135,8 @@ Common::SeekableReadStream *PtcArchive::createReadStreamForMember(const Common::
return 0;
}
+ debug(8, "PtcArchive::createReadStreamForMember(%s)", name.c_str());
+
const FileEntry &entryHeader = _items[name];
if (entryHeader._size < 4)
@@ -156,9 +158,9 @@ Common::SeekableReadStream *PtcArchive::createReadStreamForMember(const Common::
free(buffer);
size = decompLen;
buffer = decompData;
- }
- //debug("PtcArchive::createReadStreamForMember name %s", name.c_str());
+ debug(8, "PtcArchive::createReadStreamForMember: decompressed %d to %d bytes", entryHeader._size, decompLen);
+ }
return new Common::MemoryReadStream(buffer, size, DisposeAfterUse::YES);
}
diff --git a/engines/prince/cursor.cpp b/engines/prince/cursor.cpp
index ab3a52eaa2..a4e58dc4a2 100644
--- a/engines/prince/cursor.cpp
+++ b/engines/prince/cursor.cpp
@@ -20,7 +20,12 @@
*
*/
+#include "graphics/cursorman.h"
+
+#include "prince/prince.h"
#include "prince/cursor.h"
+#include "prince/debugger.h"
+#include "prince/script.h"
#include "common/debug.h"
@@ -51,4 +56,98 @@ bool Cursor::loadStream(Common::SeekableReadStream &stream) {
return true;
}
+void PrinceEngine::changeCursor(uint16 curId) {
+ _debugger->_cursorNr = curId;
+ _mouseFlag = curId;
+ _flags->setFlagValue(Flags::MOUSEENABLED, curId);
+
+ const Graphics::Surface *curSurface = nullptr;
+
+ switch (curId) {
+ default:
+ error("Unknown cursor Id: %d", curId);
+ case 0:
+ CursorMan.showMouse(false);
+ _optionsFlag = 0;
+ _selectedMob = -1;
+ return;
+ case 1:
+ curSurface = _cursor1->getSurface();
+ break;
+ case 2:
+ curSurface = _cursor2;
+ break;
+ case 3:
+ curSurface = _cursor3->getSurface();
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ mousePos.x = CLIP(mousePos.x, (int16) 315, (int16) 639);
+ mousePos.y = CLIP(mousePos.y, (int16) 0, (int16) 170);
+ _system->warpMouse(mousePos.x, mousePos.y);
+ break;
+ }
+
+ CursorMan.replaceCursorPalette(_roomBmp->getPalette(), 0, 255);
+ CursorMan.replaceCursor(
+ curSurface->getBasePtr(0, 0),
+ curSurface->w, curSurface->h,
+ 0, 0,
+ 255, false,
+ &curSurface->format
+ );
+ CursorMan.showMouse(true);
+}
+
+void PrinceEngine::makeInvCursor(int itemNr) {
+ const Graphics::Surface *cur1Surface = _cursor1->getSurface();
+ int cur1W = cur1Surface->w;
+ int cur1H = cur1Surface->h;
+ const Common::Rect cur1Rect(0, 0, cur1W, cur1H);
+
+ const Graphics::Surface *itemSurface = _allInvList[itemNr].getSurface();
+ int itemW = itemSurface->w;
+ int itemH = itemSurface->h;
+
+ int cur2W = cur1W + itemW / 2;
+ int cur2H = cur1H + itemH / 2;
+
+ if (_cursor2 != nullptr) {
+ _cursor2->free();
+ delete _cursor2;
+ }
+ _cursor2 = new Graphics::Surface();
+ _cursor2->create(cur2W, cur2H, Graphics::PixelFormat::createFormatCLUT8());
+ Common::Rect cur2Rect(0, 0, cur2W, cur2H);
+ _cursor2->fillRect(cur2Rect, 255);
+ _cursor2->copyRectToSurface(*cur1Surface, 0, 0, cur1Rect);
+
+ const byte *src1 = (const byte *)itemSurface->getBasePtr(0, 0);
+ byte *dst1 = (byte *)_cursor2->getBasePtr(cur1W, cur1H);
+
+ if (itemH % 2) {
+ itemH--;
+ }
+ if (itemW % 2) {
+ itemW--;
+ }
+
+ for (int y = 0; y < itemH; y++) {
+ const byte *src2 = src1;
+ byte *dst2 = dst1;
+ if (y % 2 == 0) {
+ for (int x = 0; x < itemW; x++, src2++) {
+ if (x % 2 == 0) {
+ if (*src2) {
+ *dst2 = *src2;
+ } else {
+ *dst2 = 255;
+ }
+ dst2++;
+ }
+ }
+ dst1 += _cursor2->pitch;
+ }
+ src1 += itemSurface->pitch;
+ }
+}
+
} // End of namespace Prince
diff --git a/engines/prince/decompress.cpp b/engines/prince/decompress.cpp
index 2b563917f7..eda992c093 100644
--- a/engines/prince/decompress.cpp
+++ b/engines/prince/decompress.cpp
@@ -27,145 +27,145 @@
namespace Prince {
static const uint16 table1[] = {
- 0x8000, 0x0002,
- 0x4000, 0x0004,
- 0x2000, 0x0008,
- 0x1000, 0x0010,
- 0x0800, 0x0020,
- 0x0400, 0x0040,
- 0x0200, 0x0080,
- 0x0100, 0x0100,
- 0x0080, 0x0200,
- 0x0040, 0x0400
+ 0x8000, 0x0002,
+ 0x4000, 0x0004,
+ 0x2000, 0x0008,
+ 0x1000, 0x0010,
+ 0x0800, 0x0020,
+ 0x0400, 0x0040,
+ 0x0200, 0x0080,
+ 0x0100, 0x0100,
+ 0x0080, 0x0200,
+ 0x0040, 0x0400
};
static const uint32 table2[] = {
- 0x0000F000,
- 0x0020FC00,
- 0x00A0FF00,
- 0x02A0FF80,
- 0x06A0FFC0,
- 0x0EA0FFE0,
- 0x1EA0FFF0,
- 0x3EA0FFF8
+ 0x0000F000,
+ 0x0020FC00,
+ 0x00A0FF00,
+ 0x02A0FF80,
+ 0x06A0FFC0,
+ 0x0EA0FFE0,
+ 0x1EA0FFF0,
+ 0x3EA0FFF8
};
static const uint16 table3[] = {
- 0x8000, 0x0000,
- 0x4000, 0x0002,
- 0x2000, 0x0006,
- 0x1000, 0x000E,
- 0x0800, 0x001E,
- 0x0400, 0x003E,
- 0x0200, 0x007E,
- 0x0100, 0x00FE,
- 0x0080, 0x01FE,
- 0x0040, 0x03FE,
- 0x0020, 0x07FE,
- 0x0010, 0x0FFE,
- 0x0008, 0x1FFE,
- 0x0004, 0x3FFE,
- 0x0002, 0x7FFE,
- 0x0001, 0xFFFE
+ 0x8000, 0x0000,
+ 0x4000, 0x0002,
+ 0x2000, 0x0006,
+ 0x1000, 0x000E,
+ 0x0800, 0x001E,
+ 0x0400, 0x003E,
+ 0x0200, 0x007E,
+ 0x0100, 0x00FE,
+ 0x0080, 0x01FE,
+ 0x0040, 0x03FE,
+ 0x0020, 0x07FE,
+ 0x0010, 0x0FFE,
+ 0x0008, 0x1FFE,
+ 0x0004, 0x3FFE,
+ 0x0002, 0x7FFE,
+ 0x0001, 0xFFFE
};
void Decompressor::decompress(byte *source, byte *dest, uint32 destSize) {
- byte *destEnd = dest + destSize;
- int more;
- _src = source;
- _dst = dest;
- _bitBuffer = 0x80;
- while (_dst < destEnd) {
- uint32 ebp;
- uint16 offset, length;
- if (getBit()) {
- if (getBit()) {
- if (getBit()) {
- if (getBit()) {
- if (getBit()) {
- if (getBit()) {
- uint32 tableIndex = 0;
- while (getBit())
- tableIndex++;
- length = table3[tableIndex * 2 + 0];
- do {
- more = !(length & 0x8000);
- length = (length << 1) | getBit();
- } while (more);
- length += table3[tableIndex * 2 + 1];
- length++;
- memcpy(_dst, _src, length);
- _src += length;
- _dst += length;
- }
- *_dst++ = *_src++;
- }
- *_dst++ = *_src++;
- }
- *_dst++ = *_src++;
- }
- *_dst++ = *_src++;
- }
- *_dst++ = *_src++;
- }
- if (!getBit()) {
- if (getBit()) {
- uint32 tableIndex = getBit();
- tableIndex = (tableIndex << 1) | getBit();
- tableIndex = (tableIndex << 1) | getBit();
- ebp = table2[tableIndex];
- length = 1;
- } else {
- ebp = 0x0000FF00;
- length = 0;
- }
- } else {
- uint32 tableIndex = 0;
- while (getBit())
- tableIndex++;
- length = table1[tableIndex * 2 + 0];
- do {
- more = !(length & 0x8000);
- length = (length << 1) | getBit();
- } while (more);
- length += table1[tableIndex * 2 + 1];
- tableIndex = getBit();
- tableIndex = (tableIndex << 1) | getBit();
- tableIndex = (tableIndex << 1) | getBit();
- ebp = table2[tableIndex];
- }
- offset = ebp & 0xFFFF;
- do {
- if (_bitBuffer == 0x80) {
- if (offset >= 0xFF00) {
- offset = (offset << 8) | *_src++;
- }
- }
- more = offset & 0x8000;
- offset = (offset << 1) | getBit();
- } while (more);
- offset += (ebp >> 16);
- length += 2;
- while (length--) {
- if (_dst >= destEnd) {
- return;
- }
- *_dst = *(_dst - offset);
- _dst++;
- }
- }
+ byte *destEnd = dest + destSize;
+ int more;
+ _src = source;
+ _dst = dest;
+ _bitBuffer = 0x80;
+ while (_dst < destEnd) {
+ uint32 ebp;
+ uint16 offset, length;
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ if (getBit()) {
+ uint32 tableIndex = 0;
+ while (getBit())
+ tableIndex++;
+ length = table3[tableIndex * 2 + 0];
+ do {
+ more = !(length & 0x8000);
+ length = (length << 1) | getBit();
+ } while (more);
+ length += table3[tableIndex * 2 + 1];
+ length++;
+ memcpy(_dst, _src, length);
+ _src += length;
+ _dst += length;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ *_dst++ = *_src++;
+ }
+ if (!getBit()) {
+ if (getBit()) {
+ uint32 tableIndex = getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ ebp = table2[tableIndex];
+ length = 1;
+ } else {
+ ebp = 0x0000FF00;
+ length = 0;
+ }
+ } else {
+ uint32 tableIndex = 0;
+ while (getBit())
+ tableIndex++;
+ length = table1[tableIndex * 2 + 0];
+ do {
+ more = !(length & 0x8000);
+ length = (length << 1) | getBit();
+ } while (more);
+ length += table1[tableIndex * 2 + 1];
+ tableIndex = getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ tableIndex = (tableIndex << 1) | getBit();
+ ebp = table2[tableIndex];
+ }
+ offset = ebp & 0xFFFF;
+ do {
+ if (_bitBuffer == 0x80) {
+ if (offset >= 0xFF00) {
+ offset = (offset << 8) | *_src++;
+ }
+ }
+ more = offset & 0x8000;
+ offset = (offset << 1) | getBit();
+ } while (more);
+ offset += (ebp >> 16);
+ length += 2;
+ while (length--) {
+ if (_dst >= destEnd) {
+ return;
+ }
+ *_dst = *(_dst - offset);
+ _dst++;
+ }
+ }
}
int Decompressor::getBit() {
- int bit = (_bitBuffer & 0x80) >> 7;
- _bitBuffer <<= 1;
- if (_bitBuffer == 0) {
- _bitBuffer = *_src++;
- bit = (_bitBuffer & 0x80) >> 7;
- _bitBuffer <<= 1;
- _bitBuffer |= 1;
- }
- return bit;
+ int bit = (_bitBuffer & 0x80) >> 7;
+ _bitBuffer <<= 1;
+ if (_bitBuffer == 0) {
+ _bitBuffer = *_src++;
+ bit = (_bitBuffer & 0x80) >> 7;
+ _bitBuffer <<= 1;
+ _bitBuffer |= 1;
+ }
+ return bit;
}
} // End of namespace Prince
diff --git a/engines/prince/detection.cpp b/engines/prince/detection.cpp
index a8fa305332..2147c23116 100644
--- a/engines/prince/detection.cpp
+++ b/engines/prince/detection.cpp
@@ -21,9 +21,15 @@
*/
#include "prince/prince.h"
+#include "engines/advancedDetector.h"
namespace Prince {
+struct PrinceGameDescription {
+ ADGameDescription desc;
+ PrinceGameType gameType;
+};
+
int PrinceEngine::getGameType() const {
return _gameDescription->gameType;
}
@@ -43,7 +49,7 @@ Common::Language PrinceEngine::getLanguage() const {
} // End of namespace Prince
static const PlainGameDescriptor princeGames[] = {
- {"prince", "Prince Game"},
+ {"prince", "The Prince and the Coward"},
{0, 0}
};
@@ -52,11 +58,11 @@ static const PrinceGameDescription gameDescriptions[] = {
{
{
"prince",
- "Galador",
+ "Galador: Der Fluch des Prinzen",
AD_ENTRY1s("databank.ptc", "5fa03833177331214ec1354761b1d2ee", 3565031),
Common::DE_DEU,
Common::kPlatformWindows,
- ADGF_TESTING,
+ ADGF_USEEXTRAASTITLE | ADGF_TESTING,
GUIO1(GUIO_NONE)
},
kPrinceDataDE
@@ -68,7 +74,7 @@ static const PrinceGameDescription gameDescriptions[] = {
AD_ENTRY1s("databank.ptc", "48ec9806bda9d152acbea8ce31c93c49", 3435298),
Common::PL_POL,
Common::kPlatformWindows,
- ADGF_TESTING,
+ ADGF_USEEXTRAASTITLE | ADGF_TESTING,
GUIO1(GUIO_NONE)
},
kPrinceDataPL
@@ -76,11 +82,11 @@ static const PrinceGameDescription gameDescriptions[] = {
{
{
"prince",
- "Galador",
+ "",
AD_ENTRY1s("talktxt.dat", "02bb2372f19aca3c65896ed81b2cefb3", 125702),
Common::RU_RUS,
Common::kPlatformWindows,
- ADGF_TESTING,
+ ADGF_TESTING | GF_EXTRACTED,
GUIO1(GUIO_NONE)
},
kPrinceDataDE
@@ -88,19 +94,19 @@ static const PrinceGameDescription gameDescriptions[] = {
{
{
"prince",
- "Galador",
+ "",
AD_ENTRY1s("databank.ptc", "a67b55730f3d7064921bd2a59e1063a3", 3892982),
Common::RU_RUS,
Common::kPlatformWindows,
- ADGF_TESTING,
+ ADGF_TESTING | GF_NOVOICES,
GUIO1(GUIO_NONE)
},
- kPrinceDataPL
+ kPrinceDataDE
},
{
{
"prince",
- "The Prince and the Coward",
+ "",
{
{"databank.ptc", 0, "5fa03833177331214ec1354761b1d2ee", 3565031},
{"prince_translation.dat", 0, 0, -1},
@@ -116,7 +122,7 @@ static const PrinceGameDescription gameDescriptions[] = {
{
{
"prince",
- "The Prince and the Coward",
+ "",
{
{"databank.ptc", 0, "48ec9806bda9d152acbea8ce31c93c49", 3435298},
{"prince_translation.dat", 0, 0, -1},
@@ -169,6 +175,7 @@ bool PrinceMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
(f == kSavesSupportCreationDate) ||
+ (f == kSavesSupportPlayTime) ||
(f == kSupportsListSaves) ||
(f == kSupportsLoadingDuringStartup) ||
(f == kSimpleSavesNames);
@@ -188,7 +195,6 @@ SaveStateList PrinceMetaEngine::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++) {
@@ -209,10 +215,6 @@ SaveStateList PrinceMetaEngine::listSaves(const char *target) const {
// Valid savegame
if (Prince::PrinceEngine::readSavegameHeader(file, header)) {
saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
- if (header.thumbnail) {
- header.thumbnail->free();
- delete header.thumbnail;
- }
}
} else {
// Must be an original format savegame
@@ -224,6 +226,7 @@ SaveStateList PrinceMetaEngine::listSaves(const char *target) const {
}
}
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
@@ -239,7 +242,7 @@ SaveStateDescriptor PrinceMetaEngine::querySaveMetaInfos(const char *target, int
f->read(buffer, kSavegameStrSize + 1);
bool hasHeader = !strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) &&
- Prince::PrinceEngine::readSavegameHeader(f, header);
+ Prince::PrinceEngine::readSavegameHeader(f, header, false);
delete f;
if (!hasHeader) {
@@ -252,6 +255,7 @@ SaveStateDescriptor PrinceMetaEngine::querySaveMetaInfos(const char *target, int
desc.setThumbnail(header.thumbnail);
desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
desc.setSaveTime(header.saveHour, header.saveMinutes);
+ desc.setPlayTime(header.playTime * 1000);
return desc;
}
diff --git a/engines/prince/draw.cpp b/engines/prince/draw.cpp
new file mode 100644
index 0000000000..a924f99def
--- /dev/null
+++ b/engines/prince/draw.cpp
@@ -0,0 +1,765 @@
+/* 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/palette.h"
+
+#include "prince/prince.h"
+
+#include "prince/animation.h"
+#include "prince/graphics.h"
+#include "prince/hero.h"
+#include "prince/script.h"
+
+namespace Prince {
+
+bool PrinceEngine::spriteCheck(int sprWidth, int sprHeight, int destX, int destY) {
+ destX -= _picWindowX;
+ destY -= _picWindowY;
+
+ // if x1 is on visible part of screen
+ if (destX < 0) {
+ if (destX + sprWidth < 1) {
+ //x2 is negative - out of window
+ return false;
+ }
+ }
+ // if x1 is outside of screen on right side
+ if (destX >= kNormalWidth) {
+ return false;
+ }
+
+ if (destY < 0) {
+ if (destY + sprHeight < 1) {
+ //y2 is negative - out of window
+ return false;
+ }
+ }
+ if (destY >= kNormalHeight) {
+ return false;
+ }
+
+ return true;
+}
+
+// CheckNak
+void PrinceEngine::checkMasks(int x1, int y1, int sprWidth, int sprHeight, int z) {
+ int x2 = x1 + sprWidth - 1;
+ int y2 = y1 + sprHeight - 1;
+ if (x1 < 0) {
+ x1 = 0;
+ }
+ for (uint i = 0; i < _maskList.size(); i++) {
+ if (!_maskList[i]._state && !_maskList[i]._flags) {
+ if (_maskList[i]._z > z) {
+ if (_maskList[i]._x1 <= x2 && _maskList[i]._x2 >= x1) {
+ if (_maskList[i]._y1 <= y2 && _maskList[i]._y2 >= y1) {
+ _maskList[i]._state = 1;
+ }
+ }
+ }
+ }
+ }
+}
+
+// ClsNak
+void PrinceEngine::clsMasks() {
+ for (uint i = 0; i < _maskList.size(); i++) {
+ if (_maskList[i]._state) {
+ _maskList[i]._state = 0;
+ }
+ }
+}
+
+// InsertNakladki
+void PrinceEngine::insertMasks(Graphics::Surface *originalRoomSurface) {
+ for (uint i = 0; i < _maskList.size(); i++) {
+ if (_maskList[i]._state) {
+ if (_maskList[i]._data != nullptr) {
+ showMask(i, originalRoomSurface);
+ } else {
+ error("insertMasks() - Wrong mask data- nr %d", i);
+ }
+ }
+ }
+}
+
+// ShowNak
+void PrinceEngine::showMask(int maskNr, Graphics::Surface *originalRoomSurface) {
+ if (!_maskList[maskNr]._flags) {
+ if (spriteCheck(_maskList[maskNr]._width, _maskList[maskNr]._height, _maskList[maskNr]._x1, _maskList[maskNr]._y1)) {
+ int destX = _maskList[maskNr]._x1 - _picWindowX;
+ int destY = _maskList[maskNr]._y1 - _picWindowY;
+ DrawNode newDrawNode;
+ newDrawNode.posX = destX;
+ newDrawNode.posY = destY;
+ newDrawNode.posZ = _maskList[maskNr]._z;
+ newDrawNode.width = _maskList[maskNr]._width;
+ newDrawNode.height = _maskList[maskNr]._height;
+ newDrawNode.s = nullptr;
+ newDrawNode.originalRoomSurface = originalRoomSurface;
+ newDrawNode.data = _maskList[maskNr].getMask();
+ newDrawNode.drawFunction = &_graph->drawMaskDrawNode;
+ _drawNodeList.push_back(newDrawNode);
+ }
+ }
+}
+
+void PrinceEngine::showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ) {
+ if (spriteCheck(spriteSurface->w, spriteSurface->h, destX, destY)) {
+ destX -= _picWindowX;
+ destY -= _picWindowY;
+ DrawNode newDrawNode;
+ newDrawNode.posX = destX;
+ newDrawNode.posY = destY;
+ newDrawNode.posZ = destZ;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.s = spriteSurface;
+ newDrawNode.originalRoomSurface = nullptr;
+ newDrawNode.data = _transTable;
+ newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
+ _drawNodeList.push_back(newDrawNode);
+ }
+}
+
+void PrinceEngine::showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ) {
+ if (spriteCheck(shadowSurface->w, shadowSurface->h, destX, destY)) {
+ destX -= _picWindowX;
+ destY -= _picWindowY;
+ DrawNode newDrawNode;
+ newDrawNode.posX = destX;
+ newDrawNode.posY = destY;
+ newDrawNode.posZ = destZ;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.s = shadowSurface;
+ newDrawNode.originalRoomSurface = nullptr;
+ newDrawNode.data = _graph->_shadowTable70;
+ newDrawNode.drawFunction = &_graph->drawAsShadowDrawNode;
+ _drawNodeList.push_back(newDrawNode);
+ }
+}
+
+void PrinceEngine::showAnim(Anim &anim) {
+ //ShowFrameCode
+ //ShowAnimFrame
+ int phase = anim._showFrame;
+ int phaseFrameIndex = anim._animData->getPhaseFrameIndex(phase);
+ int x = anim._x + anim._animData->getPhaseOffsetX(phase);
+ int y = anim._y + anim._animData->getPhaseOffsetY(phase);
+ int animFlag = anim._flags;
+ int checkMaskFlag = (animFlag & 1);
+ int maxFrontFlag = (animFlag & 2);
+ int specialZFlag = anim._nextAnim;
+ int z = anim._nextAnim;
+ Graphics::Surface *animSurface = anim._animData->getFrame(phaseFrameIndex);
+ int frameWidth = animSurface->w;
+ int frameHeight = animSurface->h;
+ int shadowZ = 0;
+
+ if (checkMaskFlag) {
+ if (!anim._nextAnim) {
+ z = y + frameHeight - 1;
+ }
+ checkMasks(x, y, frameWidth, frameHeight, z);
+ }
+
+ if (specialZFlag) {
+ z = specialZFlag;
+ } else if (maxFrontFlag) {
+ z = kMaxPicHeight + 1;
+ } else {
+ z = y + frameHeight - 1;
+ }
+ shadowZ = z;
+
+ anim._currX = x;
+ anim._currY = y;
+ anim._currW = frameWidth;
+ anim._currH = frameHeight;
+ showSprite(animSurface, x, y, z);
+
+ // make_special_shadow
+ if ((anim._flags & 0x80)) {
+ DrawNode newDrawNode;
+ newDrawNode.posX = x;
+ newDrawNode.posY = y + animSurface->h - anim._shadowBack;
+ newDrawNode.posZ = Hero::kHeroShadowZ;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.scaleValue = _scaleValue;
+ newDrawNode.originalRoomSurface = nullptr;
+ newDrawNode.data = this;
+ newDrawNode.drawFunction = &Hero::showHeroShadow;
+ newDrawNode.s = animSurface;
+ _drawNodeList.push_back(newDrawNode);
+ }
+
+ //ShowFrameCodeShadow
+ //ShowAnimFrameShadow
+ if (anim._shadowData != nullptr) {
+ int shadowPhaseFrameIndex = anim._shadowData->getPhaseFrameIndex(phase);
+ int shadowX = anim._shadowData->getBaseX() + anim._shadowData->getPhaseOffsetX(phase);
+ int shadowY = anim._shadowData->getBaseY() + anim._shadowData->getPhaseOffsetY(phase);
+ Graphics::Surface *shadowSurface = anim._shadowData->getFrame(shadowPhaseFrameIndex);
+ int shadowFrameWidth = shadowSurface->w;
+ int shadowFrameHeight = shadowSurface->h;
+
+ if (checkMaskFlag) {
+ checkMasks(shadowX, shadowY, shadowFrameWidth, shadowFrameHeight, shadowY + shadowFrameWidth - 1);
+ }
+
+ if (!shadowZ) {
+ if (maxFrontFlag) {
+ shadowZ = kMaxPicHeight + 1;
+ } else {
+ shadowZ = shadowY + shadowFrameWidth - 1;
+ }
+ }
+ showSpriteShadow(shadowSurface, shadowX, shadowY, shadowZ);
+ }
+}
+
+void PrinceEngine::showNormAnims() {
+ for (int i = 0; i < kMaxNormAnims; i++) {
+ Anim &anim = _normAnimList[i];
+ if (anim._animData != nullptr) {
+ int phaseCount = anim._animData->getPhaseCount();
+ if (!anim._state) {
+ if (anim._frame == anim._lastFrame - 1) {
+ if (anim._loopType) {
+ if (anim._loopType == 1) {
+ anim._frame = anim._loopFrame;
+ } else {
+ continue;
+ }
+ }
+ } else {
+ anim._frame++;
+ }
+ anim._showFrame = anim._frame;
+ if (anim._showFrame >= phaseCount) {
+ anim._showFrame = phaseCount - 1;
+ }
+ showAnim(anim);
+ }
+ }
+ }
+}
+
+void PrinceEngine::setBackAnim(Anim &backAnim) {
+ int start = backAnim._basaData._start;
+ if (start != -1) {
+ backAnim._frame = start;
+ backAnim._showFrame = start;
+ backAnim._loopFrame = start;
+ }
+ int end = backAnim._basaData._end;
+ if (end != -1) {
+ backAnim._lastFrame = end;
+ }
+ backAnim._state = 0;
+}
+
+void PrinceEngine::showBackAnims() {
+ for (int i = 0; i < kMaxBackAnims; i++) {
+ BAS &seq = _backAnimList[i]._seq;
+ int activeSubAnim = seq._currRelative;
+ if (!_backAnimList[i].backAnims.empty()) {
+ if (_backAnimList[i].backAnims[activeSubAnim]._animData != nullptr) {
+ if (!_backAnimList[i].backAnims[activeSubAnim]._state) {
+ seq._counter++;
+ if (seq._type == 2) {
+ if (!seq._currRelative) {
+ if (seq._counter >= seq._data) {
+ if (seq._anims > 2) {
+ seq._currRelative = _randomSource.getRandomNumber(seq._anims - 2) + 1;
+ activeSubAnim = seq._currRelative;
+ seq._current = _backAnimList[i].backAnims[activeSubAnim]._basaData._num;
+ }
+ setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ seq._counter = 0;
+ }
+ }
+ }
+
+ if (seq._type == 3) {
+ if (!seq._currRelative) {
+ if (seq._counter < seq._data2) {
+ continue;
+ } else {
+ setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ }
+ }
+ }
+
+ if (_backAnimList[i].backAnims[activeSubAnim]._frame == _backAnimList[i].backAnims[activeSubAnim]._lastFrame - 1) {
+ _backAnimList[i].backAnims[activeSubAnim]._frame = _backAnimList[i].backAnims[activeSubAnim]._loopFrame;
+ switch (seq._type) {
+ case 1:
+ if (seq._anims > 1) {
+ int rnd;
+ do {
+ rnd = _randomSource.getRandomNumber(seq._anims - 1);
+ } while (rnd == seq._currRelative);
+ seq._currRelative = rnd;
+ seq._current = _backAnimList[i].backAnims[rnd]._basaData._num;
+ activeSubAnim = rnd;
+ setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ seq._counter = 0;
+ }
+ break;
+ case 2:
+ if (seq._currRelative) {
+ seq._currRelative = 0;
+ seq._current = _backAnimList[i].backAnims[0]._basaData._num;
+ activeSubAnim = 0;
+ setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ seq._counter = 0;
+ }
+ break;
+ case 3:
+ seq._currRelative = 0;
+ seq._current = _backAnimList[i].backAnims[0]._basaData._num;
+ seq._counter = 0;
+ seq._data2 = _randomSource.getRandomNumber(seq._data - 1);
+ continue; // for bug in original game
+ break;
+ }
+ } else {
+ _backAnimList[i].backAnims[activeSubAnim]._frame++;
+ }
+ _backAnimList[i].backAnims[activeSubAnim]._showFrame = _backAnimList[i].backAnims[activeSubAnim]._frame;
+ showAnim(_backAnimList[i].backAnims[activeSubAnim]);
+ }
+ }
+ }
+ }
+}
+
+void PrinceEngine::removeSingleBackAnim(int slot) {
+ if (!_backAnimList[slot].backAnims.empty()) {
+ for (uint j = 0; j < _backAnimList[slot].backAnims.size(); j++) {
+ if (_backAnimList[slot].backAnims[j]._animData != nullptr) {
+ delete _backAnimList[slot].backAnims[j]._animData;
+ _backAnimList[slot].backAnims[j]._animData = nullptr;
+ }
+ if (_backAnimList[slot].backAnims[j]._shadowData != nullptr) {
+ delete _backAnimList[slot].backAnims[j]._shadowData;
+ _backAnimList[slot].backAnims[j]._shadowData = nullptr;
+ }
+ }
+ _backAnimList[slot].backAnims.clear();
+ _backAnimList[slot]._seq._currRelative = 0;
+ }
+}
+
+void PrinceEngine::clearBackAnimList() {
+ for (int i = 0; i < kMaxBackAnims; i++) {
+ removeSingleBackAnim(i);
+ }
+}
+
+void PrinceEngine::grabMap() {
+ _graph->_frontScreen->copyFrom(*_roomBmp->getSurface());
+ showObjects();
+ runDrawNodes();
+ _graph->_mapScreen->copyFrom(*_graph->_frontScreen);
+}
+
+void PrinceEngine::initZoomIn(int slot) {
+ freeZoomObject(slot);
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ Graphics::Surface *zoomSource = object->getSurface();
+ if (zoomSource != nullptr) {
+ object->_flags |= 0x8000;
+ object->_zoomSurface = new Graphics::Surface();
+ object->_zoomSurface->create(zoomSource->w, zoomSource->h, Graphics::PixelFormat::createFormatCLUT8());
+ object->_zoomSurface->fillRect(Common::Rect(zoomSource->w, zoomSource->h), 0xFF);
+ object->_zoomTime = 20;
+ }
+ }
+}
+
+void PrinceEngine::initZoomOut(int slot) {
+ freeZoomObject(slot);
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ Graphics::Surface *zoomSource = object->getSurface();
+ if (zoomSource != nullptr) {
+ object->_flags |= 0x4000;
+ object->_zoomSurface = new Graphics::Surface();
+ object->_zoomSurface->copyFrom(*zoomSource);
+ object->_zoomTime = 10;
+ }
+ }
+}
+
+void PrinceEngine::doZoomIn(int slot) {
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ Graphics::Surface *orgSurface = object->getSurface();
+ if (orgSurface != nullptr) {
+ byte *src1 = (byte *)orgSurface->getBasePtr(0, 0);
+ byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
+ int x = 0;
+ int surfaceHeight = orgSurface->h;
+ for (int y = 0; y < surfaceHeight; y++) {
+ byte *src2 = src1;
+ byte *dst2 = dst1;
+ int w = orgSurface->w - x;
+ src2 += x;
+ dst2 += x;
+ while (w > 0) {
+ int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
+ if (randVal < w) {
+ *(dst2 + randVal) = *(src2 + randVal);
+ src2 += zoomInStep;
+ dst2 += zoomInStep;
+ } else if (y + 1 != surfaceHeight) {
+ *(dst1 + orgSurface->pitch + randVal - w) = *(src1 + orgSurface->pitch + randVal - w);
+ }
+ w -= zoomInStep;
+ }
+ x = -1 * w;
+ src1 += orgSurface->pitch;
+ dst1 += orgSurface->pitch;
+ }
+ }
+ }
+}
+
+void PrinceEngine::doZoomOut(int slot) {
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ Graphics::Surface *orgSurface = object->getSurface();
+ if (orgSurface != nullptr) {
+ byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
+ int x = 0;
+ int surfaceHeight = orgSurface->h;
+ for (int y = 0; y < surfaceHeight; y++) {
+ byte *dst2 = dst1;
+ int w = orgSurface->w - x;
+ dst2 += x;
+ while (w > 0) {
+ int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
+ if (randVal < w) {
+ *(dst2 + randVal) = 255;
+ dst2 += zoomInStep;
+ } else if (y + 1 != surfaceHeight) {
+ *(dst1 + orgSurface->pitch + randVal - w) = 255;
+ }
+ w -= zoomInStep;
+ }
+ x = -1 * w;
+ dst1 += orgSurface->pitch;
+ }
+ }
+ }
+}
+
+void PrinceEngine::freeZoomObject(int slot) {
+ Object *object = _objList[slot];
+ if (object != nullptr) {
+ if (object->_zoomSurface != nullptr) {
+ object->_zoomSurface->free();
+ delete object->_zoomSurface;
+ object->_zoomSurface = nullptr;
+ }
+ }
+}
+
+void PrinceEngine::showObjects() {
+ for (int i = 0; i < kMaxObjects; i++) {
+ int nr = _objSlot[i];
+ if (nr != 0xFF) {
+ Graphics::Surface *objSurface = nullptr;
+ if ((_objList[nr]->_flags & 0x8000)) {
+ _objList[nr]->_zoomTime--;
+ if (!_objList[nr]->_zoomTime) {
+ freeZoomObject(nr);
+ _objList[nr]->_flags &= 0x7FFF;
+ objSurface = _objList[nr]->getSurface();
+ } else {
+ doZoomIn(nr);
+ objSurface = _objList[nr]->_zoomSurface;
+ }
+ } else if ((_objList[nr]->_flags & 0x4000)) {
+ _objList[nr]->_zoomTime--;
+ if (!_objList[nr]->_zoomTime) {
+ freeZoomObject(nr);
+ _objList[nr]->_flags &= 0xBFFF;
+ objSurface = _objList[nr]->getSurface();
+ } else {
+ doZoomOut(nr);
+ objSurface = _objList[nr]->_zoomSurface;
+ }
+ } else {
+ objSurface = _objList[nr]->getSurface();
+ }
+
+ if (objSurface != nullptr) {
+ if (spriteCheck(objSurface->w, objSurface->h, _objList[nr]->_x, _objList[nr]->_y)) {
+ int destX = _objList[nr]->_x - _picWindowX;
+ int destY = _objList[nr]->_y - _picWindowY;
+ DrawNode newDrawNode;
+ newDrawNode.posX = destX;
+ newDrawNode.posY = destY;
+ newDrawNode.posZ = _objList[nr]->_z;
+ newDrawNode.width = 0;
+ newDrawNode.height = 0;
+ newDrawNode.s = objSurface;
+ newDrawNode.originalRoomSurface = nullptr;
+ if ((_objList[nr]->_flags & 0x2000)) {
+ newDrawNode.data = nullptr;
+ newDrawNode.drawFunction = &_graph->drawBackSpriteDrawNode;
+ } else {
+ newDrawNode.data = _transTable;
+ if (_flags->getFlagValue(Flags::NOANTIALIAS)) {
+ newDrawNode.drawFunction = &_graph->drawTransparentDrawNode;
+ } else {
+ newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
+ }
+ }
+ _drawNodeList.push_back(newDrawNode);
+ }
+
+ if ((_objList[nr]->_flags & 1)) {
+ checkMasks(_objList[nr]->_x, _objList[nr]->_y, objSurface->w, objSurface->h, _objList[nr]->_z);
+ }
+ }
+ }
+ }
+}
+
+void PrinceEngine::showParallax() {
+ if (!_pscrList.empty()) {
+ for (uint i = 0; i < _pscrList.size(); i++) {
+ Graphics::Surface *pscrSurface = _pscrList[i]->getSurface();
+ if (pscrSurface != nullptr) {
+ int x = _pscrList[i]->_x - (_pscrList[i]->_step * _picWindowX / 4);
+ int y = _pscrList[i]->_y;
+ int z = PScr::kPScrZ;
+ if (spriteCheck(pscrSurface->w, pscrSurface->h, x, y)) {
+ showSprite(pscrSurface, x, y, z);
+ }
+ }
+ }
+ }
+}
+
+bool PrinceEngine::compareDrawNodes(DrawNode d1, DrawNode d2) {
+ if (d1.posZ < d2.posZ) {
+ return true;
+ }
+ return false;
+}
+
+void PrinceEngine::runDrawNodes() {
+ Common::sort(_drawNodeList.begin(), _drawNodeList.end(), compareDrawNodes);
+
+ for (uint i = 0; i < _drawNodeList.size(); i++) {
+ (*_drawNodeList[i].drawFunction)(_graph->_frontScreen, &_drawNodeList[i]);
+ }
+ _graph->change();
+}
+
+void PrinceEngine::drawScreen() {
+ if (!_showInventoryFlag || _inventoryBackgroundRemember) {
+ clsMasks();
+
+ _mainHero->showHero();
+ _mainHero->scrollHero();
+ _mainHero->drawHero();
+
+ _secondHero->showHero();
+ _secondHero->_drawX -= _picWindowX;
+ _secondHero->drawHero();
+
+ const Graphics::Surface *roomSurface;
+ if (_locationNr != 50) {
+ roomSurface = _roomBmp->getSurface();
+ } else {
+ roomSurface = _graph->_mapScreen;
+ }
+ Graphics::Surface visiblePart;
+ if (roomSurface) {
+ visiblePart = roomSurface->getSubArea(Common::Rect(_picWindowX, 0, roomSurface->w, roomSurface->h));
+ _graph->draw(_graph->_frontScreen, &visiblePart);
+ }
+
+ showBackAnims();
+
+ showNormAnims();
+
+ playNextFLCFrame();
+
+ showObjects();
+
+ if (roomSurface) {
+ insertMasks(&visiblePart);
+ }
+
+ showParallax();
+
+ runDrawNodes();
+
+ _drawNodeList.clear();
+
+ if (!_inventoryBackgroundRemember && !_dialogFlag) {
+ if (!_optionsFlag) {
+ _selectedMob = checkMob(_graph->_frontScreen, _mobList, true);
+ }
+ showTexts(_graph->_frontScreen);
+ checkOptions();
+ } else {
+ _inventoryBackgroundRemember = false;
+ }
+
+ showPower();
+
+ getDebugger()->onFrame();
+
+ } else {
+ displayInventory();
+ }
+}
+
+void PrinceEngine::blackPalette() {
+ byte *paletteBackup = (byte *)malloc(256 * 3);
+ byte *blackPalette1 = (byte *)malloc(256 * 3);
+
+ int fadeStep = kFadeStep - 1;
+ for (int i = 0; i < kFadeStep; i++) {
+ _system->getPaletteManager()->grabPalette(paletteBackup, 0, 256);
+ for (int j = 0; j < 256; j++) {
+ blackPalette1[3 * j] = paletteBackup[3 * j] * fadeStep / 4;
+ blackPalette1[3 * j + 1] = paletteBackup[3 * j + 1] * fadeStep / 4;
+ blackPalette1[3 * j + 2] = paletteBackup[3 * j + 2] * fadeStep / 4;
+ }
+ fadeStep--;
+ _graph->setPalette(blackPalette1);
+ _system->updateScreen();
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ free(paletteBackup);
+ free(blackPalette1);
+ return;
+ }
+ pausePrinceEngine();
+ }
+ free(paletteBackup);
+ free(blackPalette1);
+}
+
+void PrinceEngine::setPalette(const byte *palette) {
+ if (palette != nullptr) {
+ byte *blackPalette_ = (byte *)malloc(256 * 3);
+ int fadeStep = 0;
+ for (int i = 0; i <= kFadeStep; i++) {
+ for (int j = 0; j < 256; j++) {
+ blackPalette_[3 * j] = palette[3 * j] * fadeStep / 4;
+ blackPalette_[3 * j + 1] = palette[3 * j + 1] * fadeStep / 4;
+ blackPalette_[3 * j + 2] = palette[3 * j + 2] * fadeStep / 4;
+ }
+ fadeStep++;
+ _graph->setPalette(blackPalette_);
+ _system->updateScreen();
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ _graph->setPalette(palette);
+ free(blackPalette_);
+ return;
+ }
+ pausePrinceEngine();
+ }
+ _graph->setPalette(palette);
+ free(blackPalette_);
+ }
+}
+
+void PrinceEngine::doTalkAnim(int animNumber, int slot, AnimType animType) {
+ Text &text = _textSlots[slot];
+ int lines = calcTextLines((const char *)_interpreter->getString());
+ int time = lines * 30;
+ if (animType == kNormalAnimation) {
+ Anim &normAnim = _normAnimList[animNumber];
+ if (normAnim._animData != nullptr) {
+ if (!normAnim._state) {
+ if (normAnim._currW && normAnim._currH) {
+ text._color = _flags->getFlagValue(Flags::KOLOR);
+ text._x = normAnim._currX + normAnim._currW / 2;
+ text._y = normAnim._currY - 10;
+ }
+ }
+ }
+ } else if (animType == kBackgroundAnimation) {
+ if (!_backAnimList[animNumber].backAnims.empty()) {
+ int currAnim = _backAnimList[animNumber]._seq._currRelative;
+ Anim &backAnim = _backAnimList[animNumber].backAnims[currAnim];
+ if (backAnim._animData != nullptr) {
+ if (!backAnim._state) {
+ if (backAnim._currW && backAnim._currH) {
+ text._color = _flags->getFlagValue(Flags::KOLOR);
+ text._x = backAnim._currX + backAnim._currW / 2;
+ text._y = backAnim._currY - 10;
+ }
+ }
+ }
+ }
+ } else {
+ error("doTalkAnim() - wrong animType: %d", animType);
+ }
+ text._time = time;
+ if (getLanguage() == Common::DE_DEU) {
+ correctStringDEU((char *)_interpreter->getString());
+ }
+ text._str = (const char *)_interpreter->getString();
+ _interpreter->increaseString();
+}
+
+void PrinceEngine::freeNormAnim(int slot) {
+ if (!_normAnimList.empty()) {
+ _normAnimList[slot]._state = 1;
+ if (_normAnimList[slot]._animData != nullptr) {
+ delete _normAnimList[slot]._animData;
+ _normAnimList[slot]._animData = nullptr;
+ }
+ if (_normAnimList[slot]._shadowData != nullptr) {
+ delete _normAnimList[slot]._shadowData;
+ _normAnimList[slot]._shadowData = nullptr;
+ }
+ }
+}
+
+void PrinceEngine::freeAllNormAnims() {
+ for (int i = 0; i < kMaxNormAnims; i++) {
+ freeNormAnim(i);
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/hero.cpp b/engines/prince/hero.cpp
index 037f11e95a..8ade649a9f 100644
--- a/engines/prince/hero.cpp
+++ b/engines/prince/hero.cpp
@@ -68,7 +68,7 @@ bool Hero::loadAnimSet(uint32 animSetNr) {
_moveSet.resize(kMoveSetSize);
for (uint32 i = 0; i < kMoveSetSize; i++) {
- debug("Anim set item %d %s", i, animSet[i]);
+ debug(5, "Anim set item %d %s", i, animSet[i]);
Animation *anim = nullptr;
if (animSet[i] != nullptr) {
anim = new Animation();
diff --git a/engines/prince/inventory.cpp b/engines/prince/inventory.cpp
new file mode 100644
index 0000000000..3183b94334
--- /dev/null
+++ b/engines/prince/inventory.cpp
@@ -0,0 +1,709 @@
+/* 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 "prince/prince.h"
+
+#include "prince/graphics.h"
+#include "prince/hero.h"
+#include "prince/script.h"
+#include "prince/mhwanh.h"
+#include "prince/variatxt.h"
+#include "prince/option_text.h"
+#include "prince/font.h"
+
+namespace Prince {
+
+void PrinceEngine::addInv(int heroId, int item, bool addItemQuiet) {
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _mainHero;
+ } else if (heroId == 1) {
+ hero = _secondHero;
+ }
+ if (hero != nullptr) {
+ if (hero->_inventory.size() < kMaxItems) {
+ if (item != 0x7FFF) {
+ hero->_inventory.push_back(item);
+ }
+ if (!addItemQuiet) {
+ addInvObj();
+ }
+ _interpreter->setResult(0);
+ } else {
+ _interpreter->setResult(1);
+ }
+ }
+}
+
+void PrinceEngine::remInv(int heroId, int item) {
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _mainHero;
+ } else if (heroId == 1) {
+ hero = _secondHero;
+ }
+ if (hero != nullptr) {
+ for (uint i = 0; i < hero->_inventory.size(); i++) {
+ if (hero->_inventory[i] == item) {
+ hero->_inventory.remove_at(i);
+ _interpreter->setResult(0);
+ return;
+ }
+ }
+ }
+ _interpreter->setResult(1);
+}
+
+void PrinceEngine::clearInv(int heroId) {
+ switch (heroId) {
+ case 0:
+ _mainHero->_inventory.clear();
+ break;
+ case 1:
+ _secondHero->_inventory.clear();
+ break;
+ default:
+ error("clearInv() - wrong hero slot");
+ break;
+ }
+}
+
+void PrinceEngine::swapInv(int heroId) {
+ Common::Array<int> tempInv;
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _mainHero;
+ } else if (heroId == 1) {
+ hero = _secondHero;
+ }
+ if (hero != nullptr) {
+ for (uint i = 0; i < hero->_inventory.size(); i++) {
+ tempInv.push_back(hero->_inventory[i]);
+ }
+ hero->_inventory.clear();
+ for (uint i = 0; i < hero->_inventory2.size(); i++) {
+ hero->_inventory.push_back(hero->_inventory2[i]);
+ }
+ hero->_inventory2.clear();
+ for (uint i = 0; i < tempInv.size(); i++) {
+ hero->_inventory2.push_back(tempInv[i]);
+ }
+ tempInv.clear();
+ }
+}
+
+void PrinceEngine::addInvObj() {
+ changeCursor(0);
+ prepareInventoryToView();
+
+ _inventoryBackgroundRemember = true;
+ drawScreen();
+
+ Graphics::Surface *suitcase = _suitcaseBmp->getSurface();
+
+ if (!_flags->getFlagValue(Flags::CURSEBLINK)) {
+
+ loadSample(27, "PRZEDMIO.WAV");
+ playSample(27, 0);
+
+ _mst_shadow2 = 1;
+
+ while (_mst_shadow2 < 512) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ _mst_shadow2 += 50;
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pausePrinceEngine();
+ }
+ while (_mst_shadow2 > 256) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ _mst_shadow2 -= 42;
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pausePrinceEngine();
+ }
+ } else {
+ //CURSEBLINK:
+ for (int i = 0; i < 3; i++) {
+ _mst_shadow2 = 256;
+ while (_mst_shadow2 < 512) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ _mst_shadow2 += 50;
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pausePrinceEngine();
+ }
+ while (_mst_shadow2 > 256) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ _mst_shadow2 -= 50;
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pausePrinceEngine();
+ }
+ }
+ }
+ _mst_shadow2 = 0;
+ for (int i = 0; i < 20; i++) {
+ rememberScreenInv();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+ drawInvItems();
+ _graph->update(_graph->_screenForInventory);
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ eventMan->pollEvent(event);
+ if (shouldQuit()) {
+ return;
+ }
+ pausePrinceEngine();
+ }
+}
+
+void PrinceEngine::rememberScreenInv() {
+ _graph->_screenForInventory->copyFrom(*_graph->_frontScreen);
+}
+
+void PrinceEngine::inventoryFlagChange(bool inventoryState) {
+ if (inventoryState) {
+ _showInventoryFlag = true;
+ _inventoryBackgroundRemember = true;
+ } else {
+ _showInventoryFlag = false;
+ }
+}
+
+void PrinceEngine::prepareInventoryToView() {
+ _invMobList.clear();
+ int invItem = _mainHero->_inventory.size();
+ _invLine = invItem / 3;
+ if (invItem % 3) {
+ _invLine++;
+ }
+ if (_invLine < 4) {
+ _invLine = 4;
+ }
+ _maxInvW = (374 - 2 * _invLine) / _invLine;
+ _invLineW = _maxInvW - 2;
+
+ int currInvX = _invLineX;
+ int currInvY = _invLineY;
+
+ Common::MemoryReadStream stream(_invTxt, _invTxtSize);
+ byte c;
+
+ uint item = 0;
+ for (int i = 0; i < _invLines; i++) {
+ for (int j = 0; j < _invLine; j++) {
+ Mob tempMobItem;
+ if (item < _mainHero->_inventory.size()) {
+ int itemNr = _mainHero->_inventory[item];
+ tempMobItem._visible = 0;
+ tempMobItem._mask = itemNr;
+ tempMobItem._rect = Common::Rect(currInvX + _picWindowX, currInvY, currInvX + _picWindowX + _invLineW - 1, currInvY + _invLineH - 1);
+ tempMobItem._type = 0; // to work with checkMob()
+
+ tempMobItem._name = "";
+ tempMobItem._examText = "";
+ int txtOffset = READ_LE_UINT32(&_invTxt[itemNr * 8]);
+ int examTxtOffset = READ_LE_UINT32(&_invTxt[itemNr * 8 + 4]);
+
+ stream.seek(txtOffset);
+ while ((c = stream.readByte())) {
+ tempMobItem._name += c;
+ }
+
+ stream.seek(examTxtOffset);
+ while ((c = stream.readByte())) {
+ tempMobItem._examText += c;
+ }
+ _invMobList.push_back(tempMobItem);
+ }
+ currInvX += _invLineW + _invLineSkipX;
+ item++;
+ }
+ currInvX = _invLineX;
+ currInvY += _invLineSkipY + _invLineH;
+ }
+}
+
+void PrinceEngine::drawInvItems() {
+ int currInvX = _invLineX;
+ int currInvY = _invLineY;
+ uint item = 0;
+ for (int i = 0; i < _invLines; i++) {
+ for (int j = 0; j < _invLine; j++) {
+ if (item < _mainHero->_inventory.size()) {
+ int itemNr = _mainHero->_inventory[item];
+ _mst_shadow = 0;
+ if (_mst_shadow2) {
+ if (!_flags->getFlagValue(Flags::CURSEBLINK)) {
+ if (item + 1 == _mainHero->_inventory.size()) { // last item in inventory
+ _mst_shadow = 1;
+ }
+ } else if (itemNr == 1 || itemNr == 3 || itemNr == 4 || itemNr == 7) {
+ _mst_shadow = 1;
+ }
+ }
+
+ int drawX = currInvX;
+ int drawY = currInvY;
+ Graphics::Surface *itemSurface = nullptr;
+ if (itemNr != 68) {
+ itemSurface = _allInvList[itemNr].getSurface();
+ if (itemSurface->h < _maxInvH) {
+ drawY += (_maxInvH - itemSurface->h) / 2;
+ }
+ } else {
+ // candle item:
+ if (_candleCounter == 8) {
+ _candleCounter = 0;
+ }
+ itemNr = _candleCounter;
+ _candleCounter++;
+ itemNr &= 7;
+ itemNr += 71;
+ itemSurface = _allInvList[itemNr].getSurface();
+ drawY += _allInvList[itemNr]._y + (_maxInvH - 76) / 2 - 200;
+ }
+ if (itemSurface->w < _maxInvW) {
+ drawX += (_maxInvW - itemSurface->w) / 2;
+ }
+ if (!_mst_shadow) {
+ _graph->drawTransparentSurface(_graph->_screenForInventory, drawX, drawY, itemSurface);
+ } else {
+ _mst_shadow = _mst_shadow2;
+ _graph->drawTransparentWithBlendSurface(_graph->_screenForInventory, drawX, drawY, itemSurface);
+ }
+ }
+ currInvX += _invLineW + _invLineSkipX;
+ item++;
+ }
+ currInvX = _invLineX;
+ currInvY += _invLineSkipY + _invLineH;
+ }
+}
+
+void PrinceEngine::inventoryLeftMouseButton() {
+ if (!_mouseFlag) {
+ _textSlots[0]._time = 0;
+ _textSlots[0]._str = nullptr;
+ stopSample(28);
+ }
+
+ if (_optionsFlag == 1) {
+ if (_selectedMob != -1) {
+ if (_optionEnabled < _invOptionsNumber) {
+ _optionsFlag = 0;
+ } else {
+ return;
+ }
+ } else {
+ error("PrinceEngine::inventoryLeftMouseButton() - optionsFlag = 1, selectedMob = 0");
+ if (_currentPointerNumber == 2) {
+ changeCursor(1);
+ _currentPointerNumber = 1;
+ _selectedMob = -1;
+ _optionsMob = -1;
+ return;
+ } else {
+ return;
+ }
+ }
+ } else {
+ if (_selectedMob != -1) {
+ if (_currentPointerNumber != 2) {
+ if (_invMobList[_selectedMob]._mask != 29) {
+ _optionEnabled = 0;
+ } else {
+ // map item
+ _optionEnabled = 1;
+ }
+ } else {
+ //use_item_on_item
+ int invObjUU = _script->scanMobEventsWithItem(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUU, _selectedItem);
+ if (invObjUU == -1) {
+ int textNr = 80011; // "I can't do it."
+ if (_selectedItem == 31 || _invMobList[_selectedMob]._mask == 31) {
+ textNr = 80020; // "Nothing is happening."
+ }
+ _interpreter->setCurrentString(textNr);
+ printAt(0, 216, (char *)_variaTxt->getString(textNr - 80000), kNormalWidth / 2, 100);
+ setVoice(0, 28, 1);
+ playSample(28, 0);
+ _selectedMob = -1;
+ _optionsMob = -1;
+ return;
+ } else {
+ _interpreter->storeNewPC(invObjUU);
+ _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
+ _showInventoryFlag = false;
+ }
+ }
+ } else {
+ return;
+ }
+ }
+ //do_option
+ if (_optionEnabled == 0) {
+ int invObjExamEvent = _script->scanMobEvents(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjExam);
+ if (invObjExamEvent == -1) {
+ // do_standard
+ // FIXME: UB?
+ // Constness of the pointer returned by c_str() is cast away (which generates a compiler warning)
+ // while it potentially gets modified inside printAt()
+ printAt(0, 216, (char *)_invMobList[_selectedMob]._examText.c_str(), kNormalWidth / 2, _invExamY);
+ _interpreter->setCurrentString(_invMobList[_selectedMob]._mask + 70000);
+ setVoice(0, 28, 1);
+ playSample(28, 0);
+ // disableuseuse
+ changeCursor(0);
+ _currentPointerNumber = 1;
+ } else {
+ _interpreter->storeNewPC(invObjExamEvent);
+ _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
+ _showInventoryFlag = false;
+ }
+ } else if (_optionEnabled == 1) {
+ // not_examine
+ int invObjUse = _script->scanMobEvents(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUse);
+ if (invObjUse == -1) {
+ // do_standard_use
+ _selectedMode = 0;
+ _selectedItem = _invMobList[_selectedMob]._mask;
+ makeInvCursor(_invMobList[_selectedMob]._mask);
+ _currentPointerNumber = 2;
+ changeCursor(2);
+ } else {
+ _interpreter->storeNewPC(invObjUse);
+ _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
+ _showInventoryFlag = false;
+ }
+ } else if (_optionEnabled == 4) {
+ // do_standard_give
+ _selectedMode = 1;
+ _selectedItem = _invMobList[_selectedMob]._mask;
+ makeInvCursor(_invMobList[_selectedMob]._mask);
+ _currentPointerNumber = 2;
+ changeCursor(2);
+ } else {
+ // use_item_on_item
+ int invObjUU = _script->scanMobEventsWithItem(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUU, _selectedItem);
+ if (invObjUU == -1) {
+ int textNr = 80011; // "I can't do it."
+ if (_selectedItem == 31 || _invMobList[_selectedMob]._mask == 31) {
+ textNr = 80020; // "Nothing is happening."
+ }
+ _interpreter->setCurrentString(textNr);
+ printAt(0, 216, (char *)_variaTxt->getString(textNr - 80000), kNormalWidth / 2, 100);
+ setVoice(0, 28, 1);
+ playSample(28, 0);
+ } else {
+ _interpreter->storeNewPC(invObjUU);
+ _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
+ _showInventoryFlag = false;
+ }
+ }
+ _selectedMob = -1;
+ _optionsMob = -1;
+}
+
+void PrinceEngine::inventoryRightMouseButton() {
+ if (_textSlots[0]._str == nullptr) {
+ enableOptions(false);
+ }
+}
+
+void PrinceEngine::enableOptions(bool checkType) {
+ if (_optionsFlag != 1) {
+ changeCursor(1);
+ _currentPointerNumber = 1;
+ if (_selectedMob != -1) {
+ if (checkType) {
+ if (_mobList[_selectedMob]._type & 0x100) {
+ return;
+ }
+ }
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ int x1 = mousePos.x - _optionsWidth / 2;
+ int x2 = mousePos.x + _optionsWidth / 2;
+ if (x1 < 0) {
+ x1 = 0;
+ x2 = _optionsWidth;
+ } else if (x2 >= kNormalWidth) {
+ x1 = kNormalWidth - _optionsWidth;
+ x2 = kNormalWidth;
+ }
+ int y1 = mousePos.y - 10;
+ if (y1 < 0) {
+ y1 = 0;
+ }
+ if (y1 + _optionsHeight >= kNormalHeight) {
+ y1 = kNormalHeight - _optionsHeight;
+ }
+ _optionsMob = _selectedMob;
+ _optionsX = x1;
+ _optionsY = y1;
+ _optionsFlag = 1;
+ }
+ }
+}
+
+void PrinceEngine::checkOptions() {
+ if (_optionsFlag) {
+ Common::Rect optionsRect(_optionsX, _optionsY, _optionsX + _optionsWidth, _optionsY + _optionsHeight);
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ if (!optionsRect.contains(mousePos)) {
+ _optionsFlag = 0;
+ _selectedMob = -1;
+ return;
+ }
+ _graph->drawAsShadowSurface(_graph->_frontScreen, _optionsX, _optionsY, _optionsPic, _graph->_shadowTable50);
+
+ _optionEnabled = -1;
+ int optionsYCord = mousePos.y - (_optionsY + 16);
+ if (optionsYCord >= 0) {
+ int selectedOptionNr = optionsYCord / _optionsStep;
+ if (selectedOptionNr < _optionsNumber) {
+ _optionEnabled = selectedOptionNr;
+ }
+ }
+ int optionsColor;
+ int textY = _optionsY + 16;
+ for (int i = 0; i < _optionsNumber; i++) {
+ if (i != _optionEnabled) {
+ optionsColor = _optionsColor1;
+ } else {
+ optionsColor = _optionsColor2;
+ }
+ Common::String optText;
+ switch(getLanguage()) {
+ case Common::PL_POL:
+ optText = optionsTextPL[i];
+ break;
+ case Common::DE_DEU:
+ optText = optionsTextDE[i];
+ break;
+ case Common::EN_ANY:
+ optText = optionsTextEN[i];
+ break;
+ case Common::RU_RUS:
+ optText = optionsTextRU[i];
+ break;
+ default:
+ break;
+ };
+ uint16 textW = getTextWidth(optText.c_str());
+ uint16 textX = _optionsX + _optionsWidth / 2 - textW / 2;
+ _font->drawString(_graph->_frontScreen, optText, textX, textY, textW, optionsColor);
+ textY += _optionsStep;
+ }
+ }
+}
+
+void PrinceEngine::checkInvOptions() {
+ if (_optionsFlag) {
+ Common::Rect optionsRect(_optionsX, _optionsY, _optionsX + _invOptionsWidth, _optionsY + _invOptionsHeight);
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ if (!optionsRect.contains(mousePos)) {
+ _optionsFlag = 0;
+ _selectedMob = -1;
+ return;
+ }
+ _graph->drawAsShadowSurface(_graph->_screenForInventory, _optionsX, _optionsY, _optionsPicInInventory, _graph->_shadowTable50);
+
+ _optionEnabled = -1;
+ int optionsYCord = mousePos.y - (_optionsY + 16);
+ if (optionsYCord >= 0) {
+ int selectedOptionNr = optionsYCord / _invOptionsStep;
+ if (selectedOptionNr < _invOptionsNumber) {
+ _optionEnabled = selectedOptionNr;
+ }
+ }
+ int optionsColor;
+ int textY = _optionsY + 16;
+ for (int i = 0; i < _invOptionsNumber; i++) {
+ if (i != _optionEnabled) {
+ optionsColor = _optionsColor1;
+ } else {
+ optionsColor = _optionsColor2;
+ }
+ Common::String invText;
+ switch(getLanguage()) {
+ case Common::PL_POL:
+ invText = invOptionsTextPL[i];
+ break;
+ case Common::DE_DEU:
+ invText = invOptionsTextDE[i];
+ break;
+ case Common::EN_ANY:
+ invText = invOptionsTextEN[i];
+ break;
+ case Common::RU_RUS:
+ invText = invOptionsTextRU[i];
+ break;
+ default:
+ error("Unknown game language %d", getLanguage());
+ break;
+ };
+ uint16 textW = getTextWidth(invText.c_str());
+ uint16 textX = _optionsX + _invOptionsWidth / 2 - textW / 2;
+ _font->drawString(_graph->_screenForInventory, invText, textX, textY, _graph->_screenForInventory->w, optionsColor);
+ textY += _invOptionsStep;
+ }
+ }
+}
+
+void PrinceEngine::displayInventory() {
+
+ _mainHero->freeOldMove();
+ _secondHero->freeOldMove();
+
+ _interpreter->setFgOpcodePC(0);
+
+ stopAllSamples();
+
+ prepareInventoryToView();
+
+ while (!shouldQuit()) {
+
+ if (_textSlots[0]._str != nullptr) {
+ changeCursor(0);
+ } else {
+ changeCursor(_currentPointerNumber);
+
+ Common::Rect inventoryRect(_invX1, _invY1, _invX1 + _invWidth, _invY1 + _invHeight);
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+
+ if (!_invCurInside && inventoryRect.contains(mousePos)) {
+ _invCurInside = true;
+ }
+
+ if (_invCurInside && !inventoryRect.contains(mousePos)) {
+ inventoryFlagChange(false);
+ _invCurInside = false;
+ break;
+ }
+ }
+
+ rememberScreenInv();
+
+ Graphics::Surface *suitcase = _suitcaseBmp->getSurface();
+ _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
+
+ drawInvItems();
+
+ showTexts(_graph->_screenForInventory);
+
+ if (!_optionsFlag && _textSlots[0]._str == nullptr) {
+ _selectedMob = checkMob(_graph->_screenForInventory, _invMobList, false);
+ }
+
+ checkInvOptions();
+
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ keyHandler(event);
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ inventoryLeftMouseButton();
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ inventoryRightMouseButton();
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!_showInventoryFlag) {
+ break;
+ }
+
+ if (shouldQuit())
+ return;
+
+ getDebugger()->onFrame();
+ _graph->update(_graph->_screenForInventory);
+ pausePrinceEngine();
+ }
+
+ if (_currentPointerNumber == 2) {
+ _flags->setFlagValue(Flags::SELITEM, _selectedItem);
+ } else {
+ _flags->setFlagValue(Flags::SELITEM, 0);
+ }
+}
+
+void PrinceEngine::openInventoryCheck() {
+ if (!_optionsFlag) {
+ if (_mouseFlag == 1 || _mouseFlag == 2) {
+ if (_mainHero->_visible) {
+ if (!_flags->getFlagValue(Flags::INVALLOWED)) {
+ // 29 - Basement, 50 - Map
+ if (_locationNr != 29 && _locationNr != 50) {
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ if (mousePos.y < 4 && !_showInventoryFlag) {
+ _invCounter++;
+ } else {
+ _invCounter = 0;
+ }
+ if (_invCounter >= _invMaxCount) {
+ inventoryFlagChange(true);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/mob.cpp b/engines/prince/mob.cpp
index b170ba324b..de15991dba 100644
--- a/engines/prince/mob.cpp
+++ b/engines/prince/mob.cpp
@@ -20,7 +20,11 @@
*
*/
+#include "prince/prince.h"
+
#include "prince/mob.h"
+#include "prince/animation.h"
+#include "prince/font.h"
namespace Prince {
@@ -105,4 +109,158 @@ uint16 Mob::getData(AttrId dataId) {
}
}
+int PrinceEngine::getMob(Common::Array<Mob> &mobList, bool usePriorityList, int posX, int posY) {
+
+ Common::Point pointPos(posX, posY);
+
+ int mobListSize;
+ if (usePriorityList) {
+ mobListSize = _mobPriorityList.size();
+ } else {
+ mobListSize = mobList.size();
+ }
+
+ for (int mobNumber = 0; mobNumber < mobListSize; mobNumber++) {
+ Mob *mob = nullptr;
+ if (usePriorityList) {
+ mob = &mobList[_mobPriorityList[mobNumber]];
+ } else {
+ mob = &mobList[mobNumber];
+ }
+
+ if (mob->_visible) {
+ continue;
+ }
+
+ int type = mob->_type & 7;
+ switch (type) {
+ case 0:
+ case 1:
+ //normal_mob
+ if (!mob->_rect.contains(pointPos)) {
+ continue;
+ }
+ break;
+ case 3:
+ //mob_obj
+ if (mob->_mask < kMaxObjects) {
+ int nr = _objSlot[mob->_mask];
+ if (nr != 0xFF) {
+ Object &obj = *_objList[nr];
+ Common::Rect objectRect(obj._x, obj._y, obj._x + obj._width, obj._y + obj._height);
+ if (objectRect.contains(pointPos)) {
+ Graphics::Surface *objSurface = obj.getSurface();
+ byte *pixel = (byte *)objSurface->getBasePtr(posX - obj._x, posY - obj._y);
+ if (*pixel != 255) {
+ break;
+ }
+ }
+ }
+ }
+ continue;
+ break;
+ case 2:
+ case 5:
+ //check_ba_mob
+ if (!_backAnimList[mob->_mask].backAnims.empty()) {
+ int currentAnim = _backAnimList[mob->_mask]._seq._currRelative;
+ Anim &backAnim = _backAnimList[mob->_mask].backAnims[currentAnim];
+ if (backAnim._animData != nullptr) {
+ if (!backAnim._state) {
+ Common::Rect backAnimRect(backAnim._currX, backAnim._currY, backAnim._currX + backAnim._currW, backAnim._currY + backAnim._currH);
+ if (backAnimRect.contains(pointPos)) {
+ int phase = backAnim._showFrame;
+ int phaseFrameIndex = backAnim._animData->getPhaseFrameIndex(phase);
+ Graphics::Surface *backAnimSurface = backAnim._animData->getFrame(phaseFrameIndex);
+ byte pixel = *(byte *)backAnimSurface->getBasePtr(posX - backAnim._currX, posY - backAnim._currY);
+ if (pixel != 255) {
+ if (type == 5) {
+ if (mob->_rect.contains(pointPos)) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ continue;
+ break;
+ default:
+ //not_part_ba
+ continue;
+ break;
+ }
+
+ if (usePriorityList) {
+ return _mobPriorityList[mobNumber];
+ } else {
+ return mobNumber;
+ }
+ }
+ return -1;
+}
+
+int PrinceEngine::checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobList, bool usePriorityList) {
+ if (_mouseFlag == 0 || _mouseFlag == 3) {
+ return -1;
+ }
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ int mobNumber = getMob(mobList, usePriorityList, mousePos.x + _picWindowX, mousePos.y);
+
+ if (mobNumber != -1) {
+ Common::String mobName = mobList[mobNumber]._name;
+
+ if (getLanguage() == Common::DE_DEU) {
+ for (uint i = 0; i < mobName.size(); i++) {
+ switch (mobName[i]) {
+ case '\xc4':
+ mobName.setChar('\x83', i);
+ break;
+ case '\xd6':
+ mobName.setChar('\x84', i);
+ break;
+ case '\xdc':
+ mobName.setChar('\x85', i);
+ break;
+ case '\xdf':
+ mobName.setChar('\x7f', i);
+ break;
+ case '\xe4':
+ mobName.setChar('\x80', i);
+ break;
+ case '\xf6':
+ mobName.setChar('\x81', i);
+ break;
+ case '\xfc':
+ mobName.setChar('\x82', i);
+ break;
+ }
+ }
+ }
+
+ uint16 textW = getTextWidth(mobName.c_str());
+
+ uint16 x = mousePos.x - textW / 2;
+ if (x > screen->w) {
+ x = 0;
+ }
+
+ if (x + textW > screen->w) {
+ x = screen->w - textW;
+ }
+
+ uint16 y = mousePos.y - _font->getFontHeight();
+ if (y > screen->h) {
+ y = _font->getFontHeight() - 2;
+ }
+
+ _font->drawString(screen, mobName, x, y, screen->w, 216);
+ }
+
+ return mobNumber;
+}
+
} // End of namespace Prince
diff --git a/engines/prince/module.mk b/engines/prince/module.mk
index 27bbc21700..0a24c0c243 100644
--- a/engines/prince/module.mk
+++ b/engines/prince/module.mk
@@ -7,20 +7,25 @@ MODULE_OBJS = \
debugger.o \
decompress.o \
detection.o \
+ draw.o \
flags.o \
font.o \
graphics.o \
hero.o \
+ inventory.o \
mhwanh.o \
+ music.o \
mob.o \
object.o \
prince.o \
pscr.o \
+ resource.o \
saveload.o \
script.o \
sound.o \
variatxt.o \
- videoplayer.o
+ videoplayer.o \
+ walk.o
# This module can be built as a plugin
ifeq ($(ENABLE_PRINCE), DYNAMIC_PLUGIN)
diff --git a/engines/prince/music.cpp b/engines/prince/music.cpp
new file mode 100644
index 0000000000..58a1c1c02a
--- /dev/null
+++ b/engines/prince/music.cpp
@@ -0,0 +1,236 @@
+/* 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 "prince/prince.h"
+#include "prince/music.h"
+#include "prince/musNum.h"
+#include "prince/resource.h"
+
+#include "common/archive.h"
+#include "common/debug.h"
+#include "audio/mididrv.h"
+#include "audio/midiparser.h"
+
+namespace Prince {
+
+const char *MusicPlayer::_musTable[] = {
+ "",
+ "Battlfld.mid",
+ "Cave.mid",
+ "Cemetery.mid",
+ "Credits.mid",
+ "Fjord.mid",
+ "Guitar.mid",
+ "Hell.mid",
+ "Jingle.mid",
+ "Main.mid",
+ "Night.mid",
+ "Reality.mid",
+ "Sunlord.mid",
+ "Tavern.mid",
+ "Temple.mid",
+ "Boruta.mid",
+ "Intro.mid"
+};
+
+const uint8 MusicPlayer::_musRoomTable[] = {
+ 0,
+ ROOM01MUS,
+ ROOM02MUS,
+ ROOM03MUS,
+ ROOM04MUS,
+ ROOM05MUS,
+ ROOM06MUS,
+ ROOM07MUS,
+ ROOM08MUS,
+ ROOM09MUS,
+ ROOM10MUS,
+ ROOM11MUS,
+ ROOM12MUS,
+ ROOM13MUS,
+ ROOM14MUS,
+ ROOM15MUS,
+ ROOM16MUS,
+ ROOM17MUS,
+ ROOM18MUS,
+ ROOM19MUS,
+ ROOM20MUS,
+ ROOM21MUS,
+ ROOM22MUS,
+ ROOM23MUS,
+ ROOM24MUS,
+ ROOM25MUS,
+ ROOM26MUS,
+ ROOM27MUS,
+ ROOM28MUS,
+ ROOM29MUS,
+ ROOM30MUS,
+ ROOM31MUS,
+ ROOM32MUS,
+ ROOM33MUS,
+ ROOM34MUS,
+ ROOM35MUS,
+ ROOM36MUS,
+ ROOM37MUS,
+ ROOM38MUS,
+ ROOM39MUS,
+ ROOM40MUS,
+ ROOM41MUS,
+ ROOM42MUS,
+ ROOM43MUS,
+ 0,
+ 0,
+ ROOM46MUS,
+ ROOM47MUS,
+ ROOM48MUS,
+ ROOM49MUS,
+ ROOM50MUS,
+ ROOM51MUS,
+ ROOM52MUS,
+ ROOM53MUS,
+ ROOM54MUS,
+ ROOM55MUS,
+ ROOM56MUS,
+ ROOM57MUS,
+ ROOM58MUS,
+ ROOM59MUS,
+ ROOM60MUS,
+ ROOM61MUS
+};
+
+
+MusicPlayer::MusicPlayer(PrinceEngine *vm) : _vm(vm) {
+ _data = nullptr;
+ _dataSize = 0;
+ _isGM = false;
+
+ MidiPlayer::createDriver();
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
+}
+
+MusicPlayer::~MusicPlayer() {
+ killMidi();
+}
+
+void MusicPlayer::killMidi() {
+ Audio::MidiPlayer::stop();
+
+ free(_data);
+ _data = nullptr;
+}
+
+void MusicPlayer::loadMidi(const char *name) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
+ if (!stream) {
+ warning("Can't load midi stream %s", name);
+ return;
+ }
+
+ stream = Resource::getDecompressedStream(stream);
+
+ // Stop any currently playing MIDI file
+ killMidi();
+
+ // Read in the data for the file
+ _dataSize = stream->size();
+ _data = (byte *)malloc(_dataSize);
+ stream->read(_data, _dataSize);
+
+ delete stream;
+
+ // Start playing the music
+ sndMidiStart();
+}
+
+void MusicPlayer::sndMidiStart() {
+ _isGM = true;
+
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(_data, _dataSize)) {
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(_driver->getBaseTempo());
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+
+ _parser = parser;
+
+ syncVolume();
+
+ // Al the tracks are supposed to loop
+ _isLooping = true;
+ _isPlaying = true;
+ }
+}
+
+void MusicPlayer::send(uint32 b) {
+ if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+
+ Audio::MidiPlayer::send(b);
+}
+
+void MusicPlayer::sendToChannel(byte channel, uint32 b) {
+ if (!_channelsTable[channel]) {
+ _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
+ // If a new channel is allocated during the playback, make sure
+ // its volume is correctly initialized.
+ if (_channelsTable[channel])
+ _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
+ }
+
+ if (_channelsTable[channel])
+ _channelsTable[channel]->send(b);
+}
+
+bool PrinceEngine::loadMusic(int musNumber) {
+ uint8 midiNumber = MusicPlayer::_musRoomTable[musNumber];
+ if (midiNumber) {
+ if (midiNumber != 100) {
+ if (_currentMidi != midiNumber) {
+ _currentMidi = midiNumber;
+ const char *musName = MusicPlayer::_musTable[_currentMidi];
+ _midiPlayer->loadMidi(musName);
+ }
+ }
+ } else {
+ stopMusic();
+ }
+ return true;
+}
+
+void PrinceEngine::stopMusic() {
+ if (_midiPlayer->isPlaying()) {
+ _midiPlayer->stop();
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/sound.h b/engines/prince/music.h
index 21f9e48b37..061e10c8b8 100644
--- a/engines/prince/sound.h
+++ b/engines/prince/music.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef PRINCE_SOUND_H
-#define PRINCE_SOUND_H
+#ifndef PRINCE_MUSIC_H
+#define PRINCE_MUSIC_H
#include "audio/midiplayer.h"
#include "common/memstream.h"
diff --git a/engines/prince/object.cpp b/engines/prince/object.cpp
index e4a3eda689..109d180355 100644
--- a/engines/prince/object.cpp
+++ b/engines/prince/object.cpp
@@ -28,6 +28,7 @@
#include "graphics/surface.h"
#include "prince/object.h"
+#include "prince/resource.h"
namespace Prince {
@@ -73,6 +74,8 @@ bool Object::loadFromStream(Common::SeekableReadStream &stream) {
const Common::String obStreamName = Common::String::format("OB%02d", stream.readUint16LE());
Common::SeekableReadStream *obStream = SearchMan.createReadStreamForMember(obStreamName);
if (obStream) {
+ obStream = Resource::getDecompressedStream(obStream);
+
loadSurface(*obStream);
}
delete obStream;
diff --git a/engines/prince/option_text.h b/engines/prince/option_text.h
index f56dd421ec..cc97f042af 100644
--- a/engines/prince/option_text.h
+++ b/engines/prince/option_text.h
@@ -82,4 +82,23 @@ const char *optionsTextEN[] = {
"Talk to"
};
+// RU
+const char *invOptionsTextRU[] = {
+ "Cvjnhtnm",
+ "Bcgjkmp.",
+ "Jnrhsnm/""\x83""bnm ",
+ "Pfrhsnm/Nzyenm ",
+ "Lfnm "
+};
+
+const char *optionsTextRU[] = {
+ "Gjlevfnm",
+ "Jcvjnhtnm",
+ "Dpznm ",
+ "Bcgjkmp.",
+ "Jnrhsnm/""\x83""bnm ",
+ "Pfrhsnm/Nzyenm ",
+ "Ujdjhbnm "
+};
+
} // End of namespace Prince
diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp
index 016428935c..cb314aa058 100644
--- a/engines/prince/prince.cpp
+++ b/engines/prince/prince.cpp
@@ -32,34 +32,25 @@
#include "common/substream.h"
#include "common/str.h"
-#include "graphics/cursorman.h"
#include "graphics/surface.h"
-#include "graphics/palette.h"
#include "graphics/pixelformat.h"
#include "engines/util.h"
-#include "audio/audiostream.h"
-#include "audio/decoders/wave.h"
-
#include "prince/prince.h"
-#include "prince/font.h"
#include "prince/graphics.h"
#include "prince/script.h"
#include "prince/debugger.h"
#include "prince/object.h"
#include "prince/mob.h"
-#include "prince/sound.h"
+#include "prince/music.h"
#include "prince/variatxt.h"
-#include "prince/flags.h"
#include "prince/font.h"
#include "prince/mhwanh.h"
#include "prince/cursor.h"
#include "prince/archive.h"
#include "prince/hero.h"
-#include "prince/resource.h"
#include "prince/animation.h"
-#include "prince/option_text.h"
#include "prince/curve_values.h"
namespace Prince {
@@ -217,14 +208,17 @@ void PrinceEngine::init() {
debugEngine("Adding all path: %s", gameDataDir.getPath().c_str());
- if (getLanguage() != Common::RU_RUS) {
+ if (!(getFeatures() & GF_EXTRACTED)) {
PtcArchive *all = new PtcArchive();
if (!all->open("all/databank.ptc"))
error("Can't open all/databank.ptc");
PtcArchive *voices = new PtcArchive();
- if (!voices->open("voices/databank.ptc"))
- error("Can't open voices/databank.ptc");
+
+ if (!(getFeatures() & GF_NOVOICES)) {
+ if (!voices->open("voices/databank.ptc"))
+ error("Can't open voices/databank.ptc");
+ }
PtcArchive *sound = new PtcArchive();
if (!sound->open("sound/databank.ptc"))
@@ -331,6 +325,9 @@ void PrinceEngine::init() {
error("Can't load dialogDatStream");
return;
}
+
+ dialogDatStream = Resource::getDecompressedStream(dialogDatStream);
+
_dialogDatSize = dialogDatStream->size();
_dialogDat = (byte *)malloc(_dialogDatSize);
dialogDatStream->read(_dialogDat, _dialogDatSize);
@@ -464,148 +461,11 @@ void PrinceEngine::pauseEngineIntern(bool pause) {
Engine::pauseEngineIntern(pause);
if (pause) {
_midiPlayer->pause();
- }
- else {
+ } else {
_midiPlayer->resume();
}
}
-bool AnimListItem::loadFromStream(Common::SeekableReadStream &stream) {
- int32 pos = stream.pos();
-
- uint16 type = stream.readUint16LE();
- if (type == 0xFFFF) {
- return false;
- }
- _type = type;
- _fileNumber = stream.readUint16LE();
- _startPhase = stream.readUint16LE();
- _endPhase = stream.readUint16LE();
- _loopPhase = stream.readUint16LE();
- _x = stream.readSint16LE();
- _y = stream.readSint16LE();
- _loopType = stream.readUint16LE();
- _nextAnim = stream.readUint16LE();
- _flags = stream.readUint16LE();
-
- //debug("AnimListItem type %d, fileNumber %d, x %d, y %d, flags %d", _type, _fileNumber, _x, _y, _flags);
- //debug("startPhase %d, endPhase %d, loopPhase %d", _startPhase, _endPhase, _loopPhase);
-
- // 32 byte aligment
- stream.seek(pos + 32);
-
- return true;
-}
-
-bool PrinceEngine::loadLocation(uint16 locationNr) {
-
- blackPalette();
-
- _flicPlayer.close();
-
- memset(_textSlots, 0, sizeof(_textSlots));
- freeAllSamples();
-
- debugEngine("PrinceEngine::loadLocation %d", locationNr);
- const Common::FSNode gameDataDir(ConfMan.get("path"));
- SearchMan.remove(Common::String::format("%02d", _locationNr));
-
- _locationNr = locationNr;
- _debugger->_locationNr = locationNr;
-
- _flags->setFlagValue(Flags::CURRROOM, _locationNr);
- _interpreter->stopBg();
-
- changeCursor(0);
-
- const Common::String locationNrStr = Common::String::format("%02d", _locationNr);
- debugEngine("loadLocation %s", locationNrStr.c_str());
-
- PtcArchive *locationArchive = new PtcArchive();
- if (!locationArchive->open(locationNrStr + "/databank.ptc"))
- error("Can't open location %s", locationNrStr.c_str());
-
- SearchMan.add(locationNrStr, locationArchive);
-
- loadMusic(_locationNr);
-
- // load location background, replace old one
- Resource::loadResource(_roomBmp, "room", true);
- if (_roomBmp->getSurface()) {
- _sceneWidth = _roomBmp->getSurface()->w;
- }
-
- loadZoom(_zoomBitmap, kZoomBitmapLen, "zoom");
- loadShadow(_shadowBitmap, kShadowBitmapSize, "shadow", "shadow2");
- loadTrans(_transTable, "trans");
- loadPath("path");
-
- for (uint32 i = 0; i < _pscrList.size(); i++) {
- delete _pscrList[i];
- }
- _pscrList.clear();
- Resource::loadResource(_pscrList, "pscr.lst", false);
-
- loadMobPriority("mobpri");
-
- _mobList.clear();
- if (getGameType() == kPrinceDataDE) {
- const Common::String mobLstName = Common::String::format("mob%02d.lst", _locationNr);
- debug("name: %s", mobLstName.c_str());
- Resource::loadResource(_mobList, mobLstName.c_str(), false);
- } else if (getGameType() == kPrinceDataPL) {
- Resource::loadResource(_mobList, "mob.lst", false);
- }
- if (getFeatures() & GF_TRANSLATED) {
- // update Mob texts for translated version
- setMobTranslationTexts();
- }
-
- _animList.clear();
- Resource::loadResource(_animList, "anim.lst", false);
-
- for (uint32 i = 0; i < _objList.size(); i++) {
- delete _objList[i];
- }
- _objList.clear();
- Resource::loadResource(_objList, "obj.lst", false);
-
- _room->loadRoom(_script->getRoomOffset(_locationNr));
-
- for (uint i = 0; i < _maskList.size(); i++) {
- free(_maskList[i]._data);
- }
- _maskList.clear();
- _script->loadAllMasks(_maskList, _room->_nak);
-
- _picWindowX = 0;
-
- _lightX = _script->getLightX(_locationNr);
- _lightY = _script->getLightY(_locationNr);
- setShadowScale(_script->getShadowScale(_locationNr));
-
- for (uint i = 0; i < _mobList.size(); i++) {
- _mobList[i]._visible = _script->getMobVisible(_room->_mobs, i);
- }
-
- _script->installObjects(_room->_obj);
-
- freeAllNormAnims();
-
- clearBackAnimList();
- _script->installBackAnims(_backAnimList, _room->_backAnim);
-
- _graph->makeShadowTable(70, _graph->_shadowTable70);
- _graph->makeShadowTable(50, _graph->_shadowTable50);
-
- _mainHero->freeOldMove();
- _secondHero->freeOldMove();
-
- _mainHero->scrollHero();
-
- return true;
-}
-
void PrinceEngine::setShadowScale(int32 shadowScale) {
shadowScale = 100 - shadowScale;
if (!shadowScale) {
@@ -622,122 +482,6 @@ void PrinceEngine::plotShadowLinePoint(int x, int y, int color, void *data) {
vm->_shadLineLen++;
}
-void PrinceEngine::changeCursor(uint16 curId) {
- _debugger->_cursorNr = curId;
- _mouseFlag = curId;
- _flags->setFlagValue(Flags::MOUSEENABLED, curId);
-
- const Graphics::Surface *curSurface = nullptr;
-
- switch (curId) {
- default:
- error("Unknown cursor Id: %d", curId);
- case 0:
- CursorMan.showMouse(false);
- _optionsFlag = 0;
- _selectedMob = -1;
- return;
- case 1:
- curSurface = _cursor1->getSurface();
- break;
- case 2:
- curSurface = _cursor2;
- break;
- case 3:
- curSurface = _cursor3->getSurface();
- Common::Point mousePos = _system->getEventManager()->getMousePos();
- mousePos.x = CLIP(mousePos.x, (int16) 315, (int16) 639);
- mousePos.y = CLIP(mousePos.y, (int16) 0, (int16) 170);
- _system->warpMouse(mousePos.x, mousePos.y);
- break;
- }
-
- CursorMan.replaceCursorPalette(_roomBmp->getPalette(), 0, 255);
- CursorMan.replaceCursor(
- curSurface->getBasePtr(0, 0),
- curSurface->w, curSurface->h,
- 0, 0,
- 255, false,
- &curSurface->format
- );
- CursorMan.showMouse(true);
-}
-
-void PrinceEngine::makeInvCursor(int itemNr) {
- const Graphics::Surface *cur1Surface = _cursor1->getSurface();
- int cur1W = cur1Surface->w;
- int cur1H = cur1Surface->h;
- const Common::Rect cur1Rect(0, 0, cur1W, cur1H);
-
- const Graphics::Surface *itemSurface = _allInvList[itemNr].getSurface();
- int itemW = itemSurface->w;
- int itemH = itemSurface->h;
-
- int cur2W = cur1W + itemW / 2;
- int cur2H = cur1H + itemH / 2;
-
- if (_cursor2 != nullptr) {
- _cursor2->free();
- delete _cursor2;
- }
- _cursor2 = new Graphics::Surface();
- _cursor2->create(cur2W, cur2H, Graphics::PixelFormat::createFormatCLUT8());
- Common::Rect cur2Rect(0, 0, cur2W, cur2H);
- _cursor2->fillRect(cur2Rect, 255);
- _cursor2->copyRectToSurface(*cur1Surface, 0, 0, cur1Rect);
-
- const byte *src1 = (const byte *)itemSurface->getBasePtr(0, 0);
- byte *dst1 = (byte *)_cursor2->getBasePtr(cur1W, cur1H);
-
- if (itemH % 2) {
- itemH--;
- }
- if (itemW % 2) {
- itemW--;
- }
-
- for (int y = 0; y < itemH; y++) {
- const byte *src2 = src1;
- byte *dst2 = dst1;
- if (y % 2 == 0) {
- for (int x = 0; x < itemW; x++, src2++) {
- if (x % 2 == 0) {
- if (*src2) {
- *dst2 = *src2;
- } else {
- *dst2 = 255;
- }
- dst2++;
- }
- }
- dst1 += _cursor2->pitch;
- }
- src1 += itemSurface->pitch;
- }
-}
-
-bool PrinceEngine::loadMusic(int musNumber) {
- uint8 midiNumber = MusicPlayer::_musRoomTable[musNumber];
- if (midiNumber) {
- if (midiNumber != 100) {
- if (_currentMidi != midiNumber) {
- _currentMidi = midiNumber;
- const char *musName = MusicPlayer::_musTable[_currentMidi];
- _midiPlayer->loadMidi(musName);
- }
- }
- } else {
- stopMusic();
- }
- return true;
-}
-
-void PrinceEngine::stopMusic() {
- if (_midiPlayer->isPlaying()) {
- _midiPlayer->stop();
- }
-}
-
bool PrinceEngine::playNextFLCFrame() {
if (!_flicPlayer.isVideoLoaded())
return false;
@@ -758,285 +502,6 @@ bool PrinceEngine::playNextFLCFrame() {
return true;
}
-void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
- if (_audioStream[sampleId]) {
- if (_mixer->isSoundIDActive(sampleId)) {
- return;
- }
- _audioStream[sampleId]->rewind();
- if (sampleId < 28) {
- _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
- } else {
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
- }
- }
-}
-
-void PrinceEngine::stopSample(uint16 sampleId) {
- _mixer->stopID(sampleId);
-}
-
-void PrinceEngine::stopAllSamples() {
- _mixer->stopAll();
-}
-
-void PrinceEngine::freeSample(uint16 sampleId) {
- stopSample(sampleId);
- if (_audioStream[sampleId] != nullptr) {
- delete _audioStream[sampleId];
- _audioStream[sampleId] = nullptr;
- }
-}
-
-void PrinceEngine::freeAllSamples() {
- for (int sampleId = 0; sampleId < kMaxSamples; sampleId++) {
- freeSample(sampleId);
- }
-}
-
-bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) {
- // FIXME: This is just a workaround streamName is a path
- // SOUND\\SCIERKA1.WAV for now only last path component is used
- Common::String normalizedPath = lastPathComponent(streamName, '\\');
-
- // WALKAROUND: Wrong name in script, not existing sound in data files
- if (!normalizedPath.compareTo("9997BEKA.WAV")) {
- return 0;
- }
-
- debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str());
-
- freeSample(sampleSlot);
- Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(normalizedPath);
- if (sampleStream == nullptr) {
- delete sampleStream;
- error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot);
- }
- _audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
- delete sampleStream;
- return true;
-}
-
-bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
- debugEngine("Loading wav %s slot %d", streamName.c_str(), slot);
-
- if (slot >= kMaxTexts) {
- error("Text slot bigger than MAXTEXTS %d", kMaxTexts - 1);
- return false;
- }
-
- freeSample(sampleSlot);
- Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(streamName);
- if (sampleStream == nullptr) {
- debug("Can't open %s", streamName.c_str());
- return false;
- }
-
- uint32 id = sampleStream->readUint32LE();
- if (id != MKTAG('F', 'F', 'I', 'R')) {
- error("It's not RIFF file %s", streamName.c_str());
- return false;
- }
-
- sampleStream->skip(0x20);
- id = sampleStream->readUint32LE();
- if (id != MKTAG('a', 't', 'a', 'd')) {
- error("No data section in %s id %04x", streamName.c_str(), id);
- return false;
- }
-
- id = sampleStream->readUint32LE();
- debugEngine("SetVoice slot %d time %04x", slot, id);
- id <<= 3;
- id /= 22050;
- id += 2;
-
- _textSlots[slot]._time = id;
- if (!slot) {
- _mainHero->_talkTime = id;
- } else if (slot == 1) {
- _secondHero->_talkTime = id;
- }
-
- debugEngine("SetVoice slot %d time %04x", slot, id);
- sampleStream->seek(SEEK_SET);
- _audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
- delete sampleStream;
- return true;
-}
-
-void PrinceEngine::setVoice(uint16 slot, uint32 sampleSlot, uint16 flag) {
- Common::String sampleName;
- uint32 currentString = _interpreter->getCurrentString();
-
- if (currentString >= 80000) {
- uint32 nr = currentString - 80000;
- sampleName = Common::String::format("%02d0%02d-%02d.WAV", nr / 100, nr % 100, flag);
- } else if (currentString >= 70000) {
- sampleName = Common::String::format("inv%02d-01.WAV", currentString - 70000);
- } else if (currentString >= 60000) {
- sampleName = Common::String::format("M%04d-%02d.WAV", currentString - 60000, flag);
- } else if (currentString >= 2000) {
- return;
- } else if (flag >= 100) {
- sampleName = Common::String::format("%03d-%03d.WAV", currentString, flag);
- } else {
- sampleName = Common::String::format("%03d-%02d.WAV", currentString, flag);
- }
-
- loadVoice(slot, sampleSlot, sampleName);
-}
-
-bool PrinceEngine::loadAnim(uint16 animNr, bool loop) {
- Common::String streamName = Common::String::format("AN%02d", animNr);
- Common::SeekableReadStream *flicStream = SearchMan.createReadStreamForMember(streamName);
-
- if (!flicStream) {
- error("Can't open %s", streamName.c_str());
- return false;
- }
-
- if (!_flicPlayer.loadStream(flicStream)) {
- error("Can't load flic stream %s", streamName.c_str());
- }
-
- debugEngine("%s loaded", streamName.c_str());
- _flicLooped = loop;
- _flicPlayer.start();
- playNextFLCFrame();
- return true;
-}
-
-bool PrinceEngine::loadZoom(byte *zoomBitmap, uint32 dataSize, const char *resourceName) {
- Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
- if (!stream) {
- delete stream;
- return false;
- }
- if (stream->read(zoomBitmap, dataSize) != dataSize) {
- free(zoomBitmap);
- delete stream;
- return false;
- }
- delete stream;
- return true;
-}
-
-bool PrinceEngine::loadShadow(byte *shadowBitmap, uint32 dataSize, const char *resourceName1, const char *resourceName2) {
- Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName1);
- if (!stream) {
- delete stream;
- return false;
- }
-
- if (stream->read(shadowBitmap, dataSize) != dataSize) {
- free(shadowBitmap);
- delete stream;
- return false;
- }
-
- Common::SeekableReadStream *stream2 = SearchMan.createReadStreamForMember(resourceName2);
- if (!stream2) {
- delete stream;
- delete stream2;
- return false;
- }
-
- byte *shadowBitmap2 = shadowBitmap + dataSize;
- if (stream2->read(shadowBitmap2, dataSize) != dataSize) {
- free(shadowBitmap);
- delete stream;
- delete stream2;
- return false;
- }
-
- delete stream;
- delete stream2;
- return true;
-}
-
-bool PrinceEngine::loadTrans(byte *transTable, const char *resourceName) {
- Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
- if (!stream) {
- delete stream;
- for (int i = 0; i < 256; i++) {
- for (int j = 0; j < 256; j++) {
- transTable[i * 256 + j] = j;
- }
- }
- return true;
- }
- if (stream->read(transTable, kTransTableSize) != kTransTableSize) {
- delete stream;
- return false;
- }
- delete stream;
- return true;
-}
-
-bool PrinceEngine::loadPath(const char *resourceName) {
- Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
- if (!stream) {
- delete stream;
- return false;
- }
- if (stream->read(_roomPathBitmap, kPathBitmapLen) != kPathBitmapLen) {
- delete stream;
- return false;
- }
- delete stream;
- return true;
-}
-
-bool PrinceEngine::loadAllInv() {
- for (int i = 0; i < kMaxInv; i++) {
- InvItem tempInvItem;
-
- const Common::String invStreamName = Common::String::format("INV%02d", i);
- Common::SeekableReadStream *invStream = SearchMan.createReadStreamForMember(invStreamName);
- if (!invStream) {
- delete invStream;
- return true;
- }
-
- tempInvItem._x = invStream->readUint16LE();
- tempInvItem._y = invStream->readUint16LE();
- int width = invStream->readUint16LE();
- int height = invStream->readUint16LE();
- tempInvItem._surface = new Graphics::Surface();
- tempInvItem._surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
-
- for (int h = 0; h < tempInvItem._surface->h; h++) {
- invStream->read(tempInvItem._surface->getBasePtr(0, h), tempInvItem._surface->w);
- }
-
- _allInvList.push_back(tempInvItem);
- delete invStream;
- }
-
- return true;
-}
-
-bool PrinceEngine::loadMobPriority(const char *resourceName) {
- Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
- if (!stream) {
- delete stream;
- return false;
- }
-
- _mobPriorityList.clear();
- uint mobId;
- while (1) {
- mobId = stream->readUint32LE();
- if (mobId == 0xFFFFFFFF) {
- break;
- }
- _mobPriorityList.push_back(mobId);
- }
- delete stream;
- return true;
-}
-
void PrinceEngine::loadMobTranslationTexts() {
Common::SeekableReadStream *mobTranslationStream = SearchMan.createReadStreamForMember("mob_translate.dat");
if (!mobTranslationStream) {
@@ -1079,6 +544,14 @@ void PrinceEngine::setMobTranslationTexts() {
void PrinceEngine::keyHandler(Common::Event event) {
uint16 nChar = event.kbd.keycode;
switch (nChar) {
+ case Common::KEYCODE_F1:
+ if (canLoadGameStateCurrently())
+ scummVMSaveLoadDialog(false);
+ break;
+ case Common::KEYCODE_F2:
+ if (canSaveGameStateCurrently())
+ scummVMSaveLoadDialog(true);
+ break;
case Common::KEYCODE_d:
if (event.kbd.hasFlags(Common::KBD_CTRL)) {
getDebugger()->attach();
@@ -1100,160 +573,6 @@ void PrinceEngine::keyHandler(Common::Event event) {
}
}
-int PrinceEngine::getMob(Common::Array<Mob> &mobList, bool usePriorityList, int posX, int posY) {
-
- Common::Point pointPos(posX, posY);
-
- int mobListSize;
- if (usePriorityList) {
- mobListSize = _mobPriorityList.size();
- } else {
- mobListSize = mobList.size();
- }
-
- for (int mobNumber = 0; mobNumber < mobListSize; mobNumber++) {
- Mob *mob = nullptr;
- if (usePriorityList) {
- mob = &mobList[_mobPriorityList[mobNumber]];
- } else {
- mob = &mobList[mobNumber];
- }
-
- if (mob->_visible) {
- continue;
- }
-
- int type = mob->_type & 7;
- switch (type) {
- case 0:
- case 1:
- //normal_mob
- if (!mob->_rect.contains(pointPos)) {
- continue;
- }
- break;
- case 3:
- //mob_obj
- if (mob->_mask < kMaxObjects) {
- int nr = _objSlot[mob->_mask];
- if (nr != 0xFF) {
- Object &obj = *_objList[nr];
- Common::Rect objectRect(obj._x, obj._y, obj._x + obj._width, obj._y + obj._height);
- if (objectRect.contains(pointPos)) {
- Graphics::Surface *objSurface = obj.getSurface();
- byte *pixel = (byte *)objSurface->getBasePtr(posX - obj._x, posY - obj._y);
- if (*pixel != 255) {
- break;
- }
- }
- }
- }
- continue;
- break;
- case 2:
- case 5:
- //check_ba_mob
- if (!_backAnimList[mob->_mask].backAnims.empty()) {
- int currentAnim = _backAnimList[mob->_mask]._seq._currRelative;
- Anim &backAnim = _backAnimList[mob->_mask].backAnims[currentAnim];
- if (backAnim._animData != nullptr) {
- if (!backAnim._state) {
- Common::Rect backAnimRect(backAnim._currX, backAnim._currY, backAnim._currX + backAnim._currW, backAnim._currY + backAnim._currH);
- if (backAnimRect.contains(pointPos)) {
- int phase = backAnim._showFrame;
- int phaseFrameIndex = backAnim._animData->getPhaseFrameIndex(phase);
- Graphics::Surface *backAnimSurface = backAnim._animData->getFrame(phaseFrameIndex);
- byte pixel = *(byte *)backAnimSurface->getBasePtr(posX - backAnim._currX, posY - backAnim._currY);
- if (pixel != 255) {
- if (type == 5) {
- if (mob->_rect.contains(pointPos)) {
- break;
- }
- } else {
- break;
- }
- }
- }
- }
- }
- }
- continue;
- break;
- default:
- //not_part_ba
- continue;
- break;
- }
-
- if (usePriorityList) {
- return _mobPriorityList[mobNumber];
- } else {
- return mobNumber;
- }
- }
- return -1;
-}
-
-int PrinceEngine::checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobList, bool usePriorityList) {
- if (_mouseFlag == 0 || _mouseFlag == 3) {
- return -1;
- }
- Common::Point mousePos = _system->getEventManager()->getMousePos();
- int mobNumber = getMob(mobList, usePriorityList, mousePos.x + _picWindowX, mousePos.y);
-
- if (mobNumber != -1) {
- Common::String mobName = mobList[mobNumber]._name;
-
- if (getLanguage() == Common::DE_DEU) {
- for (uint i = 0; i < mobName.size(); i++) {
- switch (mobName[i]) {
- case '\xc4':
- mobName.setChar('\x83', i);
- break;
- case '\xd6':
- mobName.setChar('\x84', i);
- break;
- case '\xdc':
- mobName.setChar('\x85', i);
- break;
- case '\xdf':
- mobName.setChar('\x7f', i);
- break;
- case '\xe4':
- mobName.setChar('\x80', i);
- break;
- case '\xf6':
- mobName.setChar('\x81', i);
- break;
- case '\xfc':
- mobName.setChar('\x82', i);
- break;
- }
- }
- }
-
- uint16 textW = getTextWidth(mobName.c_str());
-
- uint16 x = mousePos.x - textW / 2;
- if (x > screen->w) {
- x = 0;
- }
-
- if (x + textW > screen->w) {
- x = screen->w - textW;
- }
-
- uint16 y = mousePos.y - _font->getFontHeight();
- if (y > screen->h) {
- y = _font->getFontHeight() - 2;
- }
-
- _font->drawString(screen, mobName, x, y, screen->w, 216);
- }
-
- return mobNumber;
-}
-
void PrinceEngine::printAt(uint32 slot, uint8 color, char *s, uint16 x, uint16 y) {
debugC(1, DebugChannel::kEngine, "PrinceEngine::printAt slot %d, color %d, x %02d, y %02d, str %s", slot, color, x, y, s);
@@ -1383,677 +702,6 @@ void PrinceEngine::showTexts(Graphics::Surface *screen) {
}
}
-bool PrinceEngine::spriteCheck(int sprWidth, int sprHeight, int destX, int destY) {
- destX -= _picWindowX;
- destY -= _picWindowY;
-
- // if x1 is on visible part of screen
- if (destX < 0) {
- if (destX + sprWidth < 1) {
- //x2 is negative - out of window
- return false;
- }
- }
- // if x1 is outside of screen on right side
- if (destX >= kNormalWidth) {
- return false;
- }
-
- if (destY < 0) {
- if (destY + sprHeight < 1) {
- //y2 is negative - out of window
- return false;
- }
- }
- if (destY >= kNormalHeight) {
- return false;
- }
-
- return true;
-}
-
-// CheckNak
-void PrinceEngine::checkMasks(int x1, int y1, int sprWidth, int sprHeight, int z) {
- int x2 = x1 + sprWidth - 1;
- int y2 = y1 + sprHeight - 1;
- if (x1 < 0) {
- x1 = 0;
- }
- for (uint i = 0; i < _maskList.size(); i++) {
- if (!_maskList[i]._state && !_maskList[i]._flags) {
- if (_maskList[i]._z > z) {
- if (_maskList[i]._x1 <= x2 && _maskList[i]._x2 >= x1) {
- if (_maskList[i]._y1 <= y2 && _maskList[i]._y2 >= y1) {
- _maskList[i]._state = 1;
- }
- }
- }
- }
- }
-}
-
-// ClsNak
-void PrinceEngine::clsMasks() {
- for (uint i = 0; i < _maskList.size(); i++) {
- if (_maskList[i]._state) {
- _maskList[i]._state = 0;
- }
- }
-}
-
-// InsertNakladki
-void PrinceEngine::insertMasks(Graphics::Surface *originalRoomSurface) {
- for (uint i = 0; i < _maskList.size(); i++) {
- if (_maskList[i]._state) {
- if (_maskList[i]._data != nullptr) {
- showMask(i, originalRoomSurface);
- } else {
- error("insertMasks() - Wrong mask data- nr %d", i);
- }
- }
- }
-}
-
-// ShowNak
-void PrinceEngine::showMask(int maskNr, Graphics::Surface *originalRoomSurface) {
- if (!_maskList[maskNr]._flags) {
- if (spriteCheck(_maskList[maskNr]._width, _maskList[maskNr]._height, _maskList[maskNr]._x1, _maskList[maskNr]._y1)) {
- int destX = _maskList[maskNr]._x1 - _picWindowX;
- int destY = _maskList[maskNr]._y1 - _picWindowY;
- DrawNode newDrawNode;
- newDrawNode.posX = destX;
- newDrawNode.posY = destY;
- newDrawNode.posZ = _maskList[maskNr]._z;
- newDrawNode.width = _maskList[maskNr]._width;
- newDrawNode.height = _maskList[maskNr]._height;
- newDrawNode.s = nullptr;
- newDrawNode.originalRoomSurface = originalRoomSurface;
- newDrawNode.data = _maskList[maskNr].getMask();
- newDrawNode.drawFunction = &_graph->drawMaskDrawNode;
- _drawNodeList.push_back(newDrawNode);
- }
- }
-}
-
-void PrinceEngine::showSprite(Graphics::Surface *spriteSurface, int destX, int destY, int destZ) {
- if (spriteCheck(spriteSurface->w, spriteSurface->h, destX, destY)) {
- destX -= _picWindowX;
- destY -= _picWindowY;
- DrawNode newDrawNode;
- newDrawNode.posX = destX;
- newDrawNode.posY = destY;
- newDrawNode.posZ = destZ;
- newDrawNode.width = 0;
- newDrawNode.height = 0;
- newDrawNode.s = spriteSurface;
- newDrawNode.originalRoomSurface = nullptr;
- newDrawNode.data = _transTable;
- newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
- _drawNodeList.push_back(newDrawNode);
- }
-}
-
-void PrinceEngine::showSpriteShadow(Graphics::Surface *shadowSurface, int destX, int destY, int destZ) {
- if (spriteCheck(shadowSurface->w, shadowSurface->h, destX, destY)) {
- destX -= _picWindowX;
- destY -= _picWindowY;
- DrawNode newDrawNode;
- newDrawNode.posX = destX;
- newDrawNode.posY = destY;
- newDrawNode.posZ = destZ;
- newDrawNode.width = 0;
- newDrawNode.height = 0;
- newDrawNode.s = shadowSurface;
- newDrawNode.originalRoomSurface = nullptr;
- newDrawNode.data = _graph->_shadowTable70;
- newDrawNode.drawFunction = &_graph->drawAsShadowDrawNode;
- _drawNodeList.push_back(newDrawNode);
- }
-}
-
-void PrinceEngine::showAnim(Anim &anim) {
- //ShowFrameCode
- //ShowAnimFrame
- int phase = anim._showFrame;
- int phaseFrameIndex = anim._animData->getPhaseFrameIndex(phase);
- int x = anim._x + anim._animData->getPhaseOffsetX(phase);
- int y = anim._y + anim._animData->getPhaseOffsetY(phase);
- int animFlag = anim._flags;
- int checkMaskFlag = (animFlag & 1);
- int maxFrontFlag = (animFlag & 2);
- int specialZFlag = anim._nextAnim;
- int z = anim._nextAnim;
- Graphics::Surface *animSurface = anim._animData->getFrame(phaseFrameIndex);
- int frameWidth = animSurface->w;
- int frameHeight = animSurface->h;
- int shadowZ = 0;
-
- if (checkMaskFlag) {
- if (!anim._nextAnim) {
- z = y + frameHeight - 1;
- }
- checkMasks(x, y, frameWidth, frameHeight, z);
- }
-
- if (specialZFlag) {
- z = specialZFlag;
- } else if (maxFrontFlag) {
- z = kMaxPicHeight + 1;
- } else {
- z = y + frameHeight - 1;
- }
- shadowZ = z;
-
- anim._currX = x;
- anim._currY = y;
- anim._currW = frameWidth;
- anim._currH = frameHeight;
- showSprite(animSurface, x, y, z);
-
- // make_special_shadow
- if ((anim._flags & 0x80)) {
- DrawNode newDrawNode;
- newDrawNode.posX = x;
- newDrawNode.posY = y + animSurface->h - anim._shadowBack;
- newDrawNode.posZ = Hero::kHeroShadowZ;
- newDrawNode.width = 0;
- newDrawNode.height = 0;
- newDrawNode.scaleValue = _scaleValue;
- newDrawNode.originalRoomSurface = nullptr;
- newDrawNode.data = this;
- newDrawNode.drawFunction = &Hero::showHeroShadow;
- newDrawNode.s = animSurface;
- _drawNodeList.push_back(newDrawNode);
- }
-
- //ShowFrameCodeShadow
- //ShowAnimFrameShadow
- if (anim._shadowData != nullptr) {
- int shadowPhaseFrameIndex = anim._shadowData->getPhaseFrameIndex(phase);
- int shadowX = anim._shadowData->getBaseX() + anim._shadowData->getPhaseOffsetX(phase);
- int shadowY = anim._shadowData->getBaseY() + anim._shadowData->getPhaseOffsetY(phase);
- Graphics::Surface *shadowSurface = anim._shadowData->getFrame(shadowPhaseFrameIndex);
- int shadowFrameWidth = shadowSurface->w;
- int shadowFrameHeight = shadowSurface->h;
-
- if (checkMaskFlag) {
- checkMasks(shadowX, shadowY, shadowFrameWidth, shadowFrameHeight, shadowY + shadowFrameWidth - 1);
- }
-
- if (!shadowZ) {
- if (maxFrontFlag) {
- shadowZ = kMaxPicHeight + 1;
- } else {
- shadowZ = shadowY + shadowFrameWidth - 1;
- }
- }
- showSpriteShadow(shadowSurface, shadowX, shadowY, shadowZ);
- }
-}
-
-void PrinceEngine::showNormAnims() {
- for (int i = 0; i < kMaxNormAnims; i++) {
- Anim &anim = _normAnimList[i];
- if (anim._animData != nullptr) {
- int phaseCount = anim._animData->getPhaseCount();
- if (!anim._state) {
- if (anim._frame == anim._lastFrame - 1) {
- if (anim._loopType) {
- if (anim._loopType == 1) {
- anim._frame = anim._loopFrame;
- } else {
- continue;
- }
- }
- } else {
- anim._frame++;
- }
- anim._showFrame = anim._frame;
- if (anim._showFrame >= phaseCount) {
- anim._showFrame = phaseCount - 1;
- }
- showAnim(anim);
- }
- }
- }
-}
-
-void PrinceEngine::setBackAnim(Anim &backAnim) {
- int start = backAnim._basaData._start;
- if (start != -1) {
- backAnim._frame = start;
- backAnim._showFrame = start;
- backAnim._loopFrame = start;
- }
- int end = backAnim._basaData._end;
- if (end != -1) {
- backAnim._lastFrame = end;
- }
- backAnim._state = 0;
-}
-
-void PrinceEngine::showBackAnims() {
- for (int i = 0; i < kMaxBackAnims; i++) {
- BAS &seq = _backAnimList[i]._seq;
- int activeSubAnim = seq._currRelative;
- if (!_backAnimList[i].backAnims.empty()) {
- if (_backAnimList[i].backAnims[activeSubAnim]._animData != nullptr) {
- if (!_backAnimList[i].backAnims[activeSubAnim]._state) {
- seq._counter++;
- if (seq._type == 2) {
- if (!seq._currRelative) {
- if (seq._counter >= seq._data) {
- if (seq._anims > 2) {
- seq._currRelative = _randomSource.getRandomNumber(seq._anims - 2) + 1;
- activeSubAnim = seq._currRelative;
- seq._current = _backAnimList[i].backAnims[activeSubAnim]._basaData._num;
- }
- setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
- seq._counter = 0;
- }
- }
- }
-
- if (seq._type == 3) {
- if (!seq._currRelative) {
- if (seq._counter < seq._data2) {
- continue;
- } else {
- setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
- }
- }
- }
-
- if (_backAnimList[i].backAnims[activeSubAnim]._frame == _backAnimList[i].backAnims[activeSubAnim]._lastFrame - 1) {
- _backAnimList[i].backAnims[activeSubAnim]._frame = _backAnimList[i].backAnims[activeSubAnim]._loopFrame;
- switch (seq._type) {
- case 1:
- if (seq._anims > 1) {
- int rnd;
- do {
- rnd = _randomSource.getRandomNumber(seq._anims - 1);
- } while (rnd == seq._currRelative);
- seq._currRelative = rnd;
- seq._current = _backAnimList[i].backAnims[rnd]._basaData._num;
- activeSubAnim = rnd;
- setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
- seq._counter = 0;
- }
- break;
- case 2:
- if (seq._currRelative) {
- seq._currRelative = 0;
- seq._current = _backAnimList[i].backAnims[0]._basaData._num;
- activeSubAnim = 0;
- setBackAnim(_backAnimList[i].backAnims[activeSubAnim]);
- seq._counter = 0;
- }
- break;
- case 3:
- seq._currRelative = 0;
- seq._current = _backAnimList[i].backAnims[0]._basaData._num;
- seq._counter = 0;
- seq._data2 = _randomSource.getRandomNumber(seq._data - 1);
- continue; // for bug in original game
- break;
- }
- } else {
- _backAnimList[i].backAnims[activeSubAnim]._frame++;
- }
- _backAnimList[i].backAnims[activeSubAnim]._showFrame = _backAnimList[i].backAnims[activeSubAnim]._frame;
- showAnim(_backAnimList[i].backAnims[activeSubAnim]);
- }
- }
- }
- }
-}
-
-void PrinceEngine::removeSingleBackAnim(int slot) {
- if (!_backAnimList[slot].backAnims.empty()) {
- for (uint j = 0; j < _backAnimList[slot].backAnims.size(); j++) {
- if (_backAnimList[slot].backAnims[j]._animData != nullptr) {
- delete _backAnimList[slot].backAnims[j]._animData;
- _backAnimList[slot].backAnims[j]._animData = nullptr;
- }
- if (_backAnimList[slot].backAnims[j]._shadowData != nullptr) {
- delete _backAnimList[slot].backAnims[j]._shadowData;
- _backAnimList[slot].backAnims[j]._shadowData = nullptr;
- }
- }
- _backAnimList[slot].backAnims.clear();
- _backAnimList[slot]._seq._currRelative = 0;
- }
-}
-
-void PrinceEngine::clearBackAnimList() {
- for (int i = 0; i < kMaxBackAnims; i++) {
- removeSingleBackAnim(i);
- }
-}
-
-void PrinceEngine::grabMap() {
- _graph->_frontScreen->copyFrom(*_roomBmp->getSurface());
- showObjects();
- runDrawNodes();
- _graph->_mapScreen->copyFrom(*_graph->_frontScreen);
-}
-
-void PrinceEngine::initZoomIn(int slot) {
- freeZoomObject(slot);
- Object *object = _objList[slot];
- if (object != nullptr) {
- Graphics::Surface *zoomSource = object->getSurface();
- if (zoomSource != nullptr) {
- object->_flags |= 0x8000;
- object->_zoomSurface = new Graphics::Surface();
- object->_zoomSurface->create(zoomSource->w, zoomSource->h, Graphics::PixelFormat::createFormatCLUT8());
- object->_zoomSurface->fillRect(Common::Rect(zoomSource->w, zoomSource->h), 0xFF);
- object->_zoomTime = 20;
- }
- }
-}
-
-void PrinceEngine::initZoomOut(int slot) {
- freeZoomObject(slot);
- Object *object = _objList[slot];
- if (object != nullptr) {
- Graphics::Surface *zoomSource = object->getSurface();
- if (zoomSource != nullptr) {
- object->_flags |= 0x4000;
- object->_zoomSurface = new Graphics::Surface();
- object->_zoomSurface->copyFrom(*zoomSource);
- object->_zoomTime = 10;
- }
- }
-}
-
-void PrinceEngine::doZoomIn(int slot) {
- Object *object = _objList[slot];
- if (object != nullptr) {
- Graphics::Surface *orgSurface = object->getSurface();
- if (orgSurface != nullptr) {
- byte *src1 = (byte *)orgSurface->getBasePtr(0, 0);
- byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
- int x = 0;
- int surfaceHeight = orgSurface->h;
- for (int y = 0; y < surfaceHeight; y++) {
- byte *src2 = src1;
- byte *dst2 = dst1;
- int w = orgSurface->w - x;
- src2 += x;
- dst2 += x;
- while (w > 0) {
- int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
- if (randVal < w) {
- *(dst2 + randVal) = *(src2 + randVal);
- src2 += zoomInStep;
- dst2 += zoomInStep;
- } else if (y + 1 != surfaceHeight) {
- *(dst1 + orgSurface->pitch + randVal - w) = *(src1 + orgSurface->pitch + randVal - w);
- }
- w -= zoomInStep;
- }
- x = -1 * w;
- src1 += orgSurface->pitch;
- dst1 += orgSurface->pitch;
- }
- }
- }
-}
-
-void PrinceEngine::doZoomOut(int slot) {
- Object *object = _objList[slot];
- if (object != nullptr) {
- Graphics::Surface *orgSurface = object->getSurface();
- if (orgSurface != nullptr) {
- byte *dst1 = (byte *)object->_zoomSurface->getBasePtr(0, 0);
- int x = 0;
- int surfaceHeight = orgSurface->h;
- for (int y = 0; y < surfaceHeight; y++) {
- byte *dst2 = dst1;
- int w = orgSurface->w - x;
- dst2 += x;
- while (w > 0) {
- int randVal = _randomSource.getRandomNumber(zoomInStep - 1);
- if (randVal < w) {
- *(dst2 + randVal) = 255;
- dst2 += zoomInStep;
- } else if (y + 1 != surfaceHeight) {
- *(dst1 + orgSurface->pitch + randVal - w) = 255;
- }
- w -= zoomInStep;
- }
- x = -1 * w;
- dst1 += orgSurface->pitch;
- }
- }
- }
-}
-
-void PrinceEngine::freeZoomObject(int slot) {
- Object *object = _objList[slot];
- if (object != nullptr) {
- if (object->_zoomSurface != nullptr) {
- object->_zoomSurface->free();
- delete object->_zoomSurface;
- object->_zoomSurface = nullptr;
- }
- }
-}
-
-void PrinceEngine::showObjects() {
- for (int i = 0; i < kMaxObjects; i++) {
- int nr = _objSlot[i];
- if (nr != 0xFF) {
- Graphics::Surface *objSurface = nullptr;
- if ((_objList[nr]->_flags & 0x8000)) {
- _objList[nr]->_zoomTime--;
- if (!_objList[nr]->_zoomTime) {
- freeZoomObject(nr);
- _objList[nr]->_flags &= 0x7FFF;
- objSurface = _objList[nr]->getSurface();
- } else {
- doZoomIn(nr);
- objSurface = _objList[nr]->_zoomSurface;
- }
- } else if ((_objList[nr]->_flags & 0x4000)) {
- _objList[nr]->_zoomTime--;
- if (!_objList[nr]->_zoomTime) {
- freeZoomObject(nr);
- _objList[nr]->_flags &= 0xBFFF;
- objSurface = _objList[nr]->getSurface();
- } else {
- doZoomOut(nr);
- objSurface = _objList[nr]->_zoomSurface;
- }
- } else {
- objSurface = _objList[nr]->getSurface();
- }
-
- if (objSurface != nullptr) {
- if (spriteCheck(objSurface->w, objSurface->h, _objList[nr]->_x, _objList[nr]->_y)) {
- int destX = _objList[nr]->_x - _picWindowX;
- int destY = _objList[nr]->_y - _picWindowY;
- DrawNode newDrawNode;
- newDrawNode.posX = destX;
- newDrawNode.posY = destY;
- newDrawNode.posZ = _objList[nr]->_z;
- newDrawNode.width = 0;
- newDrawNode.height = 0;
- newDrawNode.s = objSurface;
- newDrawNode.originalRoomSurface = nullptr;
- if ((_objList[nr]->_flags & 0x2000)) {
- newDrawNode.data = nullptr;
- newDrawNode.drawFunction = &_graph->drawBackSpriteDrawNode;
- } else {
- newDrawNode.data = _transTable;
- if (_flags->getFlagValue(Flags::NOANTIALIAS)) {
- newDrawNode.drawFunction = &_graph->drawTransparentDrawNode;
- } else {
- newDrawNode.drawFunction = &_graph->drawTransparentWithTransDrawNode;
- }
- }
- _drawNodeList.push_back(newDrawNode);
- }
-
- if ((_objList[nr]->_flags & 1)) {
- checkMasks(_objList[nr]->_x, _objList[nr]->_y, objSurface->w, objSurface->h, _objList[nr]->_z);
- }
- }
- }
- }
-}
-
-void PrinceEngine::showParallax() {
- if (!_pscrList.empty()) {
- for (uint i = 0; i < _pscrList.size(); i++) {
- Graphics::Surface *pscrSurface = _pscrList[i]->getSurface();
- if (pscrSurface != nullptr) {
- int x = _pscrList[i]->_x - (_pscrList[i]->_step * _picWindowX / 4);
- int y = _pscrList[i]->_y;
- int z = PScr::kPScrZ;
- if (spriteCheck(pscrSurface->w, pscrSurface->h, x, y)) {
- showSprite(pscrSurface, x, y, z);
- }
- }
- }
- }
-}
-
-bool PrinceEngine::compareDrawNodes(DrawNode d1, DrawNode d2) {
- if (d1.posZ < d2.posZ) {
- return true;
- }
- return false;
-}
-
-void PrinceEngine::runDrawNodes() {
- Common::sort(_drawNodeList.begin(), _drawNodeList.end(), compareDrawNodes);
-
- for (uint i = 0; i < _drawNodeList.size(); i++) {
- (*_drawNodeList[i].drawFunction)(_graph->_frontScreen, &_drawNodeList[i]);
- }
- _graph->change();
-}
-
-void PrinceEngine::drawScreen() {
- if (!_showInventoryFlag || _inventoryBackgroundRemember) {
- clsMasks();
-
- _mainHero->showHero();
- _mainHero->scrollHero();
- _mainHero->drawHero();
-
- _secondHero->showHero();
- _secondHero->_drawX -= _picWindowX;
- _secondHero->drawHero();
-
- const Graphics::Surface *roomSurface;
- if (_locationNr != 50) {
- roomSurface = _roomBmp->getSurface();
- } else {
- roomSurface = _graph->_mapScreen;
- }
- Graphics::Surface visiblePart;
- if (roomSurface) {
- visiblePart = roomSurface->getSubArea(Common::Rect(_picWindowX, 0, roomSurface->w, roomSurface->h));
- _graph->draw(_graph->_frontScreen, &visiblePart);
- }
-
- showBackAnims();
-
- showNormAnims();
-
- playNextFLCFrame();
-
- showObjects();
-
- if (roomSurface) {
- insertMasks(&visiblePart);
- }
-
- showParallax();
-
- runDrawNodes();
-
- _drawNodeList.clear();
-
- if (!_inventoryBackgroundRemember && !_dialogFlag) {
- if (!_optionsFlag) {
- _selectedMob = checkMob(_graph->_frontScreen, _mobList, true);
- }
- showTexts(_graph->_frontScreen);
- checkOptions();
- } else {
- _inventoryBackgroundRemember = false;
- }
-
- showPower();
-
- getDebugger()->onFrame();
-
- } else {
- displayInventory();
- }
-}
-
-void PrinceEngine::blackPalette() {
- byte *paletteBackup = (byte *)malloc(256 * 3);
- byte *blackPalette1 = (byte *)malloc(256 * 3);
-
- int fadeStep = kFadeStep - 1;
- for (int i = 0; i < kFadeStep; i++) {
- _system->getPaletteManager()->grabPalette(paletteBackup, 0, 256);
- for (int j = 0; j < 256; j++) {
- blackPalette1[3 * j] = paletteBackup[3 * j] * fadeStep / 4;
- blackPalette1[3 * j + 1] = paletteBackup[3 * j + 1] * fadeStep / 4;
- blackPalette1[3 * j + 2] = paletteBackup[3 * j + 2] * fadeStep / 4;
- }
- fadeStep--;
- _graph->setPalette(blackPalette1);
- _system->updateScreen();
- Common::Event event;
- Common::EventManager *eventMan = _system->getEventManager();
- eventMan->pollEvent(event);
- if (shouldQuit()) {
- free(paletteBackup);
- free(blackPalette1);
- return;
- }
- pausePrinceEngine();
- }
- free(paletteBackup);
- free(blackPalette1);
-}
-
-void PrinceEngine::setPalette(const byte *palette) {
- if (palette != nullptr) {
- byte *blackPalette_ = (byte *)malloc(256 * 3);
- int fadeStep = 0;
- for (int i = 0; i <= kFadeStep; i++) {
- for (int j = 0; j < 256; j++) {
- blackPalette_[3 * j] = palette[3 * j] * fadeStep / 4;
- blackPalette_[3 * j + 1] = palette[3 * j + 1] * fadeStep / 4;
- blackPalette_[3 * j + 2] = palette[3 * j + 2] * fadeStep / 4;
- }
- fadeStep++;
- _graph->setPalette(blackPalette_);
- _system->updateScreen();
- Common::Event event;
- Common::EventManager *eventMan = _system->getEventManager();
- eventMan->pollEvent(event);
- if (shouldQuit()) {
- _graph->setPalette(palette);
- free(blackPalette_);
- return;
- }
- pausePrinceEngine();
- }
- _graph->setPalette(palette);
- free(blackPalette_);
- }
-}
-
void PrinceEngine::pausePrinceEngine(int fps) {
int delay = 1000 / fps - int32(_system->getMillis() - _currentTime);
delay = delay < 0 ? 0 : delay;
@@ -2061,369 +709,6 @@ void PrinceEngine::pausePrinceEngine(int fps) {
_currentTime = _system->getMillis();
}
-void PrinceEngine::addInv(int heroId, int item, bool addItemQuiet) {
- Hero *hero = nullptr;
- if (!heroId) {
- hero = _mainHero;
- } else if (heroId == 1) {
- hero = _secondHero;
- }
- if (hero != nullptr) {
- if (hero->_inventory.size() < kMaxItems) {
- if (item != 0x7FFF) {
- hero->_inventory.push_back(item);
- }
- if (!addItemQuiet) {
- addInvObj();
- }
- _interpreter->setResult(0);
- } else {
- _interpreter->setResult(1);
- }
- }
-}
-
-void PrinceEngine::remInv(int heroId, int item) {
- Hero *hero = nullptr;
- if (!heroId) {
- hero = _mainHero;
- } else if (heroId == 1) {
- hero = _secondHero;
- }
- if (hero != nullptr) {
- for (uint i = 0; i < hero->_inventory.size(); i++) {
- if (hero->_inventory[i] == item) {
- hero->_inventory.remove_at(i);
- _interpreter->setResult(0);
- return;
- }
- }
- }
- _interpreter->setResult(1);
-}
-
-void PrinceEngine::clearInv(int heroId) {
- switch (heroId) {
- case 0:
- _mainHero->_inventory.clear();
- break;
- case 1:
- _secondHero->_inventory.clear();
- break;
- default:
- error("clearInv() - wrong hero slot");
- break;
- }
-}
-
-void PrinceEngine::swapInv(int heroId) {
- Common::Array<int> tempInv;
- Hero *hero = nullptr;
- if (!heroId) {
- hero = _mainHero;
- } else if (heroId == 1) {
- hero = _secondHero;
- }
- if (hero != nullptr) {
- for (uint i = 0; i < hero->_inventory.size(); i++) {
- tempInv.push_back(hero->_inventory[i]);
- }
- hero->_inventory.clear();
- for (uint i = 0; i < hero->_inventory2.size(); i++) {
- hero->_inventory.push_back(hero->_inventory2[i]);
- }
- hero->_inventory2.clear();
- for (uint i = 0; i < tempInv.size(); i++) {
- hero->_inventory2.push_back(tempInv[i]);
- }
- tempInv.clear();
- }
-}
-
-void PrinceEngine::addInvObj() {
- changeCursor(0);
- prepareInventoryToView();
-
- _inventoryBackgroundRemember = true;
- drawScreen();
-
- Graphics::Surface *suitcase = _suitcaseBmp->getSurface();
-
- if (!_flags->getFlagValue(Flags::CURSEBLINK)) {
-
- loadSample(27, "PRZEDMIO.WAV");
- playSample(27, 0);
-
- _mst_shadow2 = 1;
-
- while (_mst_shadow2 < 512) {
- rememberScreenInv();
- _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
- drawInvItems();
- _graph->update(_graph->_screenForInventory);
- _mst_shadow2 += 50;
- Common::Event event;
- Common::EventManager *eventMan = _system->getEventManager();
- eventMan->pollEvent(event);
- if (shouldQuit()) {
- return;
- }
- pausePrinceEngine();
- }
- while (_mst_shadow2 > 256) {
- rememberScreenInv();
- _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
- drawInvItems();
- _graph->update(_graph->_screenForInventory);
- _mst_shadow2 -= 42;
- Common::Event event;
- Common::EventManager *eventMan = _system->getEventManager();
- eventMan->pollEvent(event);
- if (shouldQuit()) {
- return;
- }
- pausePrinceEngine();
- }
- } else {
- //CURSEBLINK:
- for (int i = 0; i < 3; i++) {
- _mst_shadow2 = 256;
- while (_mst_shadow2 < 512) {
- rememberScreenInv();
- _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
- drawInvItems();
- _graph->update(_graph->_screenForInventory);
- _mst_shadow2 += 50;
- Common::Event event;
- Common::EventManager *eventMan = _system->getEventManager();
- eventMan->pollEvent(event);
- if (shouldQuit()) {
- return;
- }
- pausePrinceEngine();
- }
- while (_mst_shadow2 > 256) {
- rememberScreenInv();
- _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
- drawInvItems();
- _graph->update(_graph->_screenForInventory);
- _mst_shadow2 -= 50;
- Common::Event event;
- Common::EventManager *eventMan = _system->getEventManager();
- eventMan->pollEvent(event);
- if (shouldQuit()) {
- return;
- }
- pausePrinceEngine();
- }
- }
- }
- _mst_shadow2 = 0;
- for (int i = 0; i < 20; i++) {
- rememberScreenInv();
- _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
- drawInvItems();
- _graph->update(_graph->_screenForInventory);
- Common::Event event;
- Common::EventManager *eventMan = _system->getEventManager();
- eventMan->pollEvent(event);
- if (shouldQuit()) {
- return;
- }
- pausePrinceEngine();
- }
-}
-
-void PrinceEngine::rememberScreenInv() {
- _graph->_screenForInventory->copyFrom(*_graph->_frontScreen);
-}
-
-void PrinceEngine::inventoryFlagChange(bool inventoryState) {
- if (inventoryState) {
- _showInventoryFlag = true;
- _inventoryBackgroundRemember = true;
- } else {
- _showInventoryFlag = false;
- }
-}
-
-void PrinceEngine::prepareInventoryToView() {
- _invMobList.clear();
- int invItem = _mainHero->_inventory.size();
- _invLine = invItem / 3;
- if (invItem % 3) {
- _invLine++;
- }
- if (_invLine < 4) {
- _invLine = 4;
- }
- _maxInvW = (374 - 2 * _invLine) / _invLine;
- _invLineW = _maxInvW - 2;
-
- int currInvX = _invLineX;
- int currInvY = _invLineY;
-
- Common::MemoryReadStream stream(_invTxt, _invTxtSize);
- byte c;
-
- uint item = 0;
- for (int i = 0; i < _invLines; i++) {
- for (int j = 0; j < _invLine; j++) {
- Mob tempMobItem;
- if (item < _mainHero->_inventory.size()) {
- int itemNr = _mainHero->_inventory[item];
- tempMobItem._visible = 0;
- tempMobItem._mask = itemNr;
- tempMobItem._rect = Common::Rect(currInvX + _picWindowX, currInvY, currInvX + _picWindowX + _invLineW - 1, currInvY + _invLineH - 1);
- tempMobItem._type = 0; // to work with checkMob()
-
- tempMobItem._name = "";
- tempMobItem._examText = "";
- int txtOffset = READ_LE_UINT32(&_invTxt[itemNr * 8]);
- int examTxtOffset = READ_LE_UINT32(&_invTxt[itemNr * 8 + 4]);
-
- stream.seek(txtOffset);
- while ((c = stream.readByte())) {
- tempMobItem._name += c;
- }
-
- stream.seek(examTxtOffset);
- while ((c = stream.readByte())) {
- tempMobItem._examText += c;
- }
- _invMobList.push_back(tempMobItem);
- }
- currInvX += _invLineW + _invLineSkipX;
- item++;
- }
- currInvX = _invLineX;
- currInvY += _invLineSkipY + _invLineH;
- }
-}
-
-void PrinceEngine::drawInvItems() {
- int currInvX = _invLineX;
- int currInvY = _invLineY;
- uint item = 0;
- for (int i = 0; i < _invLines; i++) {
- for (int j = 0; j < _invLine; j++) {
- if (item < _mainHero->_inventory.size()) {
- int itemNr = _mainHero->_inventory[item];
- _mst_shadow = 0;
- if (_mst_shadow2) {
- if (!_flags->getFlagValue(Flags::CURSEBLINK)) {
- if (item + 1 == _mainHero->_inventory.size()) { // last item in inventory
- _mst_shadow = 1;
- }
- } else if (itemNr == 1 || itemNr == 3 || itemNr == 4 || itemNr == 7) {
- _mst_shadow = 1;
- }
- }
-
- int drawX = currInvX;
- int drawY = currInvY;
- Graphics::Surface *itemSurface = nullptr;
- if (itemNr != 68) {
- itemSurface = _allInvList[itemNr].getSurface();
- if (itemSurface->h < _maxInvH) {
- drawY += (_maxInvH - itemSurface->h) / 2;
- }
- } else {
- // candle item:
- if (_candleCounter == 8) {
- _candleCounter = 0;
- }
- itemNr = _candleCounter;
- _candleCounter++;
- itemNr &= 7;
- itemNr += 71;
- itemSurface = _allInvList[itemNr].getSurface();
- drawY += _allInvList[itemNr]._y + (_maxInvH - 76) / 2 - 200;
- }
- if (itemSurface->w < _maxInvW) {
- drawX += (_maxInvW - itemSurface->w) / 2;
- }
- if (!_mst_shadow) {
- _graph->drawTransparentSurface(_graph->_screenForInventory, drawX, drawY, itemSurface);
- } else {
- _mst_shadow = _mst_shadow2;
- _graph->drawTransparentWithBlendSurface(_graph->_screenForInventory, drawX, drawY, itemSurface);
- }
- }
- currInvX += _invLineW + _invLineSkipX;
- item++;
- }
- currInvX = _invLineX;
- currInvY += _invLineSkipY + _invLineH;
- }
-}
-
-void PrinceEngine::walkTo() {
- if (_mainHero->_visible) {
- _mainHero->freeHeroAnim();
- _mainHero->freeOldMove();
- _interpreter->storeNewPC(_script->_scriptInfo.usdCode);
- int destX, destY;
- if (_optionsMob != -1) {
- destX = _mobList[_optionsMob]._examPosition.x;
- destY = _mobList[_optionsMob]._examPosition.y;
- _mainHero->_destDirection = _mobList[_optionsMob]._examDirection;
- } else {
- Common::Point mousePos = _system->getEventManager()->getMousePos();
- destX = mousePos.x + _picWindowX;
- destY = mousePos.y + _picWindowY;
- _mainHero->_destDirection = 0;
- }
- _mainHero->_coords = makePath(kMainHero, _mainHero->_middleX, _mainHero->_middleY, destX, destY);
- if (_mainHero->_coords != nullptr) {
- _mainHero->_currCoords = _mainHero->_coords;
- _mainHero->_dirTab = _directionTable;
- _mainHero->_currDirTab = _directionTable;
- _directionTable = nullptr;
- _mainHero->_state = Hero::kHeroStateMove;
- moveShandria();
- }
- }
-}
-
-void PrinceEngine::moveRunHero(int heroId, int x, int y, int dir, bool runHeroFlag) {
- Hero *hero = nullptr;
- if (!heroId) {
- hero = _mainHero;
- } else if (heroId == 1) {
- hero = _secondHero;
- }
-
- if (hero != nullptr) {
- if (dir) {
- hero->_destDirection = dir;
- }
- if (x || y) {
- hero->freeOldMove();
- hero->_coords = makePath(heroId, hero->_middleX, hero->_middleY, x, y);
- if (hero->_coords != nullptr) {
- hero->_currCoords = hero->_coords;
- hero->_dirTab = _directionTable;
- hero->_currDirTab = _directionTable;
- _directionTable = nullptr;
- if (runHeroFlag) {
- hero->_state = Hero::kHeroStateRun;
- } else {
- hero->_state = Hero::kHeroStateMove;
- }
- if (heroId == kMainHero && _mouseFlag) {
- moveShandria();
- }
- }
- } else {
- hero->freeOldMove();
- hero->_state = Hero::kHeroStateTurn;
- }
- hero->freeHeroAnim();
- hero->_visible = 1;
- }
-}
-
void PrinceEngine::leftMouseButton() {
_flags->setFlagValue(Flags::ESCAPED2, 1); // skip intro animation
_flags->setFlagValue(Flags::LMOUSE, 1);
@@ -2524,351 +809,6 @@ void PrinceEngine::rightMouseButton() {
}
}
-void PrinceEngine::inventoryLeftMouseButton() {
- if (!_mouseFlag) {
- _textSlots[0]._time = 0;
- _textSlots[0]._str = nullptr;
- stopSample(28);
- }
-
- if (_optionsFlag == 1) {
- if (_selectedMob != -1) {
- if (_optionEnabled < _invOptionsNumber) {
- _optionsFlag = 0;
- } else {
- return;
- }
- } else {
- error("PrinceEngine::inventoryLeftMouseButton() - optionsFlag = 1, selectedMob = 0");
- if (_currentPointerNumber == 2) {
- changeCursor(1);
- _currentPointerNumber = 1;
- _selectedMob = -1;
- _optionsMob = -1;
- return;
- } else {
- return;
- }
- }
- } else {
- if (_selectedMob != -1) {
- if (_currentPointerNumber != 2) {
- if (_invMobList[_selectedMob]._mask != 29) {
- _optionEnabled = 0;
- } else {
- // map item
- _optionEnabled = 1;
- }
- } else {
- //use_item_on_item
- int invObjUU = _script->scanMobEventsWithItem(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUU, _selectedItem);
- if (invObjUU == -1) {
- int textNr = 80011; // "I can't do it."
- if (_selectedItem == 31 || _invMobList[_selectedMob]._mask == 31) {
- textNr = 80020; // "Nothing is happening."
- }
- _interpreter->setCurrentString(textNr);
- printAt(0, 216, (char *)_variaTxt->getString(textNr - 80000), kNormalWidth / 2, 100);
- setVoice(0, 28, 1);
- playSample(28, 0);
- _selectedMob = -1;
- _optionsMob = -1;
- return;
- } else {
- _interpreter->storeNewPC(invObjUU);
- _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
- _showInventoryFlag = false;
- }
- }
- } else {
- return;
- }
- }
- //do_option
- if (_optionEnabled == 0) {
- int invObjExamEvent = _script->scanMobEvents(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjExam);
- if (invObjExamEvent == -1) {
- // do_standard
- printAt(0, 216, (char *)_invMobList[_selectedMob]._examText.c_str(), kNormalWidth / 2, _invExamY);
- _interpreter->setCurrentString(_invMobList[_selectedMob]._mask + 70000);
- setVoice(0, 28, 1);
- playSample(28, 0);
- // disableuseuse
- changeCursor(0);
- _currentPointerNumber = 1;
- } else {
- _interpreter->storeNewPC(invObjExamEvent);
- _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
- _showInventoryFlag = false;
- }
- } else if (_optionEnabled == 1) {
- // not_examine
- int invObjUse = _script->scanMobEvents(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUse);
- if (invObjUse == -1) {
- // do_standard_use
- _selectedMode = 0;
- _selectedItem = _invMobList[_selectedMob]._mask;
- makeInvCursor(_invMobList[_selectedMob]._mask);
- _currentPointerNumber = 2;
- changeCursor(2);
- } else {
- _interpreter->storeNewPC(invObjUse);
- _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
- _showInventoryFlag = false;
- }
- } else if (_optionEnabled == 4) {
- // do_standard_give
- _selectedMode = 1;
- _selectedItem = _invMobList[_selectedMob]._mask;
- makeInvCursor(_invMobList[_selectedMob]._mask);
- _currentPointerNumber = 2;
- changeCursor(2);
- } else {
- // use_item_on_item
- int invObjUU = _script->scanMobEventsWithItem(_invMobList[_selectedMob]._mask, _script->_scriptInfo.invObjUU, _selectedItem);
- if (invObjUU == -1) {
- int textNr = 80011; // "I can't do it."
- if (_selectedItem == 31 || _invMobList[_selectedMob]._mask == 31) {
- textNr = 80020; // "Nothing is happening."
- }
- _interpreter->setCurrentString(textNr);
- printAt(0, 216, (char *)_variaTxt->getString(textNr - 80000), kNormalWidth / 2, 100);
- setVoice(0, 28, 1);
- playSample(28, 0);
- } else {
- _interpreter->storeNewPC(invObjUU);
- _flags->setFlagValue(Flags::CURRMOB, _invMobList[_selectedMob]._mask);
- _showInventoryFlag = false;
- }
- }
- _selectedMob = -1;
- _optionsMob = -1;
-}
-
-void PrinceEngine::inventoryRightMouseButton() {
- if (_textSlots[0]._str == nullptr) {
- enableOptions(false);
- }
-}
-
-void PrinceEngine::enableOptions(bool checkType) {
- if (_optionsFlag != 1) {
- changeCursor(1);
- _currentPointerNumber = 1;
- if (_selectedMob != -1) {
- if (checkType) {
- if (_mobList[_selectedMob]._type & 0x100) {
- return;
- }
- }
- Common::Point mousePos = _system->getEventManager()->getMousePos();
- int x1 = mousePos.x - _optionsWidth / 2;
- int x2 = mousePos.x + _optionsWidth / 2;
- if (x1 < 0) {
- x1 = 0;
- x2 = _optionsWidth;
- } else if (x2 >= kNormalWidth) {
- x1 = kNormalWidth - _optionsWidth;
- x2 = kNormalWidth;
- }
- int y1 = mousePos.y - 10;
- if (y1 < 0) {
- y1 = 0;
- }
- if (y1 + _optionsHeight >= kNormalHeight) {
- y1 = kNormalHeight - _optionsHeight;
- }
- _optionsMob = _selectedMob;
- _optionsX = x1;
- _optionsY = y1;
- _optionsFlag = 1;
- }
- }
-}
-
-void PrinceEngine::checkOptions() {
- if (_optionsFlag) {
- Common::Rect optionsRect(_optionsX, _optionsY, _optionsX + _optionsWidth, _optionsY + _optionsHeight);
- Common::Point mousePos = _system->getEventManager()->getMousePos();
- if (!optionsRect.contains(mousePos)) {
- _optionsFlag = 0;
- _selectedMob = -1;
- return;
- }
- _graph->drawAsShadowSurface(_graph->_frontScreen, _optionsX, _optionsY, _optionsPic, _graph->_shadowTable50);
-
- _optionEnabled = -1;
- int optionsYCord = mousePos.y - (_optionsY + 16);
- if (optionsYCord >= 0) {
- int selectedOptionNr = optionsYCord / _optionsStep;
- if (selectedOptionNr < _optionsNumber) {
- _optionEnabled = selectedOptionNr;
- }
- }
- int optionsColor;
- int textY = _optionsY + 16;
- for (int i = 0; i < _optionsNumber; i++) {
- if (i != _optionEnabled) {
- optionsColor = _optionsColor1;
- } else {
- optionsColor = _optionsColor2;
- }
- Common::String optText;
- switch(getLanguage()) {
- case Common::PL_POL:
- optText = optionsTextPL[i];
- break;
- case Common::DE_DEU:
- optText = optionsTextDE[i];
- break;
- case Common::EN_ANY:
- optText = optionsTextEN[i];
- break;
- default:
- break;
- };
- uint16 textW = getTextWidth(optText.c_str());
- uint16 textX = _optionsX + _optionsWidth / 2 - textW / 2;
- _font->drawString(_graph->_frontScreen, optText, textX, textY, textW, optionsColor);
- textY += _optionsStep;
- }
- }
-}
-
-void PrinceEngine::checkInvOptions() {
- if (_optionsFlag) {
- Common::Rect optionsRect(_optionsX, _optionsY, _optionsX + _invOptionsWidth, _optionsY + _invOptionsHeight);
- Common::Point mousePos = _system->getEventManager()->getMousePos();
- if (!optionsRect.contains(mousePos)) {
- _optionsFlag = 0;
- _selectedMob = -1;
- return;
- }
- _graph->drawAsShadowSurface(_graph->_screenForInventory, _optionsX, _optionsY, _optionsPicInInventory, _graph->_shadowTable50);
-
- _optionEnabled = -1;
- int optionsYCord = mousePos.y - (_optionsY + 16);
- if (optionsYCord >= 0) {
- int selectedOptionNr = optionsYCord / _invOptionsStep;
- if (selectedOptionNr < _invOptionsNumber) {
- _optionEnabled = selectedOptionNr;
- }
- }
- int optionsColor;
- int textY = _optionsY + 16;
- for (int i = 0; i < _invOptionsNumber; i++) {
- if (i != _optionEnabled) {
- optionsColor = _optionsColor1;
- } else {
- optionsColor = _optionsColor2;
- }
- Common::String invText;
- switch(getLanguage()) {
- case Common::PL_POL:
- invText = invOptionsTextPL[i];
- break;
- case Common::DE_DEU:
- invText = invOptionsTextDE[i];
- break;
- case Common::EN_ANY:
- invText = invOptionsTextEN[i];
- break;
- default:
- error("Unknown game language %d", getLanguage());
- break;
- };
- uint16 textW = getTextWidth(invText.c_str());
- uint16 textX = _optionsX + _invOptionsWidth / 2 - textW / 2;
- _font->drawString(_graph->_screenForInventory, invText, textX, textY, _graph->_screenForInventory->w, optionsColor);
- textY += _invOptionsStep;
- }
- }
-}
-
-void PrinceEngine::displayInventory() {
-
- _mainHero->freeOldMove();
- _secondHero->freeOldMove();
-
- _interpreter->setFgOpcodePC(0);
-
- stopAllSamples();
-
- prepareInventoryToView();
-
- while (!shouldQuit()) {
-
- if (_textSlots[0]._str != nullptr) {
- changeCursor(0);
- } else {
- changeCursor(_currentPointerNumber);
-
- Common::Rect inventoryRect(_invX1, _invY1, _invX1 + _invWidth, _invY1 + _invHeight);
- Common::Point mousePos = _system->getEventManager()->getMousePos();
-
- if (!_invCurInside && inventoryRect.contains(mousePos)) {
- _invCurInside = true;
- }
-
- if (_invCurInside && !inventoryRect.contains(mousePos)) {
- inventoryFlagChange(false);
- _invCurInside = false;
- break;
- }
- }
-
- rememberScreenInv();
-
- Graphics::Surface *suitcase = _suitcaseBmp->getSurface();
- _graph->drawTransparentSurface(_graph->_screenForInventory, 0, 0, suitcase);
-
- drawInvItems();
-
- showTexts(_graph->_screenForInventory);
-
- if (!_optionsFlag && _textSlots[0]._str == nullptr) {
- _selectedMob = checkMob(_graph->_screenForInventory, _invMobList, false);
- }
-
- checkInvOptions();
-
- Common::Event event;
- Common::EventManager *eventMan = _system->getEventManager();
- while (eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- keyHandler(event);
- break;
- case Common::EVENT_LBUTTONDOWN:
- inventoryLeftMouseButton();
- break;
- case Common::EVENT_RBUTTONDOWN:
- inventoryRightMouseButton();
- break;
- default:
- break;
- }
- }
-
- if (!_showInventoryFlag) {
- break;
- }
-
- if (shouldQuit())
- return;
-
- getDebugger()->onFrame();
- _graph->update(_graph->_screenForInventory);
- pausePrinceEngine();
- }
-
- if (_currentPointerNumber == 2) {
- _flags->setFlagValue(Flags::SELITEM, _selectedItem);
- } else {
- _flags->setFlagValue(Flags::SELITEM, 0);
- }
-}
-
void PrinceEngine::createDialogBox(int dialogBoxNr) {
_dialogLines = 0;
int amountOfDialogOptions = 0;
@@ -3037,66 +977,6 @@ void PrinceEngine::talkHero(int slot) {
_interpreter->increaseString();
}
-void PrinceEngine::doTalkAnim(int animNumber, int slot, AnimType animType) {
- Text &text = _textSlots[slot];
- int lines = calcTextLines((const char *)_interpreter->getString());
- int time = lines * 30;
- if (animType == kNormalAnimation) {
- Anim &normAnim = _normAnimList[animNumber];
- if (normAnim._animData != nullptr) {
- if (!normAnim._state) {
- if (normAnim._currW && normAnim._currH) {
- text._color = _flags->getFlagValue(Flags::KOLOR);
- text._x = normAnim._currX + normAnim._currW / 2;
- text._y = normAnim._currY - 10;
- }
- }
- }
- } else if (animType == kBackgroundAnimation) {
- if (!_backAnimList[animNumber].backAnims.empty()) {
- int currAnim = _backAnimList[animNumber]._seq._currRelative;
- Anim &backAnim = _backAnimList[animNumber].backAnims[currAnim];
- if (backAnim._animData != nullptr) {
- if (!backAnim._state) {
- if (backAnim._currW && backAnim._currH) {
- text._color = _flags->getFlagValue(Flags::KOLOR);
- text._x = backAnim._currX + backAnim._currW / 2;
- text._y = backAnim._currY - 10;
- }
- }
- }
- }
- } else {
- error("doTalkAnim() - wrong animType: %d", animType);
- }
- text._time = time;
- if (getLanguage() == Common::DE_DEU) {
- correctStringDEU((char *)_interpreter->getString());
- }
- text._str = (const char *)_interpreter->getString();
- _interpreter->increaseString();
-}
-
-void PrinceEngine::freeNormAnim(int slot) {
- if (!_normAnimList.empty()) {
- _normAnimList[slot]._state = 1;
- if (_normAnimList[slot]._animData != nullptr) {
- delete _normAnimList[slot]._animData;
- _normAnimList[slot]._animData = nullptr;
- }
- if (_normAnimList[slot]._shadowData != nullptr) {
- delete _normAnimList[slot]._shadowData;
- _normAnimList[slot]._shadowData = nullptr;
- }
- }
-}
-
-void PrinceEngine::freeAllNormAnims() {
- for (int i = 0; i < kMaxNormAnims; i++) {
- freeNormAnim(i);
- }
-}
-
void PrinceEngine::getCurve() {
_flags->setFlagValue(Flags::TORX1, _curveData[_curvPos]);
_flags->setFlagValue(Flags::TORY1, _curveData[_curvPos + 1]);
@@ -3270,1544 +1150,6 @@ void PrinceEngine::scrollCredits() {
blackPalette();
}
-// Modified version of Graphics::drawLine() to allow breaking the loop and return value
-int PrinceEngine::drawLine(int x0, int y0, int x1, int y1, int (*plotProc)(int, int, void *), void *data) {
- // Bresenham's line algorithm, as described by Wikipedia
- const bool steep = ABS(y1 - y0) > ABS(x1 - x0);
-
- if (steep) {
- SWAP(x0, y0);
- SWAP(x1, y1);
- }
-
- const int delta_x = ABS(x1 - x0);
- const int delta_y = ABS(y1 - y0);
- const int delta_err = delta_y;
- int x = x0;
- int y = y0;
- int err = 0;
-
- const int x_step = (x0 < x1) ? 1 : -1;
- const int y_step = (y0 < y1) ? 1 : -1;
-
- int stopFlag = 0;
- if (steep)
- stopFlag = (*plotProc)(y, x, data);
- else
- stopFlag = (*plotProc)(x, y, data);
-
- while (x != x1 && !stopFlag) {
- x += x_step;
- err += delta_err;
- if (2 * err > delta_x) {
- y += y_step;
- err -= delta_x;
- }
- if (steep)
- stopFlag = (*plotProc)(y, x, data);
- else
- stopFlag = (*plotProc)(x, y, data);
- }
- return stopFlag;
-}
-
-int PrinceEngine::getPixelAddr(byte *pathBitmap, int x, int y) {
- int mask = 128 >> (x & 7);
- byte value = pathBitmap[x / 8 + y * 80];
- return (mask & value);
-}
-
-void PrinceEngine::findPoint(int x, int y) {
- _fpX = x;
- _fpY = y;
-
- if (getPixelAddr(_roomPathBitmap, x, y)) {
- return;
- }
-
- int fpL = x;
- int fpU = y;
- int fpR = x;
- int fpD = y;
-
- while (1) {
- if (fpD != kMaxPicHeight) {
- if (getPixelAddr(_roomPathBitmap, x, fpD)) {
- _fpX = x;
- _fpY = fpD;
- break;
- }
- fpD++;
- }
- if (fpU) {
- if (getPixelAddr(_roomPathBitmap, x, fpU)) {
- _fpX = x;
- _fpY = fpU;
- break;
- }
- fpU--;
- }
- if (fpL) {
- if (getPixelAddr(_roomPathBitmap, fpL, y)) {
- _fpX = fpL;
- _fpY = y;
- break;
- }
- fpL--;
- }
- if (fpR != _sceneWidth) {
- if (getPixelAddr(_roomPathBitmap, fpR, y)) {
- _fpX = fpR;
- _fpY = y;
- break;
- }
- fpR++;
- }
- if (!fpU && (fpD == kMaxPicHeight)) {
- if (!fpL && (fpR == _sceneWidth)) {
- break;
- }
- }
- }
-}
-
-Direction PrinceEngine::makeDirection(int x1, int y1, int x2, int y2) {
- if (x1 != x2) {
- if (y1 != y2) {
- if (x1 > x2) {
- if (y1 > y2) {
- if (x1 - x2 >= y1 - y2) {
- return kDirLU;
- } else {
- return kDirUL;
- }
- } else {
- if (x1 - x2 >= y2 - y1) {
- return kDirLD;
- } else {
- return kDirDL;
- }
- }
- } else {
- if (y1 > y2) {
- if (x2 - x1 >= y1 - y2) {
- return kDirRU;
- } else {
- return kDirUR;
- }
- } else {
- if (x2 - x1 >= y2 - y1) {
- return kDirRD;
- } else {
- return kDirDR;
- }
- }
- }
- } else {
- if (x1 >= x2) {
- return kDirL;
- } else {
- return kDirR;
- }
- }
- } else {
- if (y1 >= y2) {
- return kDirU;
- } else {
- return kDirD;
- }
- }
-}
-
-void PrinceEngine::specialPlot(int x, int y) {
- if (_coords < _coordsBufEnd) {
- WRITE_LE_UINT16(_coords, x);
- _coords += 2;
- WRITE_LE_UINT16(_coords, y);
- _coords += 2;
- specialPlot2(x, y);
- }
-}
-
-void PrinceEngine::specialPlot2(int x, int y) {
- int mask = 128 >> (x & 7);
- _roomPathBitmapTemp[x / 8 + y * 80] |= mask;
-}
-
-void PrinceEngine::specialPlotInside(int x, int y) {
- if (_coords < _coordsBufEnd) {
- WRITE_LE_UINT16(_coords, x);
- _coords += 2;
- WRITE_LE_UINT16(_coords, y);
- _coords += 2;
- }
-}
-
-int PrinceEngine::plotTraceLine(int x, int y, void *data) {
- PrinceEngine *traceLine = (PrinceEngine *)data;
- if (!traceLine->_traceLineFirstPointFlag) {
- if (!traceLine->getPixelAddr(traceLine->_roomPathBitmapTemp, x, y)) {
- if (traceLine->getPixelAddr(traceLine->_roomPathBitmap, x, y)) {
- traceLine->specialPlotInside(x, y);
- traceLine->_traceLineLen++;
- return 0;
- } else {
- return -1;
- }
- } else {
- return 1;
- }
- } else {
- traceLine->_traceLineFirstPointFlag = false;
- return 0;
- }
-}
-
-int PrinceEngine::leftDownDir() {
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::leftDir() {
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::leftUpDir() {
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::rightDownDir() {
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::rightDir() {
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::rightUpDir() {
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::upLeftDir() {
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::upDir() {
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::upRightDir() {
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::downLeftDir() {
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::downDir() {
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::downRightDir() {
- if (!checkRightDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDownDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkRightUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- if (!checkLeftUpDir()) {
- specialPlot(_checkX, _checkY);
- return 0;
- }
- return -1;
-}
-
-int PrinceEngine::cpe() {
- if ((*(_checkBitmap - kPBW) & _checkMask)) {
- if ((*(_checkBitmap + kPBW) & _checkMask)) {
- int value;
- switch (_checkMask) {
- case 128:
- value = READ_LE_UINT16(_checkBitmap - 1);
- value &= 0x4001;
- if (value != 0x4001) {
- return 0;
- }
- break;
- case 64:
- value = *_checkBitmap;
- value &= 0xA0;
- if (value != 0xA0) {
- return 0;
- }
- break;
- case 32:
- value = *_checkBitmap;
- value &= 0x50;
- if (value != 0x50) {
- return 0;
- }
- break;
- case 16:
- value = *_checkBitmap;
- value &= 0x28;
- if (value != 0x28) {
- return 0;
- }
- break;
- case 8:
- value = *_checkBitmap;
- value &= 0x14;
- if (value != 0x14) {
- return 0;
- }
- break;
- case 4:
- value = *_checkBitmap;
- value &= 0xA;
- if (value != 0xA) {
- return 0;
- }
- break;
- case 2:
- value = *_checkBitmap;
- value &= 0x5;
- if (value != 0x5) {
- return 0;
- }
- break;
- case 1:
- value = READ_LE_UINT16(_checkBitmap);
- value &= 0x8002;
- if (value != 0x8002) {
- return 0;
- }
- break;
- default:
- error("Wrong _checkMask value - cpe()");
- break;
- }
- _checkX = _rembX;
- _checkY = _rembY;
- _checkBitmapTemp = _rembBitmapTemp;
- _checkBitmap = _rembBitmap;
- _checkMask = _rembMask;
- return -1;
- }
- return 0;
- }
- return 0;
-}
-
-int PrinceEngine::checkLeftDownDir() {
- if (_checkX && _checkY != (kMaxPicHeight / 2 - 1)) {
- int tempMask = _checkMask;
- if (tempMask != 128) {
- tempMask <<= 1;
- if ((*(_checkBitmap + kPBW) & tempMask)) {
- if (!(*(_checkBitmapTemp + kPBW) & tempMask)) {
- _checkBitmap += kPBW;
- _checkBitmapTemp += kPBW;
- _checkMask = tempMask;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- } else {
- if ((*(_checkBitmap + kPBW - 1) & 1)) {
- if (!(*(_checkBitmapTemp + kPBW - 1) & 1)) {
- _checkBitmap += (kPBW - 1);
- _checkBitmapTemp += (kPBW - 1);
- _checkMask = 1;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- }
- _checkX--;
- _checkY++;
- return cpe();
- } else {
- return -1;
- }
-}
-
-int PrinceEngine::checkLeftDir() {
- if (_checkX) {
- int tempMask = _checkMask;
- if (tempMask != 128) {
- tempMask <<= 1;
- if ((*(_checkBitmap) & tempMask)) {
- if (!(*(_checkBitmapTemp) & tempMask)) {
- _checkMask = tempMask;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- } else {
- if ((*(_checkBitmap - 1) & 1)) {
- if (!(*(_checkBitmapTemp - 1) & 1)) {
- _checkBitmap--;
- _checkBitmapTemp--;
- _checkMask = 1;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- }
- _checkX--;
- return cpe();
- } else {
- return -1;
- }
-}
-
-int PrinceEngine::checkDownDir() {
- if (_checkY != (kMaxPicHeight / 2 - 1)) {
- if ((*(_checkBitmap + kPBW) & _checkMask)) {
- if (!(*(_checkBitmapTemp + kPBW) & _checkMask)) {
- _checkBitmap += kPBW;
- _checkBitmapTemp += kPBW;
- _checkY++;
- return cpe();
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-}
-
-int PrinceEngine::checkUpDir() {
- if (_checkY) {
- if ((*(_checkBitmap - kPBW) & _checkMask)) {
- if (!(*(_checkBitmapTemp - kPBW) & _checkMask)) {
- _checkBitmap -= kPBW;
- _checkBitmapTemp -= kPBW;
- _checkY--;
- return cpe();
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- } else {
- return -1;
- }
-}
-
-int PrinceEngine::checkRightDir() {
- if (_checkX != (kMaxPicWidth / 2 - 1)) {
- int tempMask = _checkMask;
- if (tempMask != 1) {
- tempMask >>= 1;
- if ((*(_checkBitmap) & tempMask)) {
- if (!(*(_checkBitmapTemp) & tempMask)) {
- _checkMask = tempMask;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- } else {
- if ((*(_checkBitmap + 1) & 128)) {
- if (!(*(_checkBitmapTemp + 1) & 128)) {
- _checkBitmap++;
- _checkBitmapTemp++;
- _checkMask = 128;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- }
- _checkX++;
- return cpe();
- } else {
- return -1;
- }
-}
-
-int PrinceEngine::checkLeftUpDir() {
- if (_checkX && _checkY) {
- int tempMask = _checkMask;
- if (tempMask != 128) {
- tempMask <<= 1;
- if ((*(_checkBitmap - kPBW) & tempMask)) {
- if (!(*(_checkBitmapTemp - kPBW) & tempMask)) {
- _checkBitmap -= kPBW;
- _checkBitmapTemp -= kPBW;
- _checkMask = tempMask;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- } else {
- if ((*(_checkBitmap - (kPBW + 1)) & 1)) {
- if (!(*(_checkBitmapTemp - (kPBW + 1)) & 1)) {
- _checkBitmap -= (kPBW + 1);
- _checkBitmapTemp -= (kPBW + 1);
- _checkMask = 1;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- }
- _checkX--;
- _checkY--;
- return cpe();
- } else {
- return -1;
- }
-}
-
-int PrinceEngine::checkRightDownDir() {
- if (_checkX != (kMaxPicWidth / 2 - 1) && _checkY != (kMaxPicHeight / 2 - 1)) {
- int tempMask = _checkMask;
- if (tempMask != 1) {
- tempMask >>= 1;
- if ((*(_checkBitmap + kPBW) & tempMask)) {
- if (!(*(_checkBitmapTemp + kPBW) & tempMask)) {
- _checkBitmap += kPBW;
- _checkBitmapTemp += kPBW;
- _checkMask = tempMask;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- } else {
- if ((*(_checkBitmap + kPBW + 1) & 128)) {
- if (!(*(_checkBitmapTemp + kPBW + 1) & 128)) {
- _checkBitmap += kPBW + 1;
- _checkBitmapTemp += kPBW + 1;
- _checkMask = 128;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- }
- _checkX++;
- _checkY++;
- return cpe();
- } else {
- return -1;
- }
-}
-
-int PrinceEngine::checkRightUpDir() {
- if (_checkX != (kMaxPicWidth / 2 - 1) && _checkY) {
- int tempMask = _checkMask;
- if (tempMask != 1) {
- tempMask >>= 1;
- if ((*(_checkBitmap - kPBW) & tempMask)) {
- if (!(*(_checkBitmapTemp - kPBW) & tempMask)) {
- _checkBitmap -= kPBW;
- _checkBitmapTemp -= kPBW;
- _checkMask = tempMask;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- } else {
- if ((*(_checkBitmap - kPBW + 1) & 128)) {
- if (!(*(_checkBitmapTemp - kPBW + 1) & 128)) {
- _checkBitmap -= (kPBW - 1);
- _checkBitmapTemp -= (kPBW - 1);
- _checkMask = 128;
- } else {
- return 1;
- }
- } else {
- return -1;
- }
- }
- _checkX++;
- _checkY--;
- return cpe();
- } else {
- return -1;
- }
-}
-
-bool PrinceEngine::tracePath(int x1, int y1, int x2, int y2) {
- for (uint i = 0; i < kPathBitmapLen; i++) {
- _roomPathBitmapTemp[i] = 0;
- }
- if (x1 != x2 || y1 != y2) {
- if (getPixelAddr(_roomPathBitmap, x1, y1)) {
- if (getPixelAddr(_roomPathBitmap, x2, y2)) {
- _coords = _coordsBuf;
- specialPlot(x1, y1);
-
- int x = x1;
- int y = y1;
-
- while (1) {
- int btx = x;
- int bty = y;
- byte *bcad = _coords;
-
- _traceLineLen = 0;
- _traceLineFirstPointFlag = true;
- int drawLineFlag = drawLine(x, y, x2, y2, &this->plotTraceLine, this);
-
- if (!drawLineFlag) {
- return true;
- } else if (drawLineFlag == -1 && _traceLineLen >= 2) {
- byte *tempCorrds = bcad;
- while (tempCorrds != _coords) {
- x = READ_LE_UINT16(tempCorrds);
- y = READ_LE_UINT16(tempCorrds + 2);
- tempCorrds += 4;
- specialPlot2(x, y);
- }
- } else {
- _coords = bcad;
- x = btx;
- y = bty;
- }
-
- Direction dir = makeDirection(x, y, x2, y2);
-
- _rembBitmapTemp = &_roomPathBitmapTemp[x / 8 + y * 80];
- _rembBitmap = &_roomPathBitmap[x / 8 + y * 80];
- _rembMask = 128 >> (x & 7);
- _rembX = x;
- _rembY = y;
-
- _checkBitmapTemp = _rembBitmapTemp;
- _checkBitmap = _rembBitmap;
- _checkMask = _rembMask;
- _checkX = _rembX;
- _checkY = _rembY;
-
- int result;
- switch (dir) {
- case kDirLD:
- result = leftDownDir();
- break;
- case kDirL:
- result = leftDir();
- break;
- case kDirLU:
- result = leftUpDir();
- break;
- case kDirRD:
- result = rightDownDir();
- break;
- case kDirR:
- result = rightDir();
- break;
- case kDirRU:
- result = rightUpDir();
- break;
- case kDirUL:
- result = upLeftDir();
- break;
- case kDirU:
- result = upDir();
- break;
- case kDirUR:
- result = upRightDir();
- break;
- case kDirDL:
- result = downLeftDir();
- break;
- case kDirD:
- result = downDir();
- break;
- case kDirDR:
- result = downRightDir();
- break;
- default:
- result = -1;
- error("tracePath: wrong direction %d", dir);
- break;
- }
-
- if (result) {
- byte *tempCoords = _coords;
- tempCoords -= 4;
- if (tempCoords > _coordsBuf) {
- int tempX = READ_LE_UINT16(tempCoords);
- int tempY = READ_LE_UINT16(tempCoords + 2);
- if (_checkX == tempX && _checkY == tempY) {
- _coords = tempCoords;
- }
- x = READ_LE_UINT16(tempCoords);
- y = READ_LE_UINT16(tempCoords + 2);
- } else {
- return false;
- }
- } else {
- x = _checkX;
- y = _checkY;
- }
- }
- return true;
- } else {
- error("tracePath: wrong destination point");
- }
- } else {
- error("tracePath: wrong start point");
- }
- } else {
- error("tracePath: same point");
- }
-}
-
-void PrinceEngine::specialPlotInside2(int x, int y) {
- WRITE_LE_UINT16(_coords2, x);
- _coords2 += 2;
- WRITE_LE_UINT16(_coords2, y);
- _coords2 += 2;
-}
-
-int PrinceEngine::plotTracePoint(int x, int y, void *data) {
- PrinceEngine *tracePoint = (PrinceEngine *)data;
- if (!tracePoint->_tracePointFirstPointFlag) {
- if (tracePoint->getPixelAddr(tracePoint->_roomPathBitmap, x, y)) {
- tracePoint->specialPlotInside2(x, y);
- return 0;
- } else {
- return -1;
- }
- } else {
- tracePoint->_tracePointFirstPointFlag = false;
- return 0;
- }
-}
-
-void PrinceEngine::approxPath() {
- byte *oldCoords;
- _coords2 = _coordsBuf2;
- byte *tempCoordsBuf = _coordsBuf; // first point on path
- byte *tempCoords = _coords;
- if (tempCoordsBuf != tempCoords) {
- tempCoords -= 4; // last point on path
- while (tempCoordsBuf != tempCoords) {
- int x1 = READ_LE_UINT16(tempCoords);
- int y1 = READ_LE_UINT16(tempCoords + 2);
- int x2 = READ_LE_UINT16(tempCoordsBuf);
- int y2 = READ_LE_UINT16(tempCoordsBuf + 2);
- tempCoordsBuf += 4;
- //TracePoint
- oldCoords = _coords2;
- if (_coords2 == _coordsBuf2) {
- WRITE_LE_UINT16(_coords2, x1);
- WRITE_LE_UINT16(_coords2 + 2, y1);
- _coords2 += 4;
- } else {
- int testX = READ_LE_UINT16(_coords2 - 4);
- int testY = READ_LE_UINT16(_coords2 - 2);
- if (testX != x1 || testY != y1) {
- WRITE_LE_UINT16(_coords2, x1);
- WRITE_LE_UINT16(_coords2 + 2, y1);
- _coords2 += 4;
- }
- }
- _tracePointFirstPointFlag = true;
- bool drawLineFlag = drawLine(x1, y1, x2, y2, &this->plotTracePoint, this);
- if (!drawLineFlag) {
- tempCoords = tempCoordsBuf - 4;
- tempCoordsBuf = _coordsBuf;
- } else {
- _coords2 = oldCoords;
- }
- }
- }
-}
-
-void PrinceEngine::freeDirectionTable() {
- if (_directionTable != nullptr) {
- free(_directionTable);
- _directionTable = nullptr;
- }
-}
-
-int PrinceEngine::scanDirectionsFindNext(byte *tempCoordsBuf, int xDiff, int yDiff) {
-
- int tempX, tempY, direction;
-
- tempX = Hero::kHeroDirLeft;
- if (xDiff < 0) {
- tempX = Hero::kHeroDirRight;
- }
-
- tempY = Hero::kHeroDirUp;
- if (yDiff < 0) {
- tempY = Hero::kHeroDirDown;
- }
-
- while (1) {
- int againPointX1 = READ_LE_UINT16(tempCoordsBuf);
- int againPointY1 = READ_LE_UINT16(tempCoordsBuf + 2);
- tempCoordsBuf += 4;
-
- if (tempCoordsBuf == _coords) {
- direction = tempX;
- break;
- }
-
- int dX = againPointX1 - READ_LE_UINT16(tempCoordsBuf);
- int dY = againPointY1 - READ_LE_UINT16(tempCoordsBuf + 2);
-
- if (dX != xDiff) {
- direction = tempY;
- break;
- }
-
- if (dY != yDiff) {
- direction = tempX;
- break;
- }
- }
- return direction;
-}
-
-void PrinceEngine::scanDirections() {
- freeDirectionTable();
- byte *tempCoordsBuf = _coordsBuf;
- if (tempCoordsBuf != _coords) {
- int size = (_coords - tempCoordsBuf) / 4 + 1; // number of coord points plus one for end marker
- _directionTable = (byte *)malloc(size);
- byte *tempDirTab = _directionTable;
- int direction = -1;
- int lastDirection = -1;
-
- while (1) {
- int x1 = READ_LE_UINT16(tempCoordsBuf);
- int y1 = READ_LE_UINT16(tempCoordsBuf + 2);
- tempCoordsBuf += 4;
- if (tempCoordsBuf == _coords) {
- break;
- }
- int x2 = READ_LE_UINT16(tempCoordsBuf);
- int y2 = READ_LE_UINT16(tempCoordsBuf + 2);
-
- int xDiff = x1 - x2;
- int yDiff = y1 - y2;
-
- if (xDiff) {
- if (yDiff) {
- if (lastDirection != -1) {
- direction = lastDirection;
- if (direction == Hero::kHeroDirLeft) {
- if (xDiff < 0) {
- direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
- }
- } else if (direction == Hero::kHeroDirRight) {
- if (xDiff >= 0) {
- direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
- }
- } else if (direction == Hero::kHeroDirUp) {
- if (yDiff < 0) {
- direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
- }
- } else {
- if (yDiff >= 0) {
- direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
- }
- }
- } else {
- direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
- }
- } else {
- direction = Hero::kHeroDirLeft;
- if (xDiff < 0) {
- direction = Hero::kHeroDirRight;
- }
- }
- } else {
- if (yDiff) {
- direction = Hero::kHeroDirUp;
- if (yDiff < 0) {
- direction = Hero::kHeroDirDown;
- }
- } else {
- direction = lastDirection;
- }
- }
- lastDirection = direction;
- *tempDirTab = direction;
- tempDirTab++;
- }
- *tempDirTab = *(tempDirTab - 1);
- tempDirTab++;
- *tempDirTab = 0;
- }
-}
-
-void PrinceEngine::moveShandria() {
- int shanLen1 = _shanLen;
- if (_flags->getFlagValue(Flags::SHANDOG)) {
- _secondHero->freeHeroAnim();
- _secondHero->freeOldMove();
- byte *shanCoords = _mainHero->_currCoords + shanLen1 * 4 - 4;
- int shanX = READ_LE_UINT16(shanCoords - 4);
- int shanY = READ_LE_UINT16(shanCoords - 2);
- int xDiff = shanX - _secondHero->_middleX;
- if (xDiff < 0) {
- xDiff *= -1;
- }
- int yDiff = shanY - _secondHero->_middleY;
- if (yDiff < 0) {
- yDiff *= -1;
- }
- shanCoords -= 4;
- if (shanCoords != _mainHero->_currCoords) {
- yDiff *= 1.5;
- int shanDis = xDiff * xDiff + yDiff * yDiff;
- if (shanDis >= kMinDistance) {
- while (1) {
- shanCoords -= 4;
- if (shanCoords == _mainHero->_currCoords) {
- break;
- }
- int x = READ_LE_UINT16(shanCoords);
- int y = READ_LE_UINT16(shanCoords + 2);
- int pointDiffX = x - shanX;
- if (pointDiffX < 0) {
- pointDiffX *= -1;
- }
- int pointDiffY = y - shanY;
- if (pointDiffY < 0) {
- pointDiffY *= -1;
- }
- pointDiffY *= 1.5;
- int distance = pointDiffX * pointDiffX + pointDiffY * pointDiffY;
- if (distance >= kMinDistance) {
- break;
- }
- }
- int pathSizeDiff = (shanCoords - _mainHero->_currCoords) / 4;
- int destDir = *(_mainHero->_currDirTab + pathSizeDiff);
- _secondHero->_destDirection = destDir;
- int destX = READ_LE_UINT16(shanCoords);
- int destY = READ_LE_UINT16(shanCoords + 2);
- _secondHero->_coords = makePath(kSecondHero, _secondHero->_middleX, _secondHero->_middleY, destX, destY);
- if (_secondHero->_coords != nullptr) {
- _secondHero->_currCoords = _secondHero->_coords;
- int delay = shanLen1 - _shanLen;
- if (delay < 6) {
- delay = 6;
- }
- _secondHero->_moveDelay = delay / 2;
- _secondHero->_state = Hero::kHeroStateDelayMove;
- _secondHero->_dirTab = _directionTable;
- _secondHero->_currDirTab = _directionTable;
- _directionTable = nullptr;
- }
- }
- }
- }
-}
-
-byte *PrinceEngine::makePath(int heroId, int currX, int currY, int destX, int destY) {
- int realDestX = destX;
- int realDestY = destY;
- _flags->setFlagValue(Flags::MOVEDESTX, destX);
- _flags->setFlagValue(Flags::MOVEDESTY, destY);
-
- int x1 = currX / 2;
- int y1 = currY / 2;
- int x2 = destX / 2;
- int y2 = destY / 2;
-
- if ((x1 != x2) || (y1 != y2)) {
- findPoint(x1, y1);
- if (!getPixelAddr(_roomPathBitmap, _fpX, _fpY)) {
- return nullptr;
- }
- if ((x1 != _fpX) || (y1 != _fpY)) {
- x1 = _fpX;
- y1 = _fpY;
- }
- findPoint(x2, y2);
- if (!getPixelAddr(_roomPathBitmap, _fpX, _fpY)) {
- return nullptr;
- }
- if ((x2 != _fpX) || (y2 != _fpY)) {
- x2 = _fpX;
- y2 = _fpY;
- if (!_flags->getFlagValue(Flags::EXACTMOVE)) {
- realDestX = x2 * 2;
- realDestY = y2 * 2;
- _flags->setFlagValue(Flags::MOVEDESTX, realDestX);
- _flags->setFlagValue(Flags::MOVEDESTY, realDestY);
- } else {
- return nullptr;
- }
- }
-
- if ((x1 == x2) && (y1 == y2)) {
- if (!heroId) {
- _mainHero->freeOldMove();
- _mainHero->_state = Hero::kHeroStateTurn;
- } else if (heroId == 1) {
- _secondHero->freeOldMove();
- _secondHero->_state = Hero::kHeroStateTurn;
- }
- return nullptr;
- }
-
- int pathLen1 = 0;
- int pathLen2 = 0;
- int stX = x1;
- int stY = y1;
- int sizeCoords2 = 0;
-
- if (tracePath(x1, y1, x2, y2)) {
- allocCoords2();
- approxPath();
- sizeCoords2 = _coords2 - _coordsBuf2;
- for (int i = 0; i < sizeCoords2; i++) {
- _coordsBuf[i] = _coordsBuf2[i];
- }
- _coords = _coordsBuf + sizeCoords2;
- approxPath();
- _coordsBuf3 = _coordsBuf2;
- _coordsBuf2 = nullptr;
- _coords3 = _coords2;
- _coords2 = nullptr;
- pathLen1 = _coords3 - _coordsBuf3;
- }
- if (tracePath(x2, y2, x1, y1)) {
- allocCoords2();
- approxPath();
- sizeCoords2 = _coords2 - _coordsBuf2;
- for (int i = 0; i < sizeCoords2; i++) {
- _coordsBuf[i] = _coordsBuf2[i];
- }
- _coords = _coordsBuf + sizeCoords2;
- approxPath();
- pathLen2 = _coords2 - _coordsBuf2;
- }
-
- byte *chosenCoordsBuf = _coordsBuf2;
- byte *choosenCoords = _coords2;
- int choosenLength = pathLen1;
- if (pathLen1 < pathLen2) {
- chosenCoordsBuf = _coordsBuf3;
- choosenCoords = _coords3;
- choosenLength = pathLen2;
- }
-
- if (choosenLength) {
- if (chosenCoordsBuf != nullptr) {
- int tempXBegin = READ_LE_UINT16(chosenCoordsBuf);
- int tempYBegin = READ_LE_UINT16(chosenCoordsBuf + 2);
- if (stX != tempXBegin || stY != tempYBegin) {
- SWAP(chosenCoordsBuf, choosenCoords);
- chosenCoordsBuf -= 4;
- byte *tempCoordsBuf = _coordsBuf;
- while (1) {
- int cord = READ_LE_UINT32(chosenCoordsBuf);
- WRITE_LE_UINT32(tempCoordsBuf, cord);
- tempCoordsBuf += 4;
- if (chosenCoordsBuf == choosenCoords) {
- break;
- }
- chosenCoordsBuf -= 4;
- }
- _coords = tempCoordsBuf;
- } else {
- int sizeChoosen = choosenCoords - chosenCoordsBuf;
- for (int i = 0; i < sizeChoosen; i++) {
- _coordsBuf[i] = chosenCoordsBuf[i];
- }
- _coords = _coordsBuf + sizeChoosen;
- }
- WRITE_LE_UINT32(_coords, 0xFFFFFFFF);
- freeCoords2();
- freeCoords3();
- scanDirections();
-
- byte *tempCoordsBuf = _coordsBuf;
- byte *tempCoords = _coords;
- byte *newCoords;
- if (tempCoordsBuf != tempCoords) {
- int normCoordsSize = _coords - _coordsBuf + 4;
- newCoords = (byte *)malloc(normCoordsSize);
- byte *newCoordsBegin = newCoords;
- while (tempCoordsBuf != tempCoords) {
- int newValueX = READ_LE_UINT16(tempCoordsBuf);
- WRITE_LE_UINT16(newCoords, newValueX * 2);
- newCoords += 2;
- int newValueY = READ_LE_UINT16(tempCoordsBuf + 2);
- WRITE_LE_UINT16(newCoords, newValueY * 2);
- newCoords += 2;
- tempCoordsBuf += 4;
- }
- WRITE_LE_UINT16(newCoords - 4, realDestX);
- WRITE_LE_UINT16(newCoords - 2, realDestY);
- WRITE_LE_UINT32(newCoords, 0xFFFFFFFF);
- newCoords += 4;
- _shanLen = (newCoords - newCoordsBegin);
- _shanLen /= 4;
- return newCoordsBegin;
- }
- }
- }
- _coords = _coordsBuf;
- freeCoords2();
- freeCoords3();
- return nullptr;
- } else {
- if (!heroId) {
- _mainHero->freeOldMove();
- _mainHero->_state = Hero::kHeroStateTurn;
- } else if (heroId == 1) {
- _secondHero->freeOldMove();
- _secondHero->_state = Hero::kHeroStateTurn;
- }
- return nullptr;
- }
-}
-
-void PrinceEngine::allocCoords2() {
- if (_coordsBuf2 == nullptr) {
- _coordsBuf2 = (byte *)malloc(kTracePts * 4);
- _coords2 = _coordsBuf2;
- }
-}
-
-void PrinceEngine::freeCoords2() {
- if (_coordsBuf2 != nullptr) {
- free(_coordsBuf2);
- _coordsBuf2 = nullptr;
- _coords2 = nullptr;
- }
-}
-
-void PrinceEngine::freeCoords3() {
- if (_coordsBuf3 != nullptr) {
- free(_coordsBuf3);
- _coordsBuf3 = nullptr;
- _coords3 = nullptr;
- }
-}
-
-void PrinceEngine::openInventoryCheck() {
- if (!_optionsFlag) {
- if (_mouseFlag == 1 || _mouseFlag == 2) {
- if (_mainHero->_visible) {
- if (!_flags->getFlagValue(Flags::INVALLOWED)) {
- // 29 - Basement, 50 - Map
- if (_locationNr != 29 && _locationNr != 50) {
- Common::Point mousePos = _system->getEventManager()->getMousePos();
- if (mousePos.y < 4 && !_showInventoryFlag) {
- _invCounter++;
- } else {
- _invCounter = 0;
- }
- if (_invCounter >= _invMaxCount) {
- inventoryFlagChange(true);
- }
- }
- }
- }
- }
- }
-}
-
void PrinceEngine::mainLoop() {
changeCursor(0);
_currentTime = _system->getMillis();
diff --git a/engines/prince/prince.h b/engines/prince/prince.h
index 32e37e0774..e0b9490c37 100644
--- a/engines/prince/prince.h
+++ b/engines/prince/prince.h
@@ -38,7 +38,6 @@
#include "gui/debugger.h"
-#include "engines/advancedDetector.h"
#include "engines/engine.h"
#include "engines/util.h"
@@ -58,14 +57,10 @@ enum PrinceGameType {
kPrinceDataPL
};
-struct PrinceGameDescription {
- ADGameDescription desc;
- PrinceGameType gameType;
-};
-
struct SavegameHeader;
class PrinceEngine;
+struct PrinceGameDescription;
class GraphicsMan;
class Script;
class Interpreter;
@@ -82,15 +77,18 @@ class Room;
class Pscr;
enum {
- GF_TRANSLATED = 1 << 0
+ GF_TRANSLATED = 1 << 0,
+ GF_EXTRACTED = 1 << 1,
+ GF_NOVOICES = 1 << 2
};
struct SavegameHeader {
uint8 version;
Common::String saveName;
Graphics::Surface *thumbnail;
- int saveYear, saveMonth, saveDay;
- int saveHour, saveMinutes;
+ int16 saveYear, saveMonth, saveDay;
+ int16 saveHour, saveMinutes;
+ uint32 playTime;
};
#define kSavegameStrSize 14
@@ -281,6 +279,8 @@ public:
PrinceEngine(OSystem *syst, const PrinceGameDescription *gameDesc);
virtual ~PrinceEngine();
+ bool scummVMSaveLoadDialog(bool isSave);
+
virtual bool hasFeature(EngineFeature f) const;
virtual void pauseEngineIntern(bool pause);
virtual bool canSaveGameStateCurrently();
@@ -290,7 +290,7 @@ public:
void playVideo(Common::String videoFilename);
- static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail = true);
Common::String generateSaveName(int slot);
void writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header);
void syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream);
diff --git a/engines/prince/pscr.cpp b/engines/prince/pscr.cpp
index 4f79704e62..481d17cace 100644
--- a/engines/prince/pscr.cpp
+++ b/engines/prince/pscr.cpp
@@ -24,6 +24,7 @@
#include "common/stream.h"
#include "prince/pscr.h"
+#include "prince/resource.h"
namespace Prince {
@@ -64,6 +65,8 @@ bool PScr::loadFromStream(Common::SeekableReadStream &stream) {
const Common::String pscrStreamName = Common::String::format("PS%02d", file);
Common::SeekableReadStream *pscrStream = SearchMan.createReadStreamForMember(pscrStreamName);
if (pscrStream != nullptr) {
+ pscrStream = Resource::getDecompressedStream(pscrStream);
+
loadSurface(*pscrStream);
}
delete pscrStream;
diff --git a/engines/prince/resource.cpp b/engines/prince/resource.cpp
new file mode 100644
index 0000000000..34de29b388
--- /dev/null
+++ b/engines/prince/resource.cpp
@@ -0,0 +1,371 @@
+/* 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/fs.h"
+#include "common/config-manager.h"
+
+#include "prince/prince.h"
+#include "prince/graphics.h"
+#include "prince/debugger.h"
+#include "prince/script.h"
+#include "prince/hero.h"
+#include "prince/resource.h"
+#include "prince/archive.h"
+
+namespace Prince {
+
+Common::SeekableReadStream *Resource::getDecompressedStream(Common::SeekableReadStream *stream) {
+ if (!(((PrinceEngine *)g_engine)->getFeatures() & GF_EXTRACTED))
+ return stream;
+
+ byte header[4];
+
+ stream->read(header, 4);
+ stream->seek(0);
+
+ if (READ_BE_UINT32(header) == MKTAG('M', 'A', 'S', 'M')) {
+ byte *buffer = (byte *)malloc(stream->size());
+ stream->read(buffer, stream->size());
+
+ Decompressor dec;
+ uint32 decompLen = READ_BE_UINT32(buffer + 14);
+ byte *decompData = (byte *)malloc(decompLen);
+ dec.decompress(buffer + 18, decompData, decompLen);
+ free(buffer);
+
+ debug(8, "Resource::getDecompressedStream: decompressed %d to %d bytes", stream->size(), decompLen);
+
+ return new Common::MemoryReadStream(decompData, decompLen, DisposeAfterUse::YES);
+ } else {
+ return stream;
+ }
+}
+
+bool AnimListItem::loadFromStream(Common::SeekableReadStream &stream) {
+ int32 pos = stream.pos();
+
+ uint16 type = stream.readUint16LE();
+ if (type == 0xFFFF) {
+ return false;
+ }
+ _type = type;
+ _fileNumber = stream.readUint16LE();
+ _startPhase = stream.readUint16LE();
+ _endPhase = stream.readUint16LE();
+ _loopPhase = stream.readUint16LE();
+ _x = stream.readSint16LE();
+ _y = stream.readSint16LE();
+ _loopType = stream.readUint16LE();
+ _nextAnim = stream.readUint16LE();
+ _flags = stream.readUint16LE();
+
+ debug(7, "AnimListItem type %d, fileNumber %d, x %d, y %d, flags %d", _type, _fileNumber, _x, _y, _flags);
+ debug(7, "startPhase %d, endPhase %d, loopPhase %d", _startPhase, _endPhase, _loopPhase);
+
+ // 32 byte aligment
+ stream.seek(pos + 32);
+
+ return true;
+}
+
+bool PrinceEngine::loadLocation(uint16 locationNr) {
+
+ blackPalette();
+
+ _flicPlayer.close();
+
+ memset(_textSlots, 0, sizeof(_textSlots));
+ freeAllSamples();
+
+ debugEngine("PrinceEngine::loadLocation %d", locationNr);
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+ SearchMan.remove(Common::String::format("%02d", _locationNr));
+
+ _locationNr = locationNr;
+ _debugger->_locationNr = locationNr;
+
+ _flags->setFlagValue(Flags::CURRROOM, _locationNr);
+ _interpreter->stopBg();
+
+ changeCursor(0);
+
+ const Common::String locationNrStr = Common::String::format("%02d", _locationNr);
+ debugEngine("loadLocation %s", locationNrStr.c_str());
+
+ if (!(getFeatures() & GF_EXTRACTED)) {
+ PtcArchive *locationArchive = new PtcArchive();
+ if (!locationArchive->open(locationNrStr + "/databank.ptc"))
+ error("Can't open location %s", locationNrStr.c_str());
+
+ SearchMan.add(locationNrStr, locationArchive);
+ } else {
+ SearchMan.addSubDirectoryMatching(gameDataDir, locationNrStr);
+ }
+
+ loadMusic(_locationNr);
+
+ // load location background, replace old one
+ Resource::loadResource(_roomBmp, "room", true);
+ if (_roomBmp->getSurface()) {
+ _sceneWidth = _roomBmp->getSurface()->w;
+ }
+
+ loadZoom(_zoomBitmap, kZoomBitmapLen, "zoom");
+ loadShadow(_shadowBitmap, kShadowBitmapSize, "shadow", "shadow2");
+ loadTrans(_transTable, "trans");
+ loadPath("path");
+
+ for (uint32 i = 0; i < _pscrList.size(); i++) {
+ delete _pscrList[i];
+ }
+ _pscrList.clear();
+ Resource::loadResource(_pscrList, "pscr.lst", false);
+
+ loadMobPriority("mobpri");
+
+ _mobList.clear();
+ if (getGameType() == kPrinceDataDE) {
+ const Common::String mobLstName = Common::String::format("mob%02d.lst", _locationNr);
+ debug(3, "moblist name: %s", mobLstName.c_str());
+ Resource::loadResource(_mobList, mobLstName.c_str(), false);
+ } else if (getGameType() == kPrinceDataPL) {
+ Resource::loadResource(_mobList, "mob.lst", false);
+ }
+ if (getFeatures() & GF_TRANSLATED) {
+ // update Mob texts for translated version
+ setMobTranslationTexts();
+ }
+
+ _animList.clear();
+ Resource::loadResource(_animList, "anim.lst", false);
+
+ for (uint32 i = 0; i < _objList.size(); i++) {
+ delete _objList[i];
+ }
+ _objList.clear();
+ Resource::loadResource(_objList, "obj.lst", false);
+
+ _room->loadRoom(_script->getRoomOffset(_locationNr));
+
+ for (uint i = 0; i < _maskList.size(); i++) {
+ free(_maskList[i]._data);
+ }
+ _maskList.clear();
+ _script->loadAllMasks(_maskList, _room->_nak);
+
+ _picWindowX = 0;
+
+ _lightX = _script->getLightX(_locationNr);
+ _lightY = _script->getLightY(_locationNr);
+ setShadowScale(_script->getShadowScale(_locationNr));
+
+ for (uint i = 0; i < _mobList.size(); i++) {
+ _mobList[i]._visible = _script->getMobVisible(_room->_mobs, i);
+ }
+
+ _script->installObjects(_room->_obj);
+
+ freeAllNormAnims();
+
+ clearBackAnimList();
+ _script->installBackAnims(_backAnimList, _room->_backAnim);
+
+ _graph->makeShadowTable(70, _graph->_shadowTable70);
+ _graph->makeShadowTable(50, _graph->_shadowTable50);
+
+ _mainHero->freeOldMove();
+ _secondHero->freeOldMove();
+
+ _mainHero->scrollHero();
+
+ return true;
+}
+
+bool PrinceEngine::loadAnim(uint16 animNr, bool loop) {
+ Common::String streamName = Common::String::format("AN%02d", animNr);
+ Common::SeekableReadStream *flicStream = SearchMan.createReadStreamForMember(streamName);
+
+ if (!flicStream) {
+ error("Can't open %s", streamName.c_str());
+ return false;
+ }
+
+ flicStream = Resource::getDecompressedStream(flicStream);
+
+ if (!_flicPlayer.loadStream(flicStream)) {
+ error("Can't load flic stream %s", streamName.c_str());
+ }
+
+ debugEngine("%s loaded", streamName.c_str());
+ _flicLooped = loop;
+ _flicPlayer.start();
+ playNextFLCFrame();
+ return true;
+}
+
+bool PrinceEngine::loadZoom(byte *zoomBitmap, uint32 dataSize, const char *resourceName) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
+ if (!stream) {
+ delete stream;
+ return false;
+ }
+ stream = Resource::getDecompressedStream(stream);
+
+ if (stream->read(zoomBitmap, dataSize) != dataSize) {
+ free(zoomBitmap);
+ delete stream;
+ return false;
+ }
+ delete stream;
+ return true;
+}
+
+bool PrinceEngine::loadShadow(byte *shadowBitmap, uint32 dataSize, const char *resourceName1, const char *resourceName2) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName1);
+ if (!stream) {
+ delete stream;
+ return false;
+ }
+
+ stream = Resource::getDecompressedStream(stream);
+
+ if (stream->read(shadowBitmap, dataSize) != dataSize) {
+ free(shadowBitmap);
+ delete stream;
+ return false;
+ }
+
+ Common::SeekableReadStream *stream2 = SearchMan.createReadStreamForMember(resourceName2);
+ if (!stream2) {
+ delete stream;
+ delete stream2;
+ return false;
+ }
+
+ stream2 = Resource::getDecompressedStream(stream2);
+
+ byte *shadowBitmap2 = shadowBitmap + dataSize;
+ if (stream2->read(shadowBitmap2, dataSize) != dataSize) {
+ free(shadowBitmap);
+ delete stream;
+ delete stream2;
+ return false;
+ }
+
+ delete stream;
+ delete stream2;
+ return true;
+}
+
+bool PrinceEngine::loadTrans(byte *transTable, const char *resourceName) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
+ if (!stream) {
+ delete stream;
+ for (int i = 0; i < 256; i++) {
+ for (int j = 0; j < 256; j++) {
+ transTable[i * 256 + j] = j;
+ }
+ }
+ return true;
+ }
+
+ stream = Resource::getDecompressedStream(stream);
+
+ if (stream->read(transTable, kTransTableSize) != kTransTableSize) {
+ delete stream;
+ return false;
+ }
+ delete stream;
+ return true;
+}
+
+bool PrinceEngine::loadPath(const char *resourceName) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
+ if (!stream) {
+ delete stream;
+ return false;
+ }
+
+ stream = Resource::getDecompressedStream(stream);
+
+ if (stream->read(_roomPathBitmap, kPathBitmapLen) != kPathBitmapLen) {
+ delete stream;
+ return false;
+ }
+ delete stream;
+ return true;
+}
+
+bool PrinceEngine::loadAllInv() {
+ for (int i = 0; i < kMaxInv; i++) {
+ InvItem tempInvItem;
+
+ const Common::String invStreamName = Common::String::format("INV%02d", i);
+ Common::SeekableReadStream *invStream = SearchMan.createReadStreamForMember(invStreamName);
+ if (!invStream) {
+ delete invStream;
+ return true;
+ }
+
+ invStream = Resource::getDecompressedStream(invStream);
+
+ tempInvItem._x = invStream->readUint16LE();
+ tempInvItem._y = invStream->readUint16LE();
+ int width = invStream->readUint16LE();
+ int height = invStream->readUint16LE();
+ tempInvItem._surface = new Graphics::Surface();
+ tempInvItem._surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int h = 0; h < tempInvItem._surface->h; h++) {
+ invStream->read(tempInvItem._surface->getBasePtr(0, h), tempInvItem._surface->w);
+ }
+
+ _allInvList.push_back(tempInvItem);
+ delete invStream;
+ }
+
+ return true;
+}
+
+bool PrinceEngine::loadMobPriority(const char *resourceName) {
+ Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(resourceName);
+ if (!stream) {
+ delete stream;
+ return false;
+ }
+
+ stream = Resource::getDecompressedStream(stream);
+
+ _mobPriorityList.clear();
+ uint mobId;
+ while (1) {
+ mobId = stream->readUint32LE();
+ if (mobId == 0xFFFFFFFF) {
+ break;
+ }
+ _mobPriorityList.push_back(mobId);
+ }
+ delete stream;
+ return true;
+}
+
+} // End of namespace Prince
diff --git a/engines/prince/resource.h b/engines/prince/resource.h
index 96bc2ea26d..1746f2bfb5 100644
--- a/engines/prince/resource.h
+++ b/engines/prince/resource.h
@@ -24,74 +24,85 @@
#define PRINCE_RESOURCE_H
#include "common/stream.h"
+#include "common/memstream.h"
#include "common/archive.h"
#include "common/debug-channels.h"
#include "common/ptr.h"
+#include "prince/decompress.h"
+
namespace Prince {
namespace Resource {
- template <typename T>
- bool loadFromStream(T &resource, Common::SeekableReadStream &stream) {
- return resource.loadStream(stream);
- }
+Common::SeekableReadStream *getDecompressedStream(Common::SeekableReadStream *stream);
- template<typename T>
- bool loadResource(T *resource, const char *resourceName, bool required) {
- Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
- if (!stream) {
- if (required)
- error("Can't load %s", resourceName);
- return false;
- }
+template <typename T>
+bool loadFromStream(T &resource, Common::SeekableReadStream &stream) {
+ return resource.loadStream(stream);
+}
- return loadFromStream(*resource, *stream);
+template<typename T>
+bool loadResource(T *resource, const char *resourceName, bool required) {
+ Common::SeekableReadStream *stream_(SearchMan.createReadStreamForMember(resourceName));
+ if (!stream_) {
+ if (required)
+ error("Can't load %s", resourceName);
+ return false;
}
- template <typename T>
- bool loadResource(Common::Array<T> &array, Common::SeekableReadStream &stream, bool required = true) {
- T t;
- while (t.loadFromStream(stream))
- array.push_back(t);
+ Common::ScopedPtr<Common::SeekableReadStream> stream(getDecompressedStream(stream_));
- return true;
- }
+ return loadFromStream(*resource, *stream);
+}
+template <typename T>
+bool loadResource(Common::Array<T> &array, Common::SeekableReadStream &stream, bool required = true) {
+ T t;
+ while (t.loadFromStream(stream))
+ array.push_back(t);
- template <typename T>
- bool loadResource(Common::Array<T> &array, const char *resourceName, bool required = true) {
- Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
- if (!stream) {
- if (required)
- error("Can't load %s", resourceName);
- return false;
- }
+ return true;
+}
- return loadResource(array, *stream, required);
+
+template <typename T>
+bool loadResource(Common::Array<T> &array, const char *resourceName, bool required = true) {
+ Common::SeekableReadStream *stream_(SearchMan.createReadStreamForMember(resourceName));
+ if (!stream_) {
+ if (required)
+ error("Can't load %s", resourceName);
+ return false;
}
- template <typename T>
- bool loadResource(Common::Array<T *> &array, const char *resourceName, bool required = true) {
+ Common::ScopedPtr<Common::SeekableReadStream> stream(getDecompressedStream(stream_));
- Common::ScopedPtr<Common::SeekableReadStream> stream(SearchMan.createReadStreamForMember(resourceName));
- if (!stream) {
- if (required)
- error("Can't load %s", resourceName);
- return false;
- }
+ return loadResource(array, *stream, required);
+}
+
+template <typename T>
+bool loadResource(Common::Array<T *> &array, const char *resourceName, bool required = true) {
- // FIXME: This is stupid. Maybe loadFromStream should be helper method that returns initiailzed object
- while (true) {
- T* t = new T();
- if (!t->loadFromStream(*stream)) {
- delete t;
- break;
- }
- array.push_back(t);
+ Common::SeekableReadStream *stream_(SearchMan.createReadStreamForMember(resourceName));
+ if (!stream_) {
+ if (required)
+ error("Can't load %s", resourceName);
+ return false;
+ }
+
+ Common::ScopedPtr<Common::SeekableReadStream> stream(getDecompressedStream(stream_));
+
+ // FIXME: This is stupid. Maybe loadFromStream should be helper method that returns initialized object
+ while (true) {
+ T* t = new T();
+ if (!t->loadFromStream(*stream)) {
+ delete t;
+ break;
}
- return true;
+ array.push_back(t);
}
+ return true;
+}
}
diff --git a/engines/prince/saveload.cpp b/engines/prince/saveload.cpp
index 14f6078910..b1d9fc49fd 100644
--- a/engines/prince/saveload.cpp
+++ b/engines/prince/saveload.cpp
@@ -30,22 +30,63 @@
#include "common/system.h"
#include "common/config-manager.h"
#include "common/memstream.h"
+#include "common/translation.h"
#include "graphics/thumbnail.h"
#include "graphics/surface.h"
#include "graphics/palette.h"
#include "graphics/scaler.h"
+#include "gui/saveload.h"
+
namespace Prince {
-#define kBadSVG 99
#define kSavegameVersion 1
class InterpreterFlags;
class Interpreter;
-bool PrinceEngine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) {
- header.thumbnail = nullptr;
+bool PrinceEngine::scummVMSaveLoadDialog(bool isSave) {
+ GUI::SaveLoadChooser *dialog;
+ Common::String desc;
+ int slot;
+
+ if (isSave) {
+ dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+
+ slot = dialog->runModalWithCurrentTarget();
+ desc = dialog->getResultString();
+
+ if (desc.empty()) {
+ desc = dialog->createDefaultSaveDescription(slot);
+ }
+ } else {
+ dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false);
+ slot = dialog->runModalWithCurrentTarget();
+ }
+
+ delete dialog;
+
+ if (slot < 0)
+ return false;
+
+ if (isSave) {
+ return saveGameState(slot, desc).getCode() == Common::kNoError;
+ } else {
+ return loadGameState(slot).getCode() == Common::kNoError;
+ }
+}
+
+WARN_UNUSED_RESULT bool PrinceEngine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header, bool skipThumbnail) {
+ header.version = 0;
+ header.saveName.clear();
+ header.thumbnail = nullptr;
+ header.saveYear = 0;
+ header.saveMonth = 0;
+ header.saveDay = 0;
+ header.saveHour = 0;
+ header.saveMinutes = 0;
+ header.playTime = 0;
// Get the savegame version
header.version = in->readByte();
@@ -53,22 +94,22 @@ bool PrinceEngine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &he
return false;
// Read in the string
- header.saveName.clear();
char ch;
while ((ch = (char)in->readByte()) != '\0')
header.saveName += ch;
// Get the thumbnail
- header.thumbnail = Graphics::loadThumbnail(*in);
- if (!header.thumbnail)
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
- header.saveYear = in->readSint16LE();
- header.saveMonth = in->readSint16LE();
- header.saveDay = in->readSint16LE();
- header.saveHour = in->readSint16LE();
+ header.saveYear = in->readSint16LE();
+ header.saveMonth = in->readSint16LE();
+ header.saveDay = in->readSint16LE();
+ header.saveHour = in->readSint16LE();
header.saveMinutes = in->readSint16LE();
+ header.playTime = in->readUint32LE();
return true;
}
@@ -157,6 +198,8 @@ void PrinceEngine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader
out->writeSint16LE(td.tm_mday);
out->writeSint16LE(td.tm_hour);
out->writeSint16LE(td.tm_min);
+
+ out->writeUint32LE(g_engine->getTotalPlayTime() / 1000);
}
void PrinceEngine::syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream) {
@@ -417,9 +460,7 @@ bool PrinceEngine::loadGame(int slotNumber) {
return false;
}
- // Delete the thumbnail
- saveHeader.thumbnail->free();
- delete saveHeader.thumbnail;
+ g_engine->setTotalPlayTime(saveHeader.playTime * 1000);
}
// Get in the savegame
diff --git a/engines/prince/script.cpp b/engines/prince/script.cpp
index 23ef24a268..2581dde1c1 100644
--- a/engines/prince/script.cpp
+++ b/engines/prince/script.cpp
@@ -222,7 +222,7 @@ void Script::setObjId(int roomObjOffset, int slot, byte objectId) {
}
int Script::scanMobEvents(int mobMask, int dataEventOffset) {
- debug("mobMask: %d", mobMask);
+ debug(3, "scanMobEvents: mobMask: %d", mobMask);
int i = 0;
int16 mob;
int32 code;
@@ -230,7 +230,7 @@ int Script::scanMobEvents(int mobMask, int dataEventOffset) {
mob = (int)READ_LE_UINT16(&_data[dataEventOffset + i * 6]);
if (mob == mobMask) {
code = (int)READ_LE_UINT32(&_data[dataEventOffset + i * 6 + 2]);
- debug("code: %d", code);
+ debug(3, "scanMobEvents: code: %d", code);
return code;
}
i++;
@@ -239,7 +239,7 @@ int Script::scanMobEvents(int mobMask, int dataEventOffset) {
}
int Script::scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask) {
- debug("mobMask: %d", mobMask);
+ debug(3, "scanMobEventsWithItem: mobMask: %d", mobMask);
int i = 0;
int16 mob;
int16 item;
@@ -250,8 +250,8 @@ int Script::scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask
item = (int)READ_LE_UINT16(&_data[dataEventOffset + i * 8 + 2]);
if (item == itemMask) {
code = (int)READ_LE_UINT32(&_data[dataEventOffset + i * 8 + 4]);
- debug("itemMask: %d", item);
- debug("code: %d", code);
+ debug(3, "scanMobEventsWithItem: itemMask: %d", item);
+ debug(3, "scanMobEventsWithItem: code: %d", code);
return code;
}
}
@@ -388,9 +388,11 @@ bool Script::loadAllMasks(Common::Array<Mask> &maskList, int offset) {
tempMask._width = 0;
tempMask._height = 0;
tempMask._data = nullptr;
- debug("Can't load %s", msStreamName.c_str());
+ warning("loadAllMasks: Can't load %s", msStreamName.c_str());
delete msStream;
} else {
+ msStream = Resource::getDecompressedStream(msStream);
+
int32 dataSize = msStream->size();
if (dataSize != -1) {
tempMask._data = (byte *)malloc(dataSize);
@@ -450,11 +452,9 @@ void Interpreter::debugInterpreter(const char *s, ...) {
Common::String str = Common::String::format("@0x%08X: ", _lastInstruction);
str += Common::String::format("op %04d: ", _lastOpcode);
- //debugC(10, DebugChannel::kScript, "PrinceEngine::Script %s %s", str.c_str(), buf);
if (!strcmp(_mode, "fg")) {
debug(10, "PrinceEngine::Script %s %s", str.c_str(), buf);
}
- //debug("Prince::Script mode %s %s %s", _mode, str.c_str(), buf);
}
void Interpreter::stepBg() {
@@ -916,8 +916,7 @@ void Interpreter::O_ADDFLAG() {
_flags->setFlagValue(flagId, _flags->getFlagValue(flagId) + value);
if (_flags->getFlagValue(flagId)) {
_result = 1;
- }
- else {
+ } else {
_result = 0;
}
debugInterpreter("O_ADDFLAG flagId %04x (%s), value %d", flagId, Flags::getFlagName(flagId), value);
@@ -936,8 +935,7 @@ void Interpreter::O_SUBFLAG() {
_flags->setFlagValue(flagId, _flags->getFlagValue(flagId) - value);
if (_flags->getFlagValue(flagId)) {
_result = 1;
- }
- else {
+ } else {
_result = 0;
}
debugInterpreter("O_SUBFLAG flagId %d, value %d", flagId, value);
@@ -949,8 +947,7 @@ void Interpreter::O_SETSTRING() {
if (offset >= 80000) {
_string = _vm->_variaTxt->getString(offset - 80000);
debugInterpreter("GetVaria %s", _string);
- }
- else if (offset < 2000) {
+ } else if (offset < 2000) {
_vm->_dialogData = &_vm->_dialogDat[offset * 4 - 4];
uint32 of = READ_LE_UINT32(_vm->_talkTxt + offset * 4);
const char *txt = (const char *)&_vm->_talkTxt[of];
@@ -1016,6 +1013,12 @@ void Interpreter::O_XORFLAG() {
void Interpreter::O_GETMOBTEXT() {
int32 mob = readScriptFlagValue();
_currentString = _vm->_locationNr * 100 + mob + 60001;
+ // FIXME: UB?
+ // This casts away the constness of the pointer returned by c_str() which is
+ // stored and potentially modified later (for example in printAt()).
+ // Also, the pointer is only valid as long as _vm->_mobList[mob]
+ // is around and _vm->_mobList[mob]._examText hasn't been modified by any of its
+ // non-const member functions which also might or might not be a problem.
_string = (byte *)_vm->_mobList[mob]._examText.c_str();
debugInterpreter("O_GETMOBTEXT mob %d", mob);
}
@@ -1832,6 +1835,12 @@ void Interpreter::O_DISABLENAK() {
void Interpreter::O_GETMOBNAME() {
int32 modId = readScriptFlagValue();
+ // FIXME: UB?
+ // This casts away the constness of the pointer returned by c_str() which is
+ // stored and potentially modified later (for example in printAt()).
+ // Also, the pointer is only valid as long as _vm->_mobList[mobId]
+ // is around and _vm->_mobList[mobId]._name hasn't been modified by any of its
+ // non-const member functions which also might or might not be a problem.
_string = (byte *)_vm->_mobList[modId]._name.c_str();
debugInterpreter("O_GETMOBNAME modId %d", modId);
}
diff --git a/engines/prince/sound.cpp b/engines/prince/sound.cpp
index 206b131cd2..49983860be 100644
--- a/engines/prince/sound.cpp
+++ b/engines/prince/sound.cpp
@@ -20,191 +20,147 @@
*
*/
-#include "prince/sound.h"
-#include "prince/musNum.h"
-
#include "common/archive.h"
-#include "common/debug.h"
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
+
+#include "audio/audiostream.h"
+#include "audio/decoders/wave.h"
+
+#include "prince/prince.h"
+#include "prince/hero.h"
+#include "prince/script.h"
namespace Prince {
-const char *MusicPlayer::_musTable[] = {
- "",
- "Battlfld.mid",
- "Cave.mid",
- "Cemetery.mid",
- "Credits.mid",
- "Fjord.mid",
- "Guitar.mid",
- "Hell.mid",
- "Jingle.mid",
- "Main.mid",
- "Night.mid",
- "Reality.mid",
- "Sunlord.mid",
- "Tavern.mid",
- "Temple.mid",
- "Boruta.mid",
- "Intro.mid"
-};
-
-const uint8 MusicPlayer::_musRoomTable[] = {
- 0,
- ROOM01MUS,
- ROOM02MUS,
- ROOM03MUS,
- ROOM04MUS,
- ROOM05MUS,
- ROOM06MUS,
- ROOM07MUS,
- ROOM08MUS,
- ROOM09MUS,
- ROOM10MUS,
- ROOM11MUS,
- ROOM12MUS,
- ROOM13MUS,
- ROOM14MUS,
- ROOM15MUS,
- ROOM16MUS,
- ROOM17MUS,
- ROOM18MUS,
- ROOM19MUS,
- ROOM20MUS,
- ROOM21MUS,
- ROOM22MUS,
- ROOM23MUS,
- ROOM24MUS,
- ROOM25MUS,
- ROOM26MUS,
- ROOM27MUS,
- ROOM28MUS,
- ROOM29MUS,
- ROOM30MUS,
- ROOM31MUS,
- ROOM32MUS,
- ROOM33MUS,
- ROOM34MUS,
- ROOM35MUS,
- ROOM36MUS,
- ROOM37MUS,
- ROOM38MUS,
- ROOM39MUS,
- ROOM40MUS,
- ROOM41MUS,
- ROOM42MUS,
- ROOM43MUS,
- 0,
- 0,
- ROOM46MUS,
- ROOM47MUS,
- ROOM48MUS,
- ROOM49MUS,
- ROOM50MUS,
- ROOM51MUS,
- ROOM52MUS,
- ROOM53MUS,
- ROOM54MUS,
- ROOM55MUS,
- ROOM56MUS,
- ROOM57MUS,
- ROOM58MUS,
- ROOM59MUS,
- ROOM60MUS,
- ROOM61MUS
-};
-
-
-MusicPlayer::MusicPlayer(PrinceEngine *vm) : _vm(vm) {
- _data = nullptr;
- _dataSize = 0;
- _isGM = false;
-
- MidiPlayer::createDriver();
-
- int ret = _driver->open();
- if (ret == 0) {
- if (_nativeMT32)
- _driver->sendMT32Reset();
- else
- _driver->sendGMReset();
-
- _driver->setTimerCallback(this, &timerCallback);
+void PrinceEngine::playSample(uint16 sampleId, uint16 loopType) {
+ if (_audioStream[sampleId]) {
+ if (_mixer->isSoundIDActive(sampleId)) {
+ return;
+ }
+ _audioStream[sampleId]->rewind();
+ if (sampleId < 28) {
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ } else {
+ _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle[sampleId], _audioStream[sampleId], sampleId, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+ }
}
}
-MusicPlayer::~MusicPlayer() {
- killMidi();
+void PrinceEngine::stopSample(uint16 sampleId) {
+ _mixer->stopID(sampleId);
}
-void MusicPlayer::killMidi() {
- Audio::MidiPlayer::stop();
+void PrinceEngine::stopAllSamples() {
+ _mixer->stopAll();
+}
- free(_data);
- _data = nullptr;
+void PrinceEngine::freeSample(uint16 sampleId) {
+ stopSample(sampleId);
+ if (_audioStream[sampleId] != nullptr) {
+ delete _audioStream[sampleId];
+ _audioStream[sampleId] = nullptr;
+ }
}
-void MusicPlayer::loadMidi(const char *name) {
- Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name);
- if (!stream) {
- debug("Can't load midi stream %s", name);
- return;
+void PrinceEngine::freeAllSamples() {
+ for (int sampleId = 0; sampleId < kMaxSamples; sampleId++) {
+ freeSample(sampleId);
}
+}
- // Stop any currently playing MIDI file
- killMidi();
+bool PrinceEngine::loadSample(uint32 sampleSlot, const Common::String &streamName) {
+ // FIXME: This is just a workaround streamName is a path
+ // SOUND\\SCIERKA1.WAV for now only last path component is used
+ Common::String normalizedPath = lastPathComponent(streamName, '\\');
- // Read in the data for the file
- _dataSize = stream->size();
- _data = (byte *)malloc(_dataSize);
- stream->read(_data, _dataSize);
+ // WALKAROUND: Wrong name in script, not existing sound in data files
+ if (!normalizedPath.compareTo("9997BEKA.WAV")) {
+ return 0;
+ }
- delete stream;
+ debugEngine("loadSample slot %d, name %s", sampleSlot, normalizedPath.c_str());
- // Start playing the music
- sndMidiStart();
+ freeSample(sampleSlot);
+ Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(normalizedPath);
+ if (sampleStream == nullptr) {
+ delete sampleStream;
+ error("Can't load sample %s to slot %d", normalizedPath.c_str(), sampleSlot);
+ }
+ _audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
+ delete sampleStream;
+ return true;
}
-void MusicPlayer::sndMidiStart() {
- _isGM = true;
+bool PrinceEngine::loadVoice(uint32 slot, uint32 sampleSlot, const Common::String &streamName) {
+ if (getFeatures() & GF_NOVOICES)
+ return false;
- MidiParser *parser = MidiParser::createParser_SMF();
- if (parser->loadMusic(_data, _dataSize)) {
- parser->setTrack(0);
- parser->setMidiDriver(this);
- parser->setTimerRate(_driver->getBaseTempo());
- parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+ debugEngine("Loading wav %s slot %d", streamName.c_str(), slot);
- _parser = parser;
+ if (slot >= kMaxTexts) {
+ error("Text slot bigger than MAXTEXTS %d", kMaxTexts - 1);
+ return false;
+ }
- syncVolume();
+ freeSample(sampleSlot);
+ Common::SeekableReadStream *sampleStream = SearchMan.createReadStreamForMember(streamName);
+ if (sampleStream == nullptr) {
+ warning("loadVoice: Can't open %s", streamName.c_str());
+ return false;
+ }
- // Al the tracks are supposed to loop
- _isLooping = true;
- _isPlaying = true;
+ uint32 id = sampleStream->readUint32LE();
+ if (id != MKTAG('F', 'F', 'I', 'R')) {
+ error("It's not RIFF file %s", streamName.c_str());
+ return false;
}
-}
-void MusicPlayer::send(uint32 b) {
- if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) {
- b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ sampleStream->skip(0x20);
+ id = sampleStream->readUint32LE();
+ if (id != MKTAG('a', 't', 'a', 'd')) {
+ error("No data section in %s id %04x", streamName.c_str(), id);
+ return false;
}
- Audio::MidiPlayer::send(b);
+ id = sampleStream->readUint32LE();
+ debugEngine("SetVoice slot %d time %04x", slot, id);
+ id <<= 3;
+ id /= 22050;
+ id += 2;
+
+ _textSlots[slot]._time = id;
+ if (!slot) {
+ _mainHero->_talkTime = id;
+ } else if (slot == 1) {
+ _secondHero->_talkTime = id;
+ }
+
+ debugEngine("SetVoice slot %d time %04x", slot, id);
+ sampleStream->seek(SEEK_SET);
+ _audioStream[sampleSlot] = Audio::makeWAVStream(sampleStream, DisposeAfterUse::NO);
+ delete sampleStream;
+ return true;
}
-void MusicPlayer::sendToChannel(byte channel, uint32 b) {
- if (!_channelsTable[channel]) {
- _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
- // If a new channel is allocated during the playback, make sure
- // its volume is correctly initialized.
- if (_channelsTable[channel])
- _channelsTable[channel]->volume(_channelsVolume[channel] * _masterVolume / 255);
+void PrinceEngine::setVoice(uint16 slot, uint32 sampleSlot, uint16 flag) {
+ Common::String sampleName;
+ uint32 currentString = _interpreter->getCurrentString();
+
+ if (currentString >= 80000) {
+ uint32 nr = currentString - 80000;
+ sampleName = Common::String::format("%02d0%02d-%02d.WAV", nr / 100, nr % 100, flag);
+ } else if (currentString >= 70000) {
+ sampleName = Common::String::format("inv%02d-01.WAV", currentString - 70000);
+ } else if (currentString >= 60000) {
+ sampleName = Common::String::format("M%04d-%02d.WAV", currentString - 60000, flag);
+ } else if (currentString >= 2000) {
+ return;
+ } else if (flag >= 100) {
+ sampleName = Common::String::format("%03d-%03d.WAV", currentString, flag);
+ } else {
+ sampleName = Common::String::format("%03d-%02d.WAV", currentString, flag);
}
- if (_channelsTable[channel])
- _channelsTable[channel]->send(b);
+ loadVoice(slot, sampleSlot, sampleName);
}
} // End of namespace Prince
diff --git a/engines/prince/walk.cpp b/engines/prince/walk.cpp
new file mode 100644
index 0000000000..0e81c36f3f
--- /dev/null
+++ b/engines/prince/walk.cpp
@@ -0,0 +1,1610 @@
+/* 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 "prince/prince.h"
+#include "prince/hero.h"
+#include "prince/script.h"
+
+namespace Prince {
+
+void PrinceEngine::walkTo() {
+ if (_mainHero->_visible) {
+ _mainHero->freeHeroAnim();
+ _mainHero->freeOldMove();
+ _interpreter->storeNewPC(_script->_scriptInfo.usdCode);
+ int destX, destY;
+ if (_optionsMob != -1) {
+ destX = _mobList[_optionsMob]._examPosition.x;
+ destY = _mobList[_optionsMob]._examPosition.y;
+ _mainHero->_destDirection = _mobList[_optionsMob]._examDirection;
+ } else {
+ Common::Point mousePos = _system->getEventManager()->getMousePos();
+ destX = mousePos.x + _picWindowX;
+ destY = mousePos.y + _picWindowY;
+ _mainHero->_destDirection = 0;
+ }
+ _mainHero->_coords = makePath(kMainHero, _mainHero->_middleX, _mainHero->_middleY, destX, destY);
+ if (_mainHero->_coords != nullptr) {
+ _mainHero->_currCoords = _mainHero->_coords;
+ _mainHero->_dirTab = _directionTable;
+ _mainHero->_currDirTab = _directionTable;
+ _directionTable = nullptr;
+ _mainHero->_state = Hero::kHeroStateMove;
+ moveShandria();
+ }
+ }
+}
+
+void PrinceEngine::moveRunHero(int heroId, int x, int y, int dir, bool runHeroFlag) {
+ Hero *hero = nullptr;
+ if (!heroId) {
+ hero = _mainHero;
+ } else if (heroId == 1) {
+ hero = _secondHero;
+ }
+
+ if (hero != nullptr) {
+ if (dir) {
+ hero->_destDirection = dir;
+ }
+ if (x || y) {
+ hero->freeOldMove();
+ hero->_coords = makePath(heroId, hero->_middleX, hero->_middleY, x, y);
+ if (hero->_coords != nullptr) {
+ hero->_currCoords = hero->_coords;
+ hero->_dirTab = _directionTable;
+ hero->_currDirTab = _directionTable;
+ _directionTable = nullptr;
+ if (runHeroFlag) {
+ hero->_state = Hero::kHeroStateRun;
+ } else {
+ hero->_state = Hero::kHeroStateMove;
+ }
+ if (heroId == kMainHero && _mouseFlag) {
+ moveShandria();
+ }
+ }
+ } else {
+ hero->freeOldMove();
+ hero->_state = Hero::kHeroStateTurn;
+ }
+ hero->freeHeroAnim();
+ hero->_visible = 1;
+ }
+}
+
+// Modified version of Graphics::drawLine() to allow breaking the loop and return value
+int PrinceEngine::drawLine(int x0, int y0, int x1, int y1, int (*plotProc)(int, int, void *), void *data) {
+ // Bresenham's line algorithm, as described by Wikipedia
+ const bool steep = ABS(y1 - y0) > ABS(x1 - x0);
+
+ if (steep) {
+ SWAP(x0, y0);
+ SWAP(x1, y1);
+ }
+
+ const int delta_x = ABS(x1 - x0);
+ const int delta_y = ABS(y1 - y0);
+ const int delta_err = delta_y;
+ int x = x0;
+ int y = y0;
+ int err = 0;
+
+ const int x_step = (x0 < x1) ? 1 : -1;
+ const int y_step = (y0 < y1) ? 1 : -1;
+
+ int stopFlag = 0;
+ if (steep)
+ stopFlag = (*plotProc)(y, x, data);
+ else
+ stopFlag = (*plotProc)(x, y, data);
+
+ while (x != x1 && !stopFlag) {
+ x += x_step;
+ err += delta_err;
+ if (2 * err > delta_x) {
+ y += y_step;
+ err -= delta_x;
+ }
+ if (steep)
+ stopFlag = (*plotProc)(y, x, data);
+ else
+ stopFlag = (*plotProc)(x, y, data);
+ }
+ return stopFlag;
+}
+
+int PrinceEngine::getPixelAddr(byte *pathBitmap, int x, int y) {
+ int mask = 128 >> (x & 7);
+ byte value = pathBitmap[x / 8 + y * 80];
+ return (mask & value);
+}
+
+void PrinceEngine::findPoint(int x, int y) {
+ _fpX = x;
+ _fpY = y;
+
+ if (getPixelAddr(_roomPathBitmap, x, y)) {
+ return;
+ }
+
+ int fpL = x;
+ int fpU = y;
+ int fpR = x;
+ int fpD = y;
+
+ while (1) {
+ if (fpD != kMaxPicHeight) {
+ if (getPixelAddr(_roomPathBitmap, x, fpD)) {
+ _fpX = x;
+ _fpY = fpD;
+ break;
+ }
+ fpD++;
+ }
+ if (fpU) {
+ if (getPixelAddr(_roomPathBitmap, x, fpU)) {
+ _fpX = x;
+ _fpY = fpU;
+ break;
+ }
+ fpU--;
+ }
+ if (fpL) {
+ if (getPixelAddr(_roomPathBitmap, fpL, y)) {
+ _fpX = fpL;
+ _fpY = y;
+ break;
+ }
+ fpL--;
+ }
+ if (fpR != _sceneWidth) {
+ if (getPixelAddr(_roomPathBitmap, fpR, y)) {
+ _fpX = fpR;
+ _fpY = y;
+ break;
+ }
+ fpR++;
+ }
+ if (!fpU && (fpD == kMaxPicHeight)) {
+ if (!fpL && (fpR == _sceneWidth)) {
+ break;
+ }
+ }
+ }
+}
+
+Direction PrinceEngine::makeDirection(int x1, int y1, int x2, int y2) {
+ if (x1 != x2) {
+ if (y1 != y2) {
+ if (x1 > x2) {
+ if (y1 > y2) {
+ if (x1 - x2 >= y1 - y2) {
+ return kDirLU;
+ } else {
+ return kDirUL;
+ }
+ } else {
+ if (x1 - x2 >= y2 - y1) {
+ return kDirLD;
+ } else {
+ return kDirDL;
+ }
+ }
+ } else {
+ if (y1 > y2) {
+ if (x2 - x1 >= y1 - y2) {
+ return kDirRU;
+ } else {
+ return kDirUR;
+ }
+ } else {
+ if (x2 - x1 >= y2 - y1) {
+ return kDirRD;
+ } else {
+ return kDirDR;
+ }
+ }
+ }
+ } else {
+ if (x1 >= x2) {
+ return kDirL;
+ } else {
+ return kDirR;
+ }
+ }
+ } else {
+ if (y1 >= y2) {
+ return kDirU;
+ } else {
+ return kDirD;
+ }
+ }
+}
+
+void PrinceEngine::specialPlot(int x, int y) {
+ if (_coords < _coordsBufEnd) {
+ WRITE_LE_UINT16(_coords, x);
+ _coords += 2;
+ WRITE_LE_UINT16(_coords, y);
+ _coords += 2;
+ specialPlot2(x, y);
+ }
+}
+
+void PrinceEngine::specialPlot2(int x, int y) {
+ int mask = 128 >> (x & 7);
+ _roomPathBitmapTemp[x / 8 + y * 80] |= mask;
+}
+
+void PrinceEngine::specialPlotInside(int x, int y) {
+ if (_coords < _coordsBufEnd) {
+ WRITE_LE_UINT16(_coords, x);
+ _coords += 2;
+ WRITE_LE_UINT16(_coords, y);
+ _coords += 2;
+ }
+}
+
+int PrinceEngine::plotTraceLine(int x, int y, void *data) {
+ PrinceEngine *traceLine = (PrinceEngine *)data;
+ if (!traceLine->_traceLineFirstPointFlag) {
+ if (!traceLine->getPixelAddr(traceLine->_roomPathBitmapTemp, x, y)) {
+ if (traceLine->getPixelAddr(traceLine->_roomPathBitmap, x, y)) {
+ traceLine->specialPlotInside(x, y);
+ traceLine->_traceLineLen++;
+ return 0;
+ } else {
+ return -1;
+ }
+ } else {
+ return 1;
+ }
+ } else {
+ traceLine->_traceLineFirstPointFlag = false;
+ return 0;
+ }
+}
+
+int PrinceEngine::leftDownDir() {
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::leftDir() {
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::leftUpDir() {
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::rightDownDir() {
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::rightDir() {
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::rightUpDir() {
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::upLeftDir() {
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::upDir() {
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::upRightDir() {
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::downLeftDir() {
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::downDir() {
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::downRightDir() {
+ if (!checkRightDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDownDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkRightUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ if (!checkLeftUpDir()) {
+ specialPlot(_checkX, _checkY);
+ return 0;
+ }
+ return -1;
+}
+
+int PrinceEngine::cpe() {
+ if ((*(_checkBitmap - kPBW) & _checkMask)) {
+ if ((*(_checkBitmap + kPBW) & _checkMask)) {
+ int value;
+ switch (_checkMask) {
+ case 128:
+ value = READ_LE_UINT16(_checkBitmap - 1);
+ value &= 0x4001;
+ if (value != 0x4001) {
+ return 0;
+ }
+ break;
+ case 64:
+ value = *_checkBitmap;
+ value &= 0xA0;
+ if (value != 0xA0) {
+ return 0;
+ }
+ break;
+ case 32:
+ value = *_checkBitmap;
+ value &= 0x50;
+ if (value != 0x50) {
+ return 0;
+ }
+ break;
+ case 16:
+ value = *_checkBitmap;
+ value &= 0x28;
+ if (value != 0x28) {
+ return 0;
+ }
+ break;
+ case 8:
+ value = *_checkBitmap;
+ value &= 0x14;
+ if (value != 0x14) {
+ return 0;
+ }
+ break;
+ case 4:
+ value = *_checkBitmap;
+ value &= 0xA;
+ if (value != 0xA) {
+ return 0;
+ }
+ break;
+ case 2:
+ value = *_checkBitmap;
+ value &= 0x5;
+ if (value != 0x5) {
+ return 0;
+ }
+ break;
+ case 1:
+ value = READ_LE_UINT16(_checkBitmap);
+ value &= 0x8002;
+ if (value != 0x8002) {
+ return 0;
+ }
+ break;
+ default:
+ error("Wrong _checkMask value - cpe()");
+ break;
+ }
+ _checkX = _rembX;
+ _checkY = _rembY;
+ _checkBitmapTemp = _rembBitmapTemp;
+ _checkBitmap = _rembBitmap;
+ _checkMask = _rembMask;
+ return -1;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+int PrinceEngine::checkLeftDownDir() {
+ if (_checkX && _checkY != (kMaxPicHeight / 2 - 1)) {
+ int tempMask = _checkMask;
+ if (tempMask != 128) {
+ tempMask <<= 1;
+ if ((*(_checkBitmap + kPBW) & tempMask)) {
+ if (!(*(_checkBitmapTemp + kPBW) & tempMask)) {
+ _checkBitmap += kPBW;
+ _checkBitmapTemp += kPBW;
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap + kPBW - 1) & 1)) {
+ if (!(*(_checkBitmapTemp + kPBW - 1) & 1)) {
+ _checkBitmap += (kPBW - 1);
+ _checkBitmapTemp += (kPBW - 1);
+ _checkMask = 1;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX--;
+ _checkY++;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkLeftDir() {
+ if (_checkX) {
+ int tempMask = _checkMask;
+ if (tempMask != 128) {
+ tempMask <<= 1;
+ if ((*(_checkBitmap) & tempMask)) {
+ if (!(*(_checkBitmapTemp) & tempMask)) {
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap - 1) & 1)) {
+ if (!(*(_checkBitmapTemp - 1) & 1)) {
+ _checkBitmap--;
+ _checkBitmapTemp--;
+ _checkMask = 1;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX--;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkDownDir() {
+ if (_checkY != (kMaxPicHeight / 2 - 1)) {
+ if ((*(_checkBitmap + kPBW) & _checkMask)) {
+ if (!(*(_checkBitmapTemp + kPBW) & _checkMask)) {
+ _checkBitmap += kPBW;
+ _checkBitmapTemp += kPBW;
+ _checkY++;
+ return cpe();
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkUpDir() {
+ if (_checkY) {
+ if ((*(_checkBitmap - kPBW) & _checkMask)) {
+ if (!(*(_checkBitmapTemp - kPBW) & _checkMask)) {
+ _checkBitmap -= kPBW;
+ _checkBitmapTemp -= kPBW;
+ _checkY--;
+ return cpe();
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkRightDir() {
+ if (_checkX != (kMaxPicWidth / 2 - 1)) {
+ int tempMask = _checkMask;
+ if (tempMask != 1) {
+ tempMask >>= 1;
+ if ((*(_checkBitmap) & tempMask)) {
+ if (!(*(_checkBitmapTemp) & tempMask)) {
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap + 1) & 128)) {
+ if (!(*(_checkBitmapTemp + 1) & 128)) {
+ _checkBitmap++;
+ _checkBitmapTemp++;
+ _checkMask = 128;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX++;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkLeftUpDir() {
+ if (_checkX && _checkY) {
+ int tempMask = _checkMask;
+ if (tempMask != 128) {
+ tempMask <<= 1;
+ if ((*(_checkBitmap - kPBW) & tempMask)) {
+ if (!(*(_checkBitmapTemp - kPBW) & tempMask)) {
+ _checkBitmap -= kPBW;
+ _checkBitmapTemp -= kPBW;
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap - (kPBW + 1)) & 1)) {
+ if (!(*(_checkBitmapTemp - (kPBW + 1)) & 1)) {
+ _checkBitmap -= (kPBW + 1);
+ _checkBitmapTemp -= (kPBW + 1);
+ _checkMask = 1;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX--;
+ _checkY--;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkRightDownDir() {
+ if (_checkX != (kMaxPicWidth / 2 - 1) && _checkY != (kMaxPicHeight / 2 - 1)) {
+ int tempMask = _checkMask;
+ if (tempMask != 1) {
+ tempMask >>= 1;
+ if ((*(_checkBitmap + kPBW) & tempMask)) {
+ if (!(*(_checkBitmapTemp + kPBW) & tempMask)) {
+ _checkBitmap += kPBW;
+ _checkBitmapTemp += kPBW;
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap + kPBW + 1) & 128)) {
+ if (!(*(_checkBitmapTemp + kPBW + 1) & 128)) {
+ _checkBitmap += kPBW + 1;
+ _checkBitmapTemp += kPBW + 1;
+ _checkMask = 128;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX++;
+ _checkY++;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+int PrinceEngine::checkRightUpDir() {
+ if (_checkX != (kMaxPicWidth / 2 - 1) && _checkY) {
+ int tempMask = _checkMask;
+ if (tempMask != 1) {
+ tempMask >>= 1;
+ if ((*(_checkBitmap - kPBW) & tempMask)) {
+ if (!(*(_checkBitmapTemp - kPBW) & tempMask)) {
+ _checkBitmap -= kPBW;
+ _checkBitmapTemp -= kPBW;
+ _checkMask = tempMask;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ if ((*(_checkBitmap - kPBW + 1) & 128)) {
+ if (!(*(_checkBitmapTemp - kPBW + 1) & 128)) {
+ _checkBitmap -= (kPBW - 1);
+ _checkBitmapTemp -= (kPBW - 1);
+ _checkMask = 128;
+ } else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ _checkX++;
+ _checkY--;
+ return cpe();
+ } else {
+ return -1;
+ }
+}
+
+bool PrinceEngine::tracePath(int x1, int y1, int x2, int y2) {
+ for (uint i = 0; i < kPathBitmapLen; i++) {
+ _roomPathBitmapTemp[i] = 0;
+ }
+ if (x1 != x2 || y1 != y2) {
+ if (getPixelAddr(_roomPathBitmap, x1, y1)) {
+ if (getPixelAddr(_roomPathBitmap, x2, y2)) {
+ _coords = _coordsBuf;
+ specialPlot(x1, y1);
+
+ int x = x1;
+ int y = y1;
+
+ while (1) {
+ int btx = x;
+ int bty = y;
+ byte *bcad = _coords;
+
+ _traceLineLen = 0;
+ _traceLineFirstPointFlag = true;
+ int drawLineFlag = drawLine(x, y, x2, y2, &this->plotTraceLine, this);
+
+ if (!drawLineFlag) {
+ return true;
+ } else if (drawLineFlag == -1 && _traceLineLen >= 2) {
+ byte *tempCorrds = bcad;
+ while (tempCorrds != _coords) {
+ x = READ_LE_UINT16(tempCorrds);
+ y = READ_LE_UINT16(tempCorrds + 2);
+ tempCorrds += 4;
+ specialPlot2(x, y);
+ }
+ } else {
+ _coords = bcad;
+ x = btx;
+ y = bty;
+ }
+
+ Direction dir = makeDirection(x, y, x2, y2);
+
+ _rembBitmapTemp = &_roomPathBitmapTemp[x / 8 + y * 80];
+ _rembBitmap = &_roomPathBitmap[x / 8 + y * 80];
+ _rembMask = 128 >> (x & 7);
+ _rembX = x;
+ _rembY = y;
+
+ _checkBitmapTemp = _rembBitmapTemp;
+ _checkBitmap = _rembBitmap;
+ _checkMask = _rembMask;
+ _checkX = _rembX;
+ _checkY = _rembY;
+
+ int result;
+ switch (dir) {
+ case kDirLD:
+ result = leftDownDir();
+ break;
+ case kDirL:
+ result = leftDir();
+ break;
+ case kDirLU:
+ result = leftUpDir();
+ break;
+ case kDirRD:
+ result = rightDownDir();
+ break;
+ case kDirR:
+ result = rightDir();
+ break;
+ case kDirRU:
+ result = rightUpDir();
+ break;
+ case kDirUL:
+ result = upLeftDir();
+ break;
+ case kDirU:
+ result = upDir();
+ break;
+ case kDirUR:
+ result = upRightDir();
+ break;
+ case kDirDL:
+ result = downLeftDir();
+ break;
+ case kDirD:
+ result = downDir();
+ break;
+ case kDirDR:
+ result = downRightDir();
+ break;
+ default:
+ result = -1;
+ error("tracePath: wrong direction %d", dir);
+ break;
+ }
+
+ if (result) {
+ byte *tempCoords = _coords;
+ tempCoords -= 4;
+ if (tempCoords > _coordsBuf) {
+ int tempX = READ_LE_UINT16(tempCoords);
+ int tempY = READ_LE_UINT16(tempCoords + 2);
+ if (_checkX == tempX && _checkY == tempY) {
+ _coords = tempCoords;
+ }
+ x = READ_LE_UINT16(tempCoords);
+ y = READ_LE_UINT16(tempCoords + 2);
+ } else {
+ return false;
+ }
+ } else {
+ x = _checkX;
+ y = _checkY;
+ }
+ }
+ return true;
+ } else {
+ error("tracePath: wrong destination point");
+ }
+ } else {
+ error("tracePath: wrong start point");
+ }
+ } else {
+ error("tracePath: same point");
+ }
+}
+
+void PrinceEngine::specialPlotInside2(int x, int y) {
+ WRITE_LE_UINT16(_coords2, x);
+ _coords2 += 2;
+ WRITE_LE_UINT16(_coords2, y);
+ _coords2 += 2;
+}
+
+int PrinceEngine::plotTracePoint(int x, int y, void *data) {
+ PrinceEngine *tracePoint = (PrinceEngine *)data;
+ if (!tracePoint->_tracePointFirstPointFlag) {
+ if (tracePoint->getPixelAddr(tracePoint->_roomPathBitmap, x, y)) {
+ tracePoint->specialPlotInside2(x, y);
+ return 0;
+ } else {
+ return -1;
+ }
+ } else {
+ tracePoint->_tracePointFirstPointFlag = false;
+ return 0;
+ }
+}
+
+void PrinceEngine::approxPath() {
+ byte *oldCoords;
+ _coords2 = _coordsBuf2;
+ byte *tempCoordsBuf = _coordsBuf; // first point on path
+ byte *tempCoords = _coords;
+ if (tempCoordsBuf != tempCoords) {
+ tempCoords -= 4; // last point on path
+ while (tempCoordsBuf != tempCoords) {
+ int x1 = READ_LE_UINT16(tempCoords);
+ int y1 = READ_LE_UINT16(tempCoords + 2);
+ int x2 = READ_LE_UINT16(tempCoordsBuf);
+ int y2 = READ_LE_UINT16(tempCoordsBuf + 2);
+ tempCoordsBuf += 4;
+ //TracePoint
+ oldCoords = _coords2;
+ if (_coords2 == _coordsBuf2) {
+ WRITE_LE_UINT16(_coords2, x1);
+ WRITE_LE_UINT16(_coords2 + 2, y1);
+ _coords2 += 4;
+ } else {
+ int testX = READ_LE_UINT16(_coords2 - 4);
+ int testY = READ_LE_UINT16(_coords2 - 2);
+ if (testX != x1 || testY != y1) {
+ WRITE_LE_UINT16(_coords2, x1);
+ WRITE_LE_UINT16(_coords2 + 2, y1);
+ _coords2 += 4;
+ }
+ }
+ _tracePointFirstPointFlag = true;
+ bool drawLineFlag = drawLine(x1, y1, x2, y2, &this->plotTracePoint, this);
+ if (!drawLineFlag) {
+ tempCoords = tempCoordsBuf - 4;
+ tempCoordsBuf = _coordsBuf;
+ } else {
+ _coords2 = oldCoords;
+ }
+ }
+ }
+}
+
+void PrinceEngine::freeDirectionTable() {
+ if (_directionTable != nullptr) {
+ free(_directionTable);
+ _directionTable = nullptr;
+ }
+}
+
+int PrinceEngine::scanDirectionsFindNext(byte *tempCoordsBuf, int xDiff, int yDiff) {
+
+ int tempX, tempY, direction;
+
+ tempX = Hero::kHeroDirLeft;
+ if (xDiff < 0) {
+ tempX = Hero::kHeroDirRight;
+ }
+
+ tempY = Hero::kHeroDirUp;
+ if (yDiff < 0) {
+ tempY = Hero::kHeroDirDown;
+ }
+
+ while (1) {
+ int againPointX1 = READ_LE_UINT16(tempCoordsBuf);
+ int againPointY1 = READ_LE_UINT16(tempCoordsBuf + 2);
+ tempCoordsBuf += 4;
+
+ if (tempCoordsBuf == _coords) {
+ direction = tempX;
+ break;
+ }
+
+ int dX = againPointX1 - READ_LE_UINT16(tempCoordsBuf);
+ int dY = againPointY1 - READ_LE_UINT16(tempCoordsBuf + 2);
+
+ if (dX != xDiff) {
+ direction = tempY;
+ break;
+ }
+
+ if (dY != yDiff) {
+ direction = tempX;
+ break;
+ }
+ }
+ return direction;
+}
+
+void PrinceEngine::scanDirections() {
+ freeDirectionTable();
+ byte *tempCoordsBuf = _coordsBuf;
+ if (tempCoordsBuf != _coords) {
+ int size = (_coords - tempCoordsBuf) / 4 + 1; // number of coord points plus one for end marker
+ _directionTable = (byte *)malloc(size);
+ byte *tempDirTab = _directionTable;
+ int direction = -1;
+ int lastDirection = -1;
+
+ while (1) {
+ int x1 = READ_LE_UINT16(tempCoordsBuf);
+ int y1 = READ_LE_UINT16(tempCoordsBuf + 2);
+ tempCoordsBuf += 4;
+ if (tempCoordsBuf == _coords) {
+ break;
+ }
+ int x2 = READ_LE_UINT16(tempCoordsBuf);
+ int y2 = READ_LE_UINT16(tempCoordsBuf + 2);
+
+ int xDiff = x1 - x2;
+ int yDiff = y1 - y2;
+
+ if (xDiff) {
+ if (yDiff) {
+ if (lastDirection != -1) {
+ direction = lastDirection;
+ if (direction == Hero::kHeroDirLeft) {
+ if (xDiff < 0) {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ } else if (direction == Hero::kHeroDirRight) {
+ if (xDiff >= 0) {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ } else if (direction == Hero::kHeroDirUp) {
+ if (yDiff < 0) {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ } else {
+ if (yDiff >= 0) {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ }
+ } else {
+ direction = scanDirectionsFindNext(tempCoordsBuf, xDiff, yDiff);
+ }
+ } else {
+ direction = Hero::kHeroDirLeft;
+ if (xDiff < 0) {
+ direction = Hero::kHeroDirRight;
+ }
+ }
+ } else {
+ if (yDiff) {
+ direction = Hero::kHeroDirUp;
+ if (yDiff < 0) {
+ direction = Hero::kHeroDirDown;
+ }
+ } else {
+ direction = lastDirection;
+ }
+ }
+ lastDirection = direction;
+ *tempDirTab = direction;
+ tempDirTab++;
+ }
+ *tempDirTab = *(tempDirTab - 1);
+ tempDirTab++;
+ *tempDirTab = 0;
+ }
+}
+
+void PrinceEngine::moveShandria() {
+ int shanLen1 = _shanLen;
+ if (_flags->getFlagValue(Flags::SHANDOG)) {
+ _secondHero->freeHeroAnim();
+ _secondHero->freeOldMove();
+ byte *shanCoords = _mainHero->_currCoords + shanLen1 * 4 - 4;
+ int shanX = READ_LE_UINT16(shanCoords - 4);
+ int shanY = READ_LE_UINT16(shanCoords - 2);
+ int xDiff = shanX - _secondHero->_middleX;
+ if (xDiff < 0) {
+ xDiff *= -1;
+ }
+ int yDiff = shanY - _secondHero->_middleY;
+ if (yDiff < 0) {
+ yDiff *= -1;
+ }
+ shanCoords -= 4;
+ if (shanCoords != _mainHero->_currCoords) {
+ yDiff *= 1.5;
+ int shanDis = xDiff * xDiff + yDiff * yDiff;
+ if (shanDis >= kMinDistance) {
+ while (1) {
+ shanCoords -= 4;
+ if (shanCoords == _mainHero->_currCoords) {
+ break;
+ }
+ int x = READ_LE_UINT16(shanCoords);
+ int y = READ_LE_UINT16(shanCoords + 2);
+ int pointDiffX = x - shanX;
+ if (pointDiffX < 0) {
+ pointDiffX *= -1;
+ }
+ int pointDiffY = y - shanY;
+ if (pointDiffY < 0) {
+ pointDiffY *= -1;
+ }
+ pointDiffY *= 1.5;
+ int distance = pointDiffX * pointDiffX + pointDiffY * pointDiffY;
+ if (distance >= kMinDistance) {
+ break;
+ }
+ }
+ int pathSizeDiff = (shanCoords - _mainHero->_currCoords) / 4;
+ int destDir = *(_mainHero->_currDirTab + pathSizeDiff);
+ _secondHero->_destDirection = destDir;
+ int destX = READ_LE_UINT16(shanCoords);
+ int destY = READ_LE_UINT16(shanCoords + 2);
+ _secondHero->_coords = makePath(kSecondHero, _secondHero->_middleX, _secondHero->_middleY, destX, destY);
+ if (_secondHero->_coords != nullptr) {
+ _secondHero->_currCoords = _secondHero->_coords;
+ int delay = shanLen1 - _shanLen;
+ if (delay < 6) {
+ delay = 6;
+ }
+ _secondHero->_moveDelay = delay / 2;
+ _secondHero->_state = Hero::kHeroStateDelayMove;
+ _secondHero->_dirTab = _directionTable;
+ _secondHero->_currDirTab = _directionTable;
+ _directionTable = nullptr;
+ }
+ }
+ }
+ }
+}
+
+byte *PrinceEngine::makePath(int heroId, int currX, int currY, int destX, int destY) {
+ int realDestX = destX;
+ int realDestY = destY;
+ _flags->setFlagValue(Flags::MOVEDESTX, destX);
+ _flags->setFlagValue(Flags::MOVEDESTY, destY);
+
+ int x1 = currX / 2;
+ int y1 = currY / 2;
+ int x2 = destX / 2;
+ int y2 = destY / 2;
+
+ if ((x1 != x2) || (y1 != y2)) {
+ findPoint(x1, y1);
+ if (!getPixelAddr(_roomPathBitmap, _fpX, _fpY)) {
+ return nullptr;
+ }
+ if ((x1 != _fpX) || (y1 != _fpY)) {
+ x1 = _fpX;
+ y1 = _fpY;
+ }
+ findPoint(x2, y2);
+ if (!getPixelAddr(_roomPathBitmap, _fpX, _fpY)) {
+ return nullptr;
+ }
+ if ((x2 != _fpX) || (y2 != _fpY)) {
+ x2 = _fpX;
+ y2 = _fpY;
+ if (!_flags->getFlagValue(Flags::EXACTMOVE)) {
+ realDestX = x2 * 2;
+ realDestY = y2 * 2;
+ _flags->setFlagValue(Flags::MOVEDESTX, realDestX);
+ _flags->setFlagValue(Flags::MOVEDESTY, realDestY);
+ } else {
+ return nullptr;
+ }
+ }
+
+ if ((x1 == x2) && (y1 == y2)) {
+ if (!heroId) {
+ _mainHero->freeOldMove();
+ _mainHero->_state = Hero::kHeroStateTurn;
+ } else if (heroId == 1) {
+ _secondHero->freeOldMove();
+ _secondHero->_state = Hero::kHeroStateTurn;
+ }
+ return nullptr;
+ }
+
+ int pathLen1 = 0;
+ int pathLen2 = 0;
+ int stX = x1;
+ int stY = y1;
+ int sizeCoords2 = 0;
+
+ if (tracePath(x1, y1, x2, y2)) {
+ allocCoords2();
+ approxPath();
+ sizeCoords2 = _coords2 - _coordsBuf2;
+ for (int i = 0; i < sizeCoords2; i++) {
+ _coordsBuf[i] = _coordsBuf2[i];
+ }
+ _coords = _coordsBuf + sizeCoords2;
+ approxPath();
+ _coordsBuf3 = _coordsBuf2;
+ _coordsBuf2 = nullptr;
+ _coords3 = _coords2;
+ _coords2 = nullptr;
+ pathLen1 = _coords3 - _coordsBuf3;
+ }
+ if (tracePath(x2, y2, x1, y1)) {
+ allocCoords2();
+ approxPath();
+ sizeCoords2 = _coords2 - _coordsBuf2;
+ for (int i = 0; i < sizeCoords2; i++) {
+ _coordsBuf[i] = _coordsBuf2[i];
+ }
+ _coords = _coordsBuf + sizeCoords2;
+ approxPath();
+ pathLen2 = _coords2 - _coordsBuf2;
+ }
+
+ byte *chosenCoordsBuf = _coordsBuf2;
+ byte *choosenCoords = _coords2;
+ int choosenLength = pathLen1;
+ if (pathLen1 < pathLen2) {
+ chosenCoordsBuf = _coordsBuf3;
+ choosenCoords = _coords3;
+ choosenLength = pathLen2;
+ }
+
+ if (choosenLength) {
+ if (chosenCoordsBuf != nullptr) {
+ int tempXBegin = READ_LE_UINT16(chosenCoordsBuf);
+ int tempYBegin = READ_LE_UINT16(chosenCoordsBuf + 2);
+ if (stX != tempXBegin || stY != tempYBegin) {
+ SWAP(chosenCoordsBuf, choosenCoords);
+ chosenCoordsBuf -= 4;
+ byte *tempCoordsBuf = _coordsBuf;
+ while (1) {
+ int cord = READ_LE_UINT32(chosenCoordsBuf);
+ WRITE_LE_UINT32(tempCoordsBuf, cord);
+ tempCoordsBuf += 4;
+ if (chosenCoordsBuf == choosenCoords) {
+ break;
+ }
+ chosenCoordsBuf -= 4;
+ }
+ _coords = tempCoordsBuf;
+ } else {
+ int sizeChoosen = choosenCoords - chosenCoordsBuf;
+ for (int i = 0; i < sizeChoosen; i++) {
+ _coordsBuf[i] = chosenCoordsBuf[i];
+ }
+ _coords = _coordsBuf + sizeChoosen;
+ }
+ WRITE_LE_UINT32(_coords, 0xFFFFFFFF);
+ freeCoords2();
+ freeCoords3();
+ scanDirections();
+
+ byte *tempCoordsBuf = _coordsBuf;
+ byte *tempCoords = _coords;
+ byte *newCoords;
+ if (tempCoordsBuf != tempCoords) {
+ int normCoordsSize = _coords - _coordsBuf + 4;
+ newCoords = (byte *)malloc(normCoordsSize);
+ byte *newCoordsBegin = newCoords;
+ while (tempCoordsBuf != tempCoords) {
+ int newValueX = READ_LE_UINT16(tempCoordsBuf);
+ WRITE_LE_UINT16(newCoords, newValueX * 2);
+ newCoords += 2;
+ int newValueY = READ_LE_UINT16(tempCoordsBuf + 2);
+ WRITE_LE_UINT16(newCoords, newValueY * 2);
+ newCoords += 2;
+ tempCoordsBuf += 4;
+ }
+ WRITE_LE_UINT16(newCoords - 4, realDestX);
+ WRITE_LE_UINT16(newCoords - 2, realDestY);
+ WRITE_LE_UINT32(newCoords, 0xFFFFFFFF);
+ newCoords += 4;
+ _shanLen = (newCoords - newCoordsBegin);
+ _shanLen /= 4;
+ return newCoordsBegin;
+ }
+ }
+ }
+ _coords = _coordsBuf;
+ freeCoords2();
+ freeCoords3();
+ return nullptr;
+ } else {
+ if (!heroId) {
+ _mainHero->freeOldMove();
+ _mainHero->_state = Hero::kHeroStateTurn;
+ } else if (heroId == 1) {
+ _secondHero->freeOldMove();
+ _secondHero->_state = Hero::kHeroStateTurn;
+ }
+ return nullptr;
+ }
+}
+
+void PrinceEngine::allocCoords2() {
+ if (_coordsBuf2 == nullptr) {
+ _coordsBuf2 = (byte *)malloc(kTracePts * 4);
+ _coords2 = _coordsBuf2;
+ }
+}
+
+void PrinceEngine::freeCoords2() {
+ if (_coordsBuf2 != nullptr) {
+ free(_coordsBuf2);
+ _coordsBuf2 = nullptr;
+ _coords2 = nullptr;
+ }
+}
+
+void PrinceEngine::freeCoords3() {
+ if (_coordsBuf3 != nullptr) {
+ free(_coordsBuf3);
+ _coordsBuf3 = nullptr;
+ _coords3 = nullptr;
+ }
+}
+
+} // End of namespace Prince
diff --git a/engines/queen/detection.cpp b/engines/queen/detection.cpp
index aed8b7dcb1..b9a7c5dff6 100644
--- a/engines/queen/detection.cpp
+++ b/engines/queen/detection.cpp
@@ -422,6 +422,45 @@ static const QueenGameDescription gameDescriptions[] = {
},
#endif
+ // GoG.com Release - German
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1", "28f78dbec7e20f603a10c2f8ea889a5c", 108738717),
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+ // GoG.com Release - French
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1", "67e3020f8a35e1df7b1c753b5aaa71e1", 97382620),
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
+ // GoG.com Release - Italian
+ {
+ {
+ "queen",
+ "Talkie",
+ AD_ENTRY1s("queen.1", "2f72b715ed753cf905a37cdcc7ea611e", 98327801),
+ Common::IT_ITA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GAMEOPTION_ALT_INTRO)
+ },
+ },
+
{ AD_TABLE_END_MARKER }
};
@@ -447,7 +486,7 @@ public:
virtual int getMaximumSaveSlot() const { return 99; }
virtual void removeSaveState(const char *target, int slot) const;
- const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
};
bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -457,7 +496,7 @@ bool QueenMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSupportsDeleteSave);
}
-const ADGameDescription *QueenMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ADDetectedGame QueenMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
static ADGameDescription desc;
// Iterate over all files in the given directory
@@ -492,11 +531,13 @@ const ADGameDescription *QueenMetaEngine::fallbackDetect(const FileMap &allFiles
desc.extra = "Talkie";
desc.guiOptions = GAMEOPTION_ALT_INTRO;
}
- return (const ADGameDescription *)&desc;
+
+ return ADDetectedGame(&desc);
}
}
}
- return 0;
+
+ return ADDetectedGame();
}
SaveStateList QueenMetaEngine::listSaves(const char *target) const {
diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp
index 9f74aab915..c65f2de5ef 100644
--- a/engines/queen/music.cpp
+++ b/engines/queen/music.cpp
@@ -102,10 +102,7 @@ MidiMusic::~MidiMusic() {
}
void MidiMusic::setVolume(int volume) {
- if (volume < 0)
- volume = 0;
- else if (volume > 255)
- volume = 255;
+ volume = CLIP(volume, 0, 255);
if (_masterVolume == volume)
return;
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index 6fe4277c27..82c29d3389 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -105,7 +105,7 @@ public:
_singleId = "saga";
}
- virtual GameDescriptor findGame(const char *gameId) const {
+ PlainGameDescriptor findGame(const char *gameId) const override {
return Engines::findGameID(gameId, _gameIds, obsoleteGameIDsTable);
}
@@ -256,7 +256,11 @@ SaveStateDescriptor SagaMetaEngine::querySaveMetaInfos(const char *target, int s
}
if (version >= 6) {
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*in, thumbnail)) {
+ delete in;
+ return SaveStateDescriptor();
+ }
desc.setThumbnail(thumbnail);
uint32 saveDate = in->readUint32BE();
diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp
index b7c3fa4d6e..912e62d492 100644
--- a/engines/saga/events.cpp
+++ b/engines/saga/events.cpp
@@ -176,7 +176,7 @@ int Events::handleContinuous(Event *event) {
rect.setWidth(w);
rect.setHeight(h);
- _vm->_render->getBackGroundSurface()->transitionDissolve( maskBuffer, rect, 1, event_pc);
+ _vm->_render->getBackGroundSurface()->transitionDissolve(maskBuffer, rect, 1, event_pc);
_vm->_render->setFullRefresh(true);
break;
default:
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index e6b196c4cd..250d2914b7 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -2804,8 +2804,8 @@ void Interface::mapPanelDrawCrossHair() {
if (screen.contains(mapPosition)) {
_vm->_sprite->draw(_vm->_sprite->_mainSprites,
- _mapPanelCrossHairState? RID_ITE_SPR_CROSSHAIR : RID_ITE_SPR_CROSSHAIR + 1,
- mapPosition, 256);
+ _mapPanelCrossHairState ? RID_ITE_SPR_CROSSHAIR : RID_ITE_SPR_CROSSHAIR + 1,
+ mapPosition, 256);
}
}
diff --git a/engines/saga/isomap.cpp b/engines/saga/isomap.cpp
index cff415868e..ae2b458461 100644
--- a/engines/saga/isomap.cpp
+++ b/engines/saga/isomap.cpp
@@ -304,18 +304,8 @@ void IsoMap::adjustScroll(bool jump) {
maxScrollPos.y = playerPoint.y + SAGA_SCROLL_LIMIT_Y2;
if (jump) {
- if (_viewScroll.y < minScrollPos.y) {
- _viewScroll.y = minScrollPos.y;
- }
- if (_viewScroll.y > maxScrollPos.y) {
- _viewScroll.y = maxScrollPos.y;
- }
- if (_viewScroll.x < minScrollPos.x) {
- _viewScroll.x = minScrollPos.x;
- }
- if (_viewScroll.x > maxScrollPos.x) {
- _viewScroll.x = maxScrollPos.x;
- }
+ _viewScroll.x = CLIP(_viewScroll.x, minScrollPos.x, maxScrollPos.x);
+ _viewScroll.y = CLIP(_viewScroll.y, minScrollPos.y, maxScrollPos.y);
} else {
_viewScroll.y = smoothSlide(_viewScroll.y, minScrollPos.y, maxScrollPos.y);
_viewScroll.x = smoothSlide(_viewScroll.x, minScrollPos.x, maxScrollPos.x);
@@ -453,7 +443,7 @@ void IsoMap::drawTiles(const Location *location) {
if (uc != u2 || vc != v2) {
metaTileIndex = 0;
- switch ( _tileMap.edgeType) {
+ switch (_tileMap.edgeType) {
case kEdgeTypeBlack:
continue;
case kEdgeTypeFill0:
@@ -497,7 +487,7 @@ void IsoMap::drawTiles(const Location *location) {
if (uc != u2 || vc != v2) {
metaTileIndex = 0;
- switch ( _tileMap.edgeType) {
+ switch (_tileMap.edgeType) {
case kEdgeTypeBlack:
continue;
case kEdgeTypeFill0:
@@ -750,7 +740,7 @@ void IsoMap::drawTile(uint16 tileIndex, const Point &point, const Location *loca
if (location->z >= 16) {
return;
} else {
- switch (_tilesTable[tileIndex].GetMaskRule()) {
+ switch (_tilesTable[tileIndex].getMaskRule()) {
case kMaskRuleNever:
return;
case kMaskRuleAlways:
@@ -1015,7 +1005,7 @@ int16 IsoMap::getTileIndex(int16 u, int16 v, int16 z) {
if ((uc != mtileU) || (vc != mtileV)) {
metaTileIndex = 0;
- switch ( _tileMap.edgeType) {
+ switch (_tileMap.edgeType) {
case kEdgeTypeBlack:
return 0;
case kEdgeTypeFill0:
@@ -1088,8 +1078,8 @@ void IsoMap::testPossibleDirections(int16 u, int16 v, uint16 terraComp[8], int s
#define TEST_TILE_PROLOG(offsetU, offsetV) \
tile = getTile(u + offsetU, v + offsetV , _platformHeight); \
if (tile != NULL) { \
- fgdMask = tile->GetFGDMask(); \
- bgdMask = tile->GetBGDMask(); \
+ fgdMask = tile->getFGDMask(); \
+ bgdMask = tile->getBGDMask(); \
mask = tile->terrainMask;
#define TEST_TILE_EPILOG(index) \
@@ -1193,7 +1183,7 @@ void IsoMap::placeOnTileMap(const Location &start, Location &result, int16 dista
_platformHeight = _vm->_actor->_protagonist->_location.z / 8;
- memset( &_searchArray, 0, sizeof(_searchArray));
+ memset(&_searchArray, 0, sizeof(_searchArray));
for (ActorDataArray::const_iterator actor = _vm->_actor->_actors.begin(); actor != _vm->_actor->_actors.end(); ++actor) {
if (!actor->_inScene) continue;
@@ -1248,7 +1238,7 @@ void IsoMap::placeOnTileMap(const Location &start, Location &result, int16 dista
}
}
- pushPoint(tilePoint.u + tdir->u,tilePoint.v + tdir->v, tilePoint.cost + tdir->cost, dir);
+ pushPoint(tilePoint.u + tdir->u, tilePoint.v + tdir->v, tilePoint.cost + tdir->cost, dir);
}
}
@@ -1263,35 +1253,35 @@ bool IsoMap::findNearestChasm(int16 &u0, int16 &v0, uint16 &direction) {
v = v0;
for (i = 1; i < 5; i++) {
- if (getTile( u - i, v, 6) == NULL) {
+ if (getTile(u - i, v, 6) == NULL) {
u0 = u - i - 1;
v0 = v;
direction = kDirDownLeft;
return true;
}
- if (getTile( u, v - i, 6) == NULL) {
+ if (getTile(u, v - i, 6) == NULL) {
u0 = u;
v0 = v - i - 1;
direction = kDirDownRight;
return true;
}
- if (getTile( u - i, v - i, 6) == NULL) {
+ if (getTile(u - i, v - i, 6) == NULL) {
u0 = u - i - 1;
v0 = v - i - 1;
direction = kDirDown;
return true;
}
- if (getTile( u + i, v - i, 6) == NULL) {
+ if (getTile(u + i, v - i, 6) == NULL) {
u0 = u + i + 1;
v0 = v - i - 1;
direction = kDirDownRight;
return true;
}
- if (getTile( u - i, v + i, 6) == NULL) {
+ if (getTile(u - i, v + i, 6) == NULL) {
u0 = u + i + 1;
v0 = v - i - 1;
direction = kDirLeft;
@@ -1300,21 +1290,21 @@ bool IsoMap::findNearestChasm(int16 &u0, int16 &v0, uint16 &direction) {
}
for (i = 1; i < 5; i++) {
- if (getTile( u + i, v, 6) == NULL) {
+ if (getTile(u + i, v, 6) == NULL) {
u0 = u + i + 1;
v0 = v;
direction = kDirUpRight;
return true;
}
- if (getTile( u, v + i, 6) == NULL) {
+ if (getTile(u, v + i, 6) == NULL) {
u0 = u;
v0 = v + i + 1;
direction = kDirUpLeft;
return true;
}
- if (getTile( u + i, v + i, 6) == NULL) {
+ if (getTile(u + i, v + i, 6) == NULL) {
u0 = u + i + 1;
v0 = v + i + 1;
direction = kDirUp;
@@ -1324,7 +1314,7 @@ bool IsoMap::findNearestChasm(int16 &u0, int16 &v0, uint16 &direction) {
return false;
}
-void IsoMap::findDragonTilePath(ActorData* actor,const Location &start, const Location &end, uint16 initialDirection) {
+void IsoMap::findDragonTilePath(ActorData* actor, const Location &start, const Location &end, uint16 initialDirection) {
byte *res;
int i;
int16 u;
@@ -1360,7 +1350,7 @@ void IsoMap::findDragonTilePath(ActorData* actor,const Location &start, const Lo
_platformHeight = _vm->_actor->_protagonist->_location.z / 8;
- memset( &_dragonSearchArray, 0, sizeof(_dragonSearchArray));
+ memset(&_dragonSearchArray, 0, sizeof(_dragonSearchArray));
for (u = 0; u < SAGA_DRAGON_SEARCH_DIAMETER; u++) {
for (v = 0; v < SAGA_DRAGON_SEARCH_DIAMETER; v++) {
@@ -1378,8 +1368,8 @@ void IsoMap::findDragonTilePath(ActorData* actor,const Location &start, const Lo
tile = getTile(u1, v1, _platformHeight);
if (tile != NULL) {
mask = tile->terrainMask;
- if (((mask != 0) && (tile->GetFGDAttr() >= kTerrBlock)) ||
- ((mask != 0xFFFF) && (tile->GetBGDAttr() >= kTerrBlock))) {
+ if (((mask != 0 ) && (tile->getFGDAttr() >= kTerrBlock)) ||
+ ((mask != 0xFFFF) && (tile->getBGDAttr() >= kTerrBlock))) {
pcell->visited = 1;
}
} else {
@@ -1390,7 +1380,7 @@ void IsoMap::findDragonTilePath(ActorData* actor,const Location &start, const Lo
first = true;
_queueCount = _readCount = 0;
- pushDragonPoint( SAGA_DRAGON_SEARCH_CENTER, SAGA_DRAGON_SEARCH_CENTER, initialDirection);
+ pushDragonPoint(SAGA_DRAGON_SEARCH_CENTER, SAGA_DRAGON_SEARCH_CENTER, initialDirection);
while (_queueCount != _readCount) {
@@ -1414,40 +1404,40 @@ void IsoMap::findDragonTilePath(ActorData* actor,const Location &start, const Lo
switch (tilePoint->direction) {
case kDirUpRight:
- if (checkDragonPoint( tilePoint->u + 1, tilePoint->v + 0, kDirUpRight)) {
- pushDragonPoint( tilePoint->u + 2, tilePoint->v + 0, kDirUpRight);
- pushDragonPoint( tilePoint->u + 1, tilePoint->v + 1, kDirUpLeft);
- pushDragonPoint( tilePoint->u + 1, tilePoint->v - 1, kDirDownRight);
+ if (checkDragonPoint(tilePoint->u + 1, tilePoint->v + 0, kDirUpRight)) {
+ pushDragonPoint(tilePoint->u + 2, tilePoint->v + 0, kDirUpRight);
+ pushDragonPoint(tilePoint->u + 1, tilePoint->v + 1, kDirUpLeft);
+ pushDragonPoint(tilePoint->u + 1, tilePoint->v - 1, kDirDownRight);
}
break;
case kDirDownRight:
- if (checkDragonPoint( tilePoint->u + 0, tilePoint->v - 1, kDirDownRight)) {
- pushDragonPoint( tilePoint->u + 0, tilePoint->v - 2, kDirDownRight);
- pushDragonPoint( tilePoint->u + 1, tilePoint->v - 1, kDirUpRight);
- pushDragonPoint( tilePoint->u - 1, tilePoint->v - 1, kDirDownLeft);
+ if (checkDragonPoint(tilePoint->u + 0, tilePoint->v - 1, kDirDownRight)) {
+ pushDragonPoint(tilePoint->u + 0, tilePoint->v - 2, kDirDownRight);
+ pushDragonPoint(tilePoint->u + 1, tilePoint->v - 1, kDirUpRight);
+ pushDragonPoint(tilePoint->u - 1, tilePoint->v - 1, kDirDownLeft);
}
break;
case kDirDownLeft:
- if (checkDragonPoint( tilePoint->u - 1, tilePoint->v + 0, kDirDownLeft)) {
- pushDragonPoint( tilePoint->u - 2, tilePoint->v + 0, kDirDownLeft);
- pushDragonPoint( tilePoint->u - 1, tilePoint->v - 1, kDirDownRight);
- pushDragonPoint( tilePoint->u - 1, tilePoint->v + 1, kDirUpLeft);
+ if (checkDragonPoint(tilePoint->u - 1, tilePoint->v + 0, kDirDownLeft)) {
+ pushDragonPoint(tilePoint->u - 2, tilePoint->v + 0, kDirDownLeft);
+ pushDragonPoint(tilePoint->u - 1, tilePoint->v - 1, kDirDownRight);
+ pushDragonPoint(tilePoint->u - 1, tilePoint->v + 1, kDirUpLeft);
}
break;
case kDirUpLeft:
- if (checkDragonPoint( tilePoint->u + 0, tilePoint->v + 1, kDirUpLeft)) {
- pushDragonPoint( tilePoint->u + 0, tilePoint->v + 2, kDirUpLeft);
- pushDragonPoint( tilePoint->u - 1, tilePoint->v + 1, kDirDownLeft);
- pushDragonPoint( tilePoint->u + 1, tilePoint->v + 1, kDirUpRight);
+ if (checkDragonPoint(tilePoint->u + 0, tilePoint->v + 1, kDirUpLeft)) {
+ pushDragonPoint(tilePoint->u + 0, tilePoint->v + 2, kDirUpLeft);
+ pushDragonPoint(tilePoint->u - 1, tilePoint->v + 1, kDirDownLeft);
+ pushDragonPoint(tilePoint->u + 1, tilePoint->v + 1, kDirUpRight);
}
break;
}
if (first && (_queueCount == _readCount)) {
- pushDragonPoint( tilePoint->u + 1, tilePoint->v + 0, kDirUpRight);
- pushDragonPoint( tilePoint->u + 0, tilePoint->v - 1, kDirDownRight);
- pushDragonPoint( tilePoint->u - 1, tilePoint->v + 0, kDirDownLeft);
- pushDragonPoint( tilePoint->u + 0, tilePoint->v + 1, kDirUpLeft);
+ pushDragonPoint(tilePoint->u + 1, tilePoint->v + 0, kDirUpRight);
+ pushDragonPoint(tilePoint->u + 0, tilePoint->v - 1, kDirDownRight);
+ pushDragonPoint(tilePoint->u - 1, tilePoint->v + 0, kDirDownLeft);
+ pushDragonPoint(tilePoint->u + 0, tilePoint->v + 1, kDirUpLeft);
}
first = false;
}
@@ -1517,7 +1507,7 @@ void IsoMap::findTilePath(ActorData* actor, const Location &start, const Locatio
- memset( &_searchArray, 0, sizeof(_searchArray));
+ memset(&_searchArray, 0, sizeof(_searchArray));
if (!(actor->_actorFlags & kActorNoCollide) &&
(_vm->_scene->currentSceneResourceId() != ITE_SCENE_OVERMAP)) {
@@ -1658,7 +1648,7 @@ bool IsoMap::nextTileTarget(ActorData* actor) {
void IsoMap::screenPointToTileCoords(const Point &position, Location &location) {
Point mPos(position);
- int x,y;
+ int x, y;
if (_vm->_scene->currentSceneResourceId() == ITE_SCENE_OVERMAP){
if (mPos.y < 16) {
diff --git a/engines/saga/isomap.h b/engines/saga/isomap.h
index 155d9b8d24..83dfd98b87 100644
--- a/engines/saga/isomap.h
+++ b/engines/saga/isomap.h
@@ -95,20 +95,20 @@ struct IsoTileData {
byte *tilePointer;
uint16 terrainMask;
byte FGDBGDAttr;
- int8 GetMaskRule() const {
+ int8 getMaskRule() const {
return attributes & 0x0F;
}
- byte GetFGDAttr() const {
+ byte getFGDAttr() const {
return FGDBGDAttr >> 4;
}
- byte GetBGDAttr() const {
+ byte getBGDAttr() const {
return FGDBGDAttr & 0x0F;
}
- uint16 GetFGDMask() const {
- return 1 << GetFGDAttr();
+ uint16 getFGDMask() const {
+ return 1 << getFGDAttr();
}
- uint16 GetBGDMask() const {
- return 1 << GetBGDAttr();
+ uint16 getBGDMask() const {
+ return 1 << getBGDAttr();
}
};
diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp
index 1d014052ed..77090860aa 100644
--- a/engines/saga/puzzle.cpp
+++ b/engines/saga/puzzle.cpp
@@ -93,25 +93,25 @@ Puzzle::Puzzle(SagaEngine *vm) : _vm(vm), _solved(false), _active(false) {
_hintSpeaker = 0;
_slidePointX = _slidePointY = 0;
- initPieceInfo( 0, 268, 18, 0, 0, 0 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 3,
- Point(0, 1), Point(0, 62), Point(15, 31), Point(0, 0), Point(0, 0), Point(0,0));
- initPieceInfo( 1, 270, 52, 0, 0, 0 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 4,
+ initPieceInfo(0, 268, 18, 0, 0, 0 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 3,
+ Point(0, 1), Point(0, 62), Point(15, 31), Point(0, 0), Point(0, 0), Point(0, 0));
+ initPieceInfo(1, 270, 52, 0, 0, 0 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 4,
Point(0, 31), Point(0, 47), Point(39, 47), Point(15, 1), Point(0, 0), Point(0, 0));
- initPieceInfo( 2, 19, 51, 0, 0, 0 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ initPieceInfo(2, 19, 51, 0, 0, 0 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
Point(0, 0), Point(23, 46), Point(39, 15), Point(31, 0), Point(0, 0), Point(0, 0));
- initPieceInfo( 3, 73, 0, 0, 0, 32 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 6,
+ initPieceInfo(3, 73, 0, 0, 0, 32 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 6,
Point(0, 0), Point(8, 16), Point(0, 31), Point(31, 31), Point(39, 15), Point(31, 0));
- initPieceInfo( 4, 0, 35, 0, 0, 64 + PUZZLE_X_OFFSET, 16 + PUZZLE_Y_OFFSET, 0, 4,
+ initPieceInfo(4, 0, 35, 0, 0, 64 + PUZZLE_X_OFFSET, 16 + PUZZLE_Y_OFFSET, 0, 4,
Point(0, 15), Point(15, 46), Point(23, 32), Point(7, 1), Point(0, 0), Point(0, 0));
- initPieceInfo( 5, 215, 0, 0, 0, 24 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 6,
+ initPieceInfo(5, 215, 0, 0, 0, 24 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 6,
Point(0, 15), Point(8, 31), Point(39, 31), Point(47, 16), Point(39, 0), Point(8, 0));
- initPieceInfo( 6, 159, 0, 0, 0, 32 + PUZZLE_X_OFFSET, 48 + PUZZLE_Y_OFFSET, 0, 5,
+ initPieceInfo(6, 159, 0, 0, 0, 32 + PUZZLE_X_OFFSET, 48 + PUZZLE_Y_OFFSET, 0, 5,
Point(0, 16), Point(8, 31), Point(55, 31), Point(39, 1), Point(32, 15), Point(0, 0));
- initPieceInfo( 7, 9, 70, 0, 0, 80 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 5,
+ initPieceInfo(7, 9, 70, 0, 0, 80 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 5,
Point(0, 31), Point(8, 47), Point(23, 47), Point(31, 31), Point(15, 1), Point(0, 0));
- initPieceInfo( 8, 288, 18, 0, 0, 96 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ initPieceInfo(8, 288, 18, 0, 0, 96 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
Point(0, 31), Point(15, 62), Point(31, 32), Point(15, 1), Point(0, 0), Point(0, 0));
- initPieceInfo( 9, 112, 0, 0, 0, 112 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
+ initPieceInfo(9, 112, 0, 0, 0, 112 + PUZZLE_X_OFFSET, 0 + PUZZLE_Y_OFFSET, 0, 4,
Point(0, 0), Point(16, 31), Point(47, 31), Point(31, 0), Point(0, 0), Point(0, 0));
initPieceInfo(10, 27, 89, 0, 0, 104 + PUZZLE_X_OFFSET, 32 + PUZZLE_Y_OFFSET, 0, 4,
Point(0, 47), Point(31, 47), Point(31, 0), Point(24, 0), Point(0, 0), Point(0, 0));
diff --git a/engines/saga/resource_hrs.cpp b/engines/saga/resource_hrs.cpp
index ba58830269..9257f65cbc 100644
--- a/engines/saga/resource_hrs.cpp
+++ b/engines/saga/resource_hrs.cpp
@@ -34,7 +34,6 @@
#include "saga/scene.h"
#include "saga/sndres.h"
-#include "engines/advancedDetector.h"
#include "common/endian.h"
namespace Saga {
diff --git a/engines/saga/resource_res.cpp b/engines/saga/resource_res.cpp
index d57238b2eb..a2822f8b33 100644
--- a/engines/saga/resource_res.cpp
+++ b/engines/saga/resource_res.cpp
@@ -32,8 +32,6 @@
#include "saga/scene.h"
#include "saga/sndres.h"
-#include "engines/advancedDetector.h"
-
namespace Saga {
#ifdef ENABLE_IHNM
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 36496e828b..b0d78f753d 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -572,7 +572,7 @@ public:
}
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const;
- const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
virtual bool hasFeature(MetaEngineFeature f) const;
virtual SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const;
@@ -600,7 +600,7 @@ Common::Language charToScummVMLanguage(const char c) {
}
}
-const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ADDetectedGame SciMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
bool foundResMap = false;
bool foundRes000 = false;
@@ -657,7 +657,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
// If these files aren't found, it can't be SCI
if (!foundResMap && !foundRes000)
- return 0;
+ return ADDetectedGame();
ResourceManager resMan(true);
resMan.addAppropriateSourcesForDetection(fslist);
@@ -668,7 +668,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
// Is SCI32 compiled in? If not, and this is a SCI32 game,
// stop here
if (getSciVersionForDetection() >= SCI_VERSION_2)
- return 0;
+ return ADDetectedGame();
#endif
ViewType gameViews = resMan.getViewType();
@@ -677,7 +677,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
// Can't be SCI (or unsupported SCI views). Pinball Creep by Sierra also uses resource.map/resource.000 files
// but doesn't share SCI format at all
if (gameViews == kViewUnknown)
- return 0;
+ return ADDetectedGame();
// Set the platform to Amiga if the game is using Amiga views
if (gameViews == kViewAmiga)
@@ -688,7 +688,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
// If we don't have a game id, the game is not SCI
if (sierraGameId.empty())
- return 0;
+ return ADDetectedGame();
Common::String gameId = convertSierraGameId(sierraGameId, &s_fallbackDesc.flags, resMan);
strncpy(s_fallbackGameIdBuf, gameId.c_str(), sizeof(s_fallbackGameIdBuf) - 1);
@@ -763,7 +763,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const FileMap &allFiles,
s_fallbackDesc.extra = "CD";
}
- return &s_fallbackDesc;
+ return ADDetectedGame(&s_fallbackDesc);
}
bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
@@ -881,7 +881,14 @@ SaveStateDescriptor SciMetaEngine::querySaveMetaInfos(const char *target, int sl
descriptor.setDescription(meta.name);
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*in, thumbnail)) {
+ // invalid
+ delete in;
+
+ descriptor.setDescription("*Invalid*");
+ return descriptor;
+ }
descriptor.setThumbnail(thumbnail);
int day = (meta.saveDate >> 24) & 0xFF;
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 7e63c3576c..3c23cd515f 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -1073,6 +1073,7 @@ reg_t kSetPort(EngineState *s, int argc, reg_t *argv) {
case 7:
initPriorityBandsFlag = true;
+ // fall through
case 6:
picRect.top = argv[0].toSint16();
picRect.left = argv[1].toSint16();
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index 937b1cfc2f..eb4d5d3748 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -1919,7 +1919,7 @@ static int intersectDir(const Vertex *v1, const Vertex *v2) {
// Direction of edge in degrees from pos. x-axis, between -180 and 180
static int edgeDir(const Vertex *v) {
Common::Point p = v->_next->v - v->v;
- int deg = (int)Common::rad2deg((float)atan2((double)p.y, (double)p.x));
+ int deg = Common::rad2deg<float,int>((float)atan2((double)p.y, (double)p.x));
if (deg < -180) deg += 360;
if (deg > 180) deg -= 360;
return deg;
diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp
index aef84e212d..ab56311cd6 100644
--- a/engines/sci/event.cpp
+++ b/engines/sci/event.cpp
@@ -418,7 +418,7 @@ SciEvent EventManager::getSciEvent(SciEventType mask) {
void EventManager::flushEvents() {
Common::EventManager *em = g_system->getEventManager();
Common::Event event;
- while (em->pollEvent(event));
+ while (em->pollEvent(event)) {}
_events.clear();
}
diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp
index 317e98feab..8875162394 100644
--- a/engines/sci/graphics/animate.cpp
+++ b/engines/sci/graphics/animate.cpp
@@ -650,6 +650,11 @@ void GfxAnimate::animateShowPic() {
}
void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv) {
+ // If necessary, delay this kAnimate for a running PalVary.
+ // See delayForPalVaryWorkaround() for details.
+ if (_screen->_picNotValid)
+ _palette->delayForPalVaryWorkaround();
+
byte old_picNotValid = _screen->_picNotValid;
if (getSciVersion() >= SCI_VERSION_1_1)
diff --git a/engines/sci/graphics/celobj32.h b/engines/sci/graphics/celobj32.h
index 02b2859f5c..37e9d39bf5 100644
--- a/engines/sci/graphics/celobj32.h
+++ b/engines/sci/graphics/celobj32.h
@@ -132,6 +132,9 @@ struct CelInfo32 {
default:
assert(!"Should never happen");
}
+ // This code should not be reached but the compiler expects to see a legal
+ // return from a non-void function.
+ return Common::String("here be dragons");
}
};
diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp
index e36028d984..bc0b8485d2 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -716,6 +716,7 @@ void GfxPalette::palVaryInit() {
_palVaryStepStop = 0;
_palVaryDirection = 0;
_palVaryTicks = 0;
+ _palVaryZeroTick = false;
}
bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) {
@@ -759,19 +760,13 @@ bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint1
_palVaryStep = 1;
_palVaryStepStop = stepStop;
_palVaryDirection = direction;
+
// if no ticks are given, jump directly to destination
- if (!_palVaryTicks) {
+ if (!_palVaryTicks)
_palVaryDirection = stepStop;
- // sierra sci set the timer to 1 tick instead of calling it directly
- // we have to change this to prevent a race condition to happen in
- // at least freddy pharkas during nighttime. In that case kPalVary is
- // called right before a transition and because we load pictures much
- // faster, the 1 tick won't pass sometimes resulting in the palette
- // being daytime instead of nighttime during the transition.
- palVaryProcess(1, true);
- } else {
- palVaryInstallTimer();
- }
+ _palVaryZeroTick = (_palVaryTicks == 0); //see delayForPalVaryWorkaround()
+
+ palVaryInstallTimer();
return true;
}
return false;
@@ -788,14 +783,13 @@ int16 GfxPalette::kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direc
_palVaryStepStop = stepStop;
_palVaryDirection = direction != -1 ? -direction : -_palVaryDirection;
- if (!_palVaryTicks) {
+ // if no ticks are given, jump directly to destination
+ if (!_palVaryTicks)
_palVaryDirection = _palVaryStepStop - _palVaryStep;
- // see palVaryInit above, we fix the code here as well
- // just in case
- palVaryProcess(1, true);
- } else {
- palVaryInstallTimer();
- }
+ _palVaryZeroTick = (_palVaryTicks == 0); // see delayForPalVaryWorkaround()
+
+ palVaryInstallTimer();
+
return kernelPalVaryGetCurrentStep();
}
@@ -855,6 +849,7 @@ void GfxPalette::palVaryIncreaseSignal() {
// FIXME: increments from another thread aren't guaranteed to be atomic
if (!_palVaryPaused)
_palVarySignal++;
+ _palVaryZeroTick = false;
}
// Actually do the pal vary processing
@@ -865,6 +860,34 @@ void GfxPalette::palVaryUpdate() {
}
}
+void GfxPalette::delayForPalVaryWorkaround() {
+ if (_palVaryResourceId == -1)
+ return;
+ if (_palVaryPaused)
+ return;
+
+ // This gets called at the very beginning of kAnimate.
+ // If a zero-tick palVary is running, we delay briefly to give the
+ // palVary time to trigger. In theory there should be no reason for this
+ // to have to wait more than a tick, but we time-out after 4 ticks
+ // to be on the safe side.
+ //
+ // This prevents a race condition in Freddy Pharkas during nighttime,
+ // since we load pictures much faster than on original hardware (bug #5298).
+
+ if (_palVaryZeroTick) {
+ int i;
+ for (i = 0; i < 4; ++i) {
+ g_sci->sleep(17);
+ if (!_palVaryZeroTick)
+ break;
+ }
+ debugC(kDebugLevelGraphics, "Delayed kAnimate for kPalVary, %d times", i+1);
+ if (_palVaryZeroTick)
+ warning("Delayed kAnimate for kPalVary timed out");
+ }
+}
+
void GfxPalette::palVaryPrepareForTransition() {
if (_palVaryResourceId != -1) {
// Before doing transitions, we have to prepare palette
diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h
index af74169976..2923df9220 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -88,6 +88,8 @@ public:
void palVaryPrepareForTransition();
void palVaryProcess(int signal, bool setPalette);
+ void delayForPalVaryWorkaround();
+
Palette _sysPalette;
void saveLoadWithSerializer(Common::Serializer &s);
@@ -122,6 +124,7 @@ protected:
uint16 _palVaryTicks;
int _palVaryPaused;
int _palVarySignal;
+ bool _palVaryZeroTick;
uint16 _totalScreenColors;
void loadMacIconBarPalette();
diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp
index 46d08a5997..889a875804 100644
--- a/engines/sci/sound/drivers/midi.cpp
+++ b/engines/sci/sound/drivers/midi.cpp
@@ -143,25 +143,25 @@ public:
MidiPlayer_Midi(SciVersion version);
virtual ~MidiPlayer_Midi();
- int open(ResourceManager *resMan);
- void close();
- void send(uint32 b);
- void sysEx(const byte *msg, uint16 length);
- bool hasRhythmChannel() const { return true; }
- byte getPlayId() const;
- int getPolyphony() const {
+ int open(ResourceManager *resMan) override;
+ void close() override;
+ void send(uint32 b) override;
+ void sysEx(const byte *msg, uint16 length) override;
+ bool hasRhythmChannel() const override { return true; }
+ byte getPlayId() const override;
+ int getPolyphony() const override {
if (g_sci && g_sci->_features->useAltWinGMSound())
return 16;
else
return kVoices;
}
- int getFirstChannel() const;
- int getLastChannel() const;
- void setVolume(byte volume);
+ int getFirstChannel() const override;
+ int getLastChannel() const override;
+ void setVolume(byte volume) override;
virtual void onNewSound() override;
- int getVolume();
- void setReverb(int8 reverb);
- void playSwitch(bool play);
+ int getVolume() override;
+ void setReverb(int8 reverb) override;
+ void playSwitch(bool play) override;
private:
bool isMt32GmPatch(const SciSpan<const byte> &data);
diff --git a/engines/scumm/camera.cpp b/engines/scumm/camera.cpp
index 799fdd7547..5a81057aac 100644
--- a/engines/scumm/camera.cpp
+++ b/engines/scumm/camera.cpp
@@ -25,6 +25,8 @@
#include "scumm/charset.h"
#include "scumm/scumm_v7.h"
+#include "common/util.h"
+
namespace Scumm {
void ScummEngine::setCameraAtEx(int at) {
@@ -85,17 +87,8 @@ void ScummEngine::setCameraFollows(Actor *a, bool setCamera) {
}
void ScummEngine::clampCameraPos(Common::Point *pt) {
- if (pt->x < VAR(VAR_CAMERA_MIN_X))
- pt->x = (short) VAR(VAR_CAMERA_MIN_X);
-
- if (pt->x > VAR(VAR_CAMERA_MAX_X))
- pt->x = (short) VAR(VAR_CAMERA_MAX_X);
-
- if (pt->y < VAR(VAR_CAMERA_MIN_Y))
- pt->y = (short) VAR(VAR_CAMERA_MIN_Y);
-
- if (pt->y > VAR(VAR_CAMERA_MAX_Y))
- pt->y = (short) VAR(VAR_CAMERA_MAX_Y);
+ pt->x = CLIP<short>(pt->x, VAR(VAR_CAMERA_MIN_X), VAR(VAR_CAMERA_MAX_X));
+ pt->y = CLIP<short>(pt->y, VAR(VAR_CAMERA_MIN_Y), VAR(VAR_CAMERA_MAX_Y));
}
void ScummEngine::moveCamera() {
diff --git a/engines/scumm/configure.engine b/engines/scumm/configure.engine
index e8962a371e..42c75226da 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 "" "" "highres"
+add_engine he "HE71+ games" yes "" "" "highres bink"
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 0aa993a53a..fccb30b0fa 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -959,9 +959,9 @@ public:
virtual const char *getOriginalCopyright() const;
virtual bool hasFeature(MetaEngineFeature f) const;
- virtual GameList getSupportedGames() const;
- virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const Common::FSList &fslist) const;
+ PlainGameList getSupportedGames() const override;
+ PlainGameDescriptor findGame(const char *gameid) const override;
+ virtual DetectedGames detectGames(const Common::FSList &fslist) const override;
virtual Common::Error createInstance(OSystem *syst, Engine **engine) const;
@@ -992,11 +992,11 @@ bool ScummEngine::hasFeature(EngineFeature f) const {
(f == kSupportsSubtitleOptions);
}
-GameList ScummMetaEngine::getSupportedGames() const {
- return GameList(gameDescriptions);
+PlainGameList ScummMetaEngine::getSupportedGames() const {
+ return PlainGameList(gameDescriptions);
}
-GameDescriptor ScummMetaEngine::findGame(const char *gameid) const {
+PlainGameDescriptor ScummMetaEngine::findGame(const char *gameid) const {
return Engines::findGameID(gameid, gameDescriptions, obsoleteGameIDsTable);
}
@@ -1026,29 +1026,26 @@ static Common::String generatePreferredTarget(const DetectorResult &x) {
return res;
}
-GameList ScummMetaEngine::detectGames(const Common::FSList &fslist) const {
- GameList detectedGames;
+DetectedGames ScummMetaEngine::detectGames(const Common::FSList &fslist) const {
+ DetectedGames detectedGames;
Common::List<DetectorResult> results;
-
::detectGames(fslist, results, 0);
for (Common::List<DetectorResult>::iterator
x = results.begin(); x != results.end(); ++x) {
const PlainGameDescriptor *g = findPlainGameDescriptor(x->game.gameid, gameDescriptions);
assert(g);
- GameDescriptor dg(x->game.gameid, g->description, x->language, x->game.platform);
- // Append additional information, if set, to the description.
- dg.updateDesc(x->extra);
+ DetectedGame game = DetectedGame(x->game.gameid, g->description, x->language, x->game.platform, x->extra);
// Compute and set the preferred target name for this game.
// Based on generateComplexID() in advancedDetector.cpp.
- dg["preferredtarget"] = generatePreferredTarget(*x);
+ game.preferredTarget = generatePreferredTarget(*x);
- dg.setGUIOptions(x->game.guioptions + MidiDriver::musicType2GUIO(x->game.midi));
- dg.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language));
+ game.setGUIOptions(x->game.guioptions + MidiDriver::musicType2GUIO(x->game.midi));
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language));
- detectedGames.push_back(dg);
+ detectedGames.push_back(game);
}
return detectedGames;
@@ -1324,6 +1321,14 @@ SaveStateDescriptor ScummMetaEngine::querySaveMetaInfos(const char *target, int
}
SaveStateDescriptor desc(slot, saveDesc);
+
+ // Do not allow save slot 0 (used for auto-saving) to be deleted or
+ // overwritten.
+ if (slot == 0) {
+ desc.setWriteProtectedFlag(true);
+ desc.setDeletableFlag(false);
+ }
+
desc.setThumbnail(thumbnail);
if (infoPtr) {
diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h
index 9dee4c8a0b..b2cd760ff4 100644
--- a/engines/scumm/dialogs.h
+++ b/engines/scumm/dialogs.h
@@ -127,15 +127,15 @@ class ValueDisplayDialog : public GUI::Dialog {
public:
ValueDisplayDialog(const Common::String& label, int minVal, int maxVal, int val, uint16 incKey, uint16 decKey);
- virtual void open();
+ virtual void open() override;
void drawDialog(GUI::DrawLayer layerToDraw) override;
- virtual void handleTickle();
- virtual void handleMouseDown(int x, int y, int button, int clickCount) {
+ virtual void handleTickle() override;
+ virtual void handleMouseDown(int x, int y, int button, int clickCount) override {
close();
}
- virtual void handleKeyDown(Common::KeyState state);
+ virtual void handleKeyDown(Common::KeyState state) override;
- virtual void reflowLayout();
+ virtual void reflowLayout() override;
protected:
enum {
diff --git a/engines/scumm/he/moonbase/ai_main.cpp b/engines/scumm/he/moonbase/ai_main.cpp
index c391105658..c5c1f6a8e4 100644
--- a/engines/scumm/he/moonbase/ai_main.cpp
+++ b/engines/scumm/he/moonbase/ai_main.cpp
@@ -2811,9 +2811,9 @@ int AI::simulateBuildingLaunch(int x, int y, int power, int angle, int numSteps,
numSteps = 1;
if (!sXSpeed && !sYSpeed) {
- sZSpeed = (static_cast<int>(.70711 * power)) ;
- sXSpeed = (static_cast<int>(cos(degToRad(angle)) * sZSpeed)) ;
- sYSpeed = (static_cast<int>(sin(degToRad(angle)) * sZSpeed)) ;
+ sZSpeed = (static_cast<int>(.70711 * power));
+ sXSpeed = (static_cast<int>(cos(degToRad(angle)) * sZSpeed));
+ sYSpeed = (static_cast<int>(sin(degToRad(angle)) * sZSpeed));
sZSpeed *= SCALE_Z;
@@ -2959,9 +2959,9 @@ int AI::simulateWeaponLaunch(int x, int y, int power, int angle, int numSteps) {
if (!numSteps) numSteps = 1;
if (!sXSpeed && !sYSpeed) {
- sZSpeed = (static_cast<int>(.70711 * power)) ;
- sXSpeed = (static_cast<int>(cos(degToRad(angle)) * sZSpeed)) ;
- sYSpeed = (static_cast<int>(sin(degToRad(angle)) * sZSpeed)) ;
+ sZSpeed = (static_cast<int>(.70711 * power));
+ sXSpeed = (static_cast<int>(cos(degToRad(angle)) * sZSpeed));
+ sYSpeed = (static_cast<int>(sin(degToRad(angle)) * sZSpeed));
sZSpeed *= SCALE_Z;
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp
index 5de921bc6b..f5526ab11d 100644
--- a/engines/scumm/imuse/imuse.cpp
+++ b/engines/scumm/imuse/imuse.cpp
@@ -1236,11 +1236,8 @@ int32 IMuseInternal::ImSetTrigger(int sound, int id, int a, int b, int c, int d,
if (trig->id == id && trig->sound == sound && trig->command[0] == a)
break;
- uint16 diff;
- if (trig->expire <= _snm_trigger_index)
- diff = _snm_trigger_index - trig->expire;
- else
- diff = 0x10000 - trig->expire + _snm_trigger_index;
+ // The wraparound if trig->expire > _snm_trigger_index is intentional
+ uint16 diff = _snm_trigger_index - trig->expire;
if (!oldest_ptr || oldest_trigger < diff) {
oldest_ptr = trig;
diff --git a/engines/scumm/imuse_digi/dimuse_track.h b/engines/scumm/imuse_digi/dimuse_track.h
index a007903139..ef0a8adb21 100644
--- a/engines/scumm/imuse_digi/dimuse_track.h
+++ b/engines/scumm/imuse_digi/dimuse_track.h
@@ -66,7 +66,7 @@ struct Track {
int32 curRegion; // id of current used region
int32 curHookId; // id of current used hook id
int32 volGroupId; // id of volume group (IMUSE_VOLGRP_VOICE, IMUSE_VOLGRP_SFX, IMUSE_VOLGRP_MUSIC)
- int32 soundType; // type of sound data (kSpeechSoundType, kSFXSoundType, kMusicSoundType)
+ int32 soundType; // type of sound data (IMUSE_BUNDLE, IMUSE_RESOURCE)
int32 feedSize; // size of sound data needed to be filled at each callback iteration
int32 dataMod12Bit; // value used between all callback to align 12 bit source of data
int32 mixerFlags; // flags for sound mixer's channel (kFlagStereo, kFlag16Bits, kFlagUnsigned)
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 6ef7e4d7f4..9c5271e51c 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -560,7 +560,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
} else if (pauseKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_SPACE && lastKeyHit.hasFlags(0))) {
pauseGame();
- } else if (talkstopKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_PERIOD && lastKeyHit.hasFlags(0))) {
+ } else if (talkstopKeyEnabled && lastKeyHit.ascii == '.') {
_talkDelay = 0;
if (_sound->_sfxMode & 2)
stopTalk();
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index f4aea93b8b..df0b3e1035 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -45,6 +45,7 @@ void ScummEngine::addObjectToInventory(uint obj, uint room) {
idx = getObjectIndex(obj);
assert(idx >= 0);
ptr = getResourceAddress(rtFlObject, _objs[idx].fl_object_index) + 8;
+ assert(ptr);
size = READ_BE_UINT32(ptr + 4);
} else {
findObjectInRoom(&foir, foCodeHeader, obj, room);
@@ -742,6 +743,7 @@ void ScummEngine::resetRoomObjects() {
const CodeHeader *cdhd;
room = getResourceAddress(rtRoom, _roomResource);
+ assert(room);
if (_numObjectsInRoom == 0)
return;
@@ -756,7 +758,7 @@ void ScummEngine::resetRoomObjects() {
assert(searchptr);
// Load in new room objects
- ResourceIterator obcds(searchptr, false);
+ ResourceIterator obcds(searchptr, false);
for (i = 0; i < _numObjectsInRoom; i++) {
od = &_objs[findLocalObjectSlot()];
@@ -784,7 +786,7 @@ void ScummEngine::resetRoomObjects() {
}
searchptr = room;
- ResourceIterator obims(room, false);
+ ResourceIterator obims(room, false);
for (i = 0; i < _numObjectsInRoom; i++) {
ptr = obims.findNext(MKTAG('O','B','I','M'));
if (ptr == NULL)
@@ -810,6 +812,7 @@ void ScummEngine_v3old::resetRoomObjects() {
const byte *room, *ptr;
room = getResourceAddress(rtRoom, _roomResource);
+ assert(room);
if (_numObjectsInRoom == 0)
return;
@@ -854,6 +857,7 @@ void ScummEngine_v4::resetRoomObjects() {
const byte *room;
room = getResourceAddress(rtRoom, _roomResource);
+ assert(room);
if (_numObjectsInRoom == 0)
return;
@@ -861,7 +865,7 @@ void ScummEngine_v4::resetRoomObjects() {
if (_numObjectsInRoom > _numLocalObjects)
error("More than %d objects in room %d", _numLocalObjects, _roomResource);
- ResourceIterator obcds(room, true);
+ ResourceIterator obcds(room, true);
for (i = 0; i < _numObjectsInRoom; i++) {
od = &_objs[findLocalObjectSlot()];
@@ -878,7 +882,7 @@ void ScummEngine_v4::resetRoomObjects() {
}
}
- ResourceIterator obims(room, true);
+ ResourceIterator obims(room, true);
for (i = 0; i < _numObjectsInRoom; i++) {
// In the PC Engine version of Loom, there aren't image blocks
// for all objects.
@@ -979,10 +983,12 @@ void ScummEngine::resetRoomObject(ObjectData *od, const byte *room, const byte *
assert(room);
if (searchptr == NULL) {
- if (_game.version == 8)
+ if (_game.version == 8) {
searchptr = getResourceAddress(rtRoomScripts, _roomResource);
- else
+ assert(searchptr);
+ } else {
searchptr = room;
+ }
}
cdhd = (const CodeHeader *)findResourceData(MKTAG('C','D','H','D'), searchptr + od->OBCDoffset);
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index 7f0f449a92..40f4ec93c9 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -97,6 +97,7 @@ void Player_AD::startSound(int sound) {
// Query the sound resource
const byte *res = _vm->getResourceAddress(rtSound, sound);
+ assert(res);
if (res[2] == 0x80) {
// Stop the current sounds
diff --git a/engines/scumm/players/player_nes.cpp b/engines/scumm/players/player_nes.cpp
index 3b5adc4550..b2f6eb0d40 100644
--- a/engines/scumm/players/player_nes.cpp
+++ b/engines/scumm/players/player_nes.cpp
@@ -1029,11 +1029,7 @@ top:
}
_mchan[x].volume += _mchan[x].voldelta;
-
- if (_mchan[x].volume < 0)
- _mchan[x].volume = 0;
- if (_mchan[x].volume > MAXVOLUME)
- _mchan[x].volume = MAXVOLUME;
+ _mchan[x].volume = CLIP(_mchan[x].volume, 0, MAXVOLUME);
APU_writeChannel(x, 0, (_mchan[x].volume >> 3) | _mchan[x].envflags);
}
diff --git a/engines/scumm/players/player_towns.cpp b/engines/scumm/players/player_towns.cpp
index 16080205c0..a1add906bb 100644
--- a/engines/scumm/players/player_towns.cpp
+++ b/engines/scumm/players/player_towns.cpp
@@ -236,6 +236,8 @@ void Player_Towns_v1::setMusicVolume(int vol) {
void Player_Towns_v1::startSound(int sound) {
uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
+ assert(ptr);
+
if (_vm->_game.version != 3)
ptr += 2;
@@ -620,6 +622,7 @@ int Player_Towns_v2::getSoundStatus(int sound) const {
void Player_Towns_v2::startSound(int sound) {
uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
+ assert(ptr);
if (READ_BE_UINT32(ptr) == MKTAG('T','O','W','S')) {
_soundOverride[sound].type = 7;
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index d04b3bb5ad..84dd16efa6 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -706,7 +706,9 @@ bool ScummEngine::querySaveMetaInfos(const char *target, int slot, int heversion
if (hdr.ver > VER(52)) {
if (Graphics::checkThumbnailHeader(*in)) {
- thumbnail = Graphics::loadThumbnail(*in);
+ if (!Graphics::loadThumbnail(*in, thumbnail)) {
+ return false;
+ }
}
if (hdr.ver > VER(57)) {
diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp
index 822e32d9c4..208b1f4aef 100644
--- a/engines/scumm/script_v2.cpp
+++ b/engines/scumm/script_v2.cpp
@@ -1188,7 +1188,7 @@ void ScummEngine_v2::o2_startScript() {
}
}
- // WORKAROUND bug #4556: Purple Tentacle can appear in the lab, after being
+ // WORKAROUND bug #4556: Purple Tentacle can appear in the lab, after being
// chased out and end up stuck in the room. This bug is triggered if the player
// enters the lab within 45 minutes of first entering the mansion and has chased Purple Tentacle
// out. Eventually the cutscene with Purple Tentacle chasing Sandy in the lab
@@ -1211,10 +1211,9 @@ void ScummEngine_v2::o2_startScript() {
}
void ScummEngine_v2::stopScriptCommon(int script) {
-
// WORKAROUND bug #4112: If you enter the lab while Dr. Fred has the powered turned off
// to repair the Zom-B-Matic, the script will be stopped and the power will never turn
- // back on. This fix forces the power on, when the player enters the lab,
+ // back on. This fix forces the power on, when the player enters the lab,
// if the script which turned it off is running
if (_game.id == GID_MANIAC && _roomResource == 4 && isScriptRunning(MM_SCRIPT(138))) {
@@ -1320,7 +1319,7 @@ void ScummEngine_v2::o2_putActorInRoom() {
// Var[245] is set to have the Disguise on in most situations
//
// We don't touch the variable in the following situations
- // If the Caponian is being put into the space ship room, or the current room is the
+ // If the Caponian is being put into the space ship room, or the current room is the
// space ship and the Caponian is being put into the backroom of the telephone company (you didnt show your fan club card)
if (_game.id == GID_ZAK && _game.version <= 2 && act == 7) {
// Is script-96 cutscene done
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index fc64df4a1a..2f6ea489d5 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2435,6 +2435,9 @@ void ScummEngine::scummLoop_handleSaveLoad() {
if (success && _saveTemporaryState && VAR_GAME_LOADED != 0xFF && _game.version <= 7)
VAR(VAR_GAME_LOADED) = 201;
+
+ if (!_saveTemporaryState)
+ _lastSaveTime = _system->getMillis();
} else {
success = loadState(_saveLoadSlot, _saveTemporaryState, filename);
if (!success)
@@ -2458,7 +2461,6 @@ void ScummEngine::scummLoop_handleSaveLoad() {
clearClickedStatus();
_saveLoadFlag = 0;
- _lastSaveTime = _system->getMillis();
}
}
diff --git a/engines/sherlock/detection.cpp b/engines/sherlock/detection.cpp
index 9184fd8e88..e72700fbf2 100644
--- a/engines/sherlock/detection.cpp
+++ b/engines/sherlock/detection.cpp
@@ -200,6 +200,8 @@ bool SherlockMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSupportsDeleteSave) ||
(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
+ (f == kSavesSupportCreationDate) ||
+ (f == kSavesSupportPlayTime) ||
(f == kSimpleSavesNames);
}
@@ -233,7 +235,10 @@ SaveStateDescriptor SherlockMetaEngine::querySaveMetaInfos(const char *target, i
if (f) {
Sherlock::SherlockSavegameHeader header;
- Sherlock::SaveManager::readSavegameHeader(f, header);
+ if (!Sherlock::SaveManager::readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
delete f;
// Create the return descriptor
diff --git a/engines/sherlock/image_file.cpp b/engines/sherlock/image_file.cpp
index c53e537bb8..112655648a 100644
--- a/engines/sherlock/image_file.cpp
+++ b/engines/sherlock/image_file.cpp
@@ -703,7 +703,7 @@ void ImageFile3DO::load3DOCelRoomData(Common::SeekableReadStream &stream) {
error("load3DOCelRoomData: expected cel data, not enough bytes");
// read data into memory
- byte *celDataPtr = new byte[celDataSize];
+ byte *celDataPtr = new byte[celDataSize];
stream.read(celDataPtr, celDataSize);
streamLeft -= celDataSize;
@@ -936,15 +936,15 @@ void ImageFile3DO::loadFont(Common::SeekableReadStream &stream) {
stream.read(bitsTablePtr, bitsTableSize);
// Now extract all characters
- uint16 curChar = 0;
- const byte *curBitsLinePtr = bitsTablePtr;
- const byte *curBitsPtr = NULL;
- byte curBitsLeft = 0;
- uint32 curCharHeightLeft = 0;
- uint32 curCharWidthLeft = 0;
- byte curBits = 0;
- byte curBitsReversed = 0;
- byte curPosX = 0;
+ uint16 curChar = 0;
+ const byte *curBitsLinePtr = bitsTablePtr;
+ const byte *curBitsPtr = NULL;
+ byte curBitsLeft = 0;
+ uint32 curCharHeightLeft = 0;
+ uint32 curCharWidthLeft = 0;
+ byte curBits = 0;
+ byte curBitsReversed = 0;
+ byte curPosX = 0;
assert(bitsTableSize >= (header_maxChar * header_fontHeight * header_bytesPerLine)); // Security
diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index cef7157034..20b811ea98 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -182,8 +182,8 @@ bool MidiParser_SH::loadMusic(byte *musData, uint32 musDataSize) {
_musData = musData;
_musDataSize = musDataSize;
- byte *headerPtr = _musData + 12; // skip over the already checked SPACE header
- byte *pos = headerPtr;
+ byte *headerPtr = _musData + 12; // skip over the already checked SPACE header
+ byte *pos = headerPtr;
uint16 headerSize = READ_LE_UINT16(headerPtr);
assert(headerSize == 0x7F); // Security check
diff --git a/engines/sherlock/objects.h b/engines/sherlock/objects.h
index 25ccddedbb..6f1148e956 100644
--- a/engines/sherlock/objects.h
+++ b/engines/sherlock/objects.h
@@ -470,7 +470,7 @@ struct SceneImage {
int _filesize; // File size
SceneImage();
-} ;
+};
} // End of namespace Sherlock
diff --git a/engines/sherlock/resources.cpp b/engines/sherlock/resources.cpp
index 9ed6951fbe..ec7d60a1a2 100644
--- a/engines/sherlock/resources.cpp
+++ b/engines/sherlock/resources.cpp
@@ -57,23 +57,24 @@ void Cache::load(const Common::String &name, Common::SeekableReadStream &stream)
int32 signature = stream.readUint32BE();
stream.seek(0);
-
- // Check whether the file is compressed
- if (signature == MKTAG('L', 'Z', 'V', 26)) {
- // Allocate a new cache entry
- _resources[name] = CacheEntry();
- CacheEntry &cacheEntry = _resources[name];
+ // Allocate a new cache entry
+ _resources[name] = CacheEntry();
+ CacheEntry &cacheEntry = _resources[name];
+ // Check whether the file is compressed
+ if (signature == MKTAG('L', 'Z', 'V', 26)) {
// It's compressed, so decompress the file and store its data in the cache entry
Common::SeekableReadStream *decompressed = _vm->_res->decompress(stream);
cacheEntry.resize(decompressed->size());
decompressed->read(&cacheEntry[0], decompressed->size());
delete decompressed;
-
+ } else {
+ // It's not, so read the raw data of the file into the cache entry
+ cacheEntry.resize(stream.size());
+ stream.read(&cacheEntry[0], stream.size());
}
-
}
Common::SeekableReadStream *Cache::get(const Common::String &filename) const {
diff --git a/engines/sherlock/saveload.cpp b/engines/sherlock/saveload.cpp
index 44b5e103d2..ca27f57a97 100644
--- a/engines/sherlock/saveload.cpp
+++ b/engines/sherlock/saveload.cpp
@@ -93,7 +93,6 @@ SaveStateList SaveManager::getSavegameList(const Common::String &target) {
SherlockSavegameHeader 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) {
@@ -104,24 +103,20 @@ SaveStateList SaveManager::getSavegameList(const Common::String &target) {
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
- if (!readSavegameHeader(in, header))
- continue;
+ if (readSavegameHeader(in, header))
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
- saveList.push_back(SaveStateDescriptor(slot, header._saveName));
-
- header._thumbnail->free();
- delete header._thumbnail;
delete in;
}
}
}
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
-bool SaveManager::readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header) {
+WARN_UNUSED_RESULT bool SaveManager::readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
- header._thumbnail = nullptr;
// Validate the header Id
in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
@@ -138,9 +133,9 @@ bool SaveManager::readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHea
while ((ch = (char)in->readByte()) != '\0') header._saveName += ch;
// Get the thumbnail
- header._thumbnail = Graphics::loadThumbnail(*in);
- if (!header._thumbnail)
+ if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
header._year = in->readSint16LE();
@@ -212,11 +207,6 @@ void SaveManager::loadGame(int slot) {
if (!readSavegameHeader(saveFile, header))
error("Invalid savegame");
- if (header._thumbnail) {
- header._thumbnail->free();
- delete header._thumbnail;
- }
-
// Synchronize the savegame data
Serializer s(saveFile, nullptr);
s.setVersion(header._version);
diff --git a/engines/sherlock/saveload.h b/engines/sherlock/saveload.h
index 59b0b26d6e..6348b0f668 100644
--- a/engines/sherlock/saveload.h
+++ b/engines/sherlock/saveload.h
@@ -105,7 +105,7 @@ public:
/**
* Read in the header information for a savegame
*/
- static bool readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, SherlockSavegameHeader &header, bool skipThumbnail = true);
/**
* Return the index of the button the mouse is over, if any
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index 2aa6ae8902..fbe025c0b7 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -258,8 +258,8 @@ void ScalpelEngine::setupGraphics() {
// First try for a 640x400 mode
g_system->beginGFXTransaction();
- initCommonGFX();
- g_system->initSize(640, 400, &pixelFormatRGB565);
+ initCommonGFX();
+ g_system->initSize(640, 400, &pixelFormatRGB565);
OSystem::TransactionError gfxError = g_system->endGFXTransaction();
if (gfxError == OSystem::kTransactionSuccess) {
diff --git a/engines/sherlock/sherlock.cpp b/engines/sherlock/sherlock.cpp
index c6b38f78d7..fcc092f017 100644
--- a/engines/sherlock/sherlock.cpp
+++ b/engines/sherlock/sherlock.cpp
@@ -137,9 +137,9 @@ Common::Error SherlockEngine::run() {
_saves->loadGame(_loadGameSlot);
_loadGameSlot = -1;
} else {
- do
+ do {
showOpening();
- while (!shouldQuit() && !_interactiveFl);
+ } while (!shouldQuit() && !_interactiveFl);
}
while (!shouldQuit()) {
diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp
index fc3c2e6574..458cc1a9c2 100644
--- a/engines/sherlock/tattoo/tattoo_people.cpp
+++ b/engines/sherlock/tattoo/tattoo_people.cpp
@@ -39,7 +39,7 @@ struct AdjustWalk {
int _xAdjust;
int _flipXAdjust;
int _yAdjust;
-} ;
+};
static const AdjustWalk ADJUST_WALKS[NUM_ADJUSTED_WALKS] = {
{ "TUPRIGHT", -7, -19, 6 },
diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp
index b5425f9532..642e4d31a7 100644
--- a/engines/sky/detection.cpp
+++ b/engines/sky/detection.cpp
@@ -76,10 +76,10 @@ public:
virtual const char *getOriginalCopyright() const;
virtual bool hasFeature(MetaEngineFeature f) const;
- virtual GameList getSupportedGames() const;
+ PlainGameList getSupportedGames() const override;
virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const;
- virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const Common::FSList &fslist) const;
+ PlainGameDescriptor findGame(const char *gameid) const override;
+ DetectedGames detectGames(const Common::FSList &fslist) const override;
virtual Common::Error createInstance(OSystem *syst, Engine **engine) const;
@@ -110,8 +110,8 @@ bool Sky::SkyEngine::hasFeature(EngineFeature f) const {
(f == kSupportsSavingDuringRuntime);
}
-GameList SkyMetaEngine::getSupportedGames() const {
- GameList games;
+PlainGameList SkyMetaEngine::getSupportedGames() const {
+ PlainGameList games;
games.push_back(skySetting);
return games;
}
@@ -135,14 +135,14 @@ const ExtraGuiOptions SkyMetaEngine::getExtraGuiOptions(const Common::String &ta
return options;
}
-GameDescriptor SkyMetaEngine::findGame(const char *gameid) const {
+PlainGameDescriptor SkyMetaEngine::findGame(const char *gameid) const {
if (0 == scumm_stricmp(gameid, skySetting.gameId))
return skySetting;
- return GameDescriptor();
+ return PlainGameDescriptor::empty();
}
-GameList SkyMetaEngine::detectGames(const Common::FSList &fslist) const {
- GameList detectedGames;
+DetectedGames SkyMetaEngine::detectGames(const Common::FSList &fslist) const {
+ DetectedGames detectedGames;
bool hasSkyDsk = false;
bool hasSkyDnr = false;
int dinnerTableEntries = -1;
@@ -173,18 +173,25 @@ 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);
const SkyVersion *sv = skyVersions;
while (sv->dinnerTableEntries) {
if (dinnerTableEntries == sv->dinnerTableEntries &&
(sv->dataDiskSize == dataDiskSize || sv->dataDiskSize == -1)) {
- dg.updateDesc(Common::String::format("v0.0%d %s", sv->version, sv->extraDesc).c_str());
- dg.setGUIOptions(sv->guioptions);
break;
}
++sv;
}
- detectedGames.push_back(dg);
+
+ if (sv->dinnerTableEntries) {
+ Common::String extra = Common::String::format("v0.0%d %s", sv->version, sv->extraDesc);
+
+ DetectedGame game = DetectedGame(skySetting.gameId, skySetting.description, Common::UNK_LANG, Common::kPlatformUnknown, extra);
+ game.setGUIOptions(sv->guioptions);
+
+ detectedGames.push_back(game);
+ } else {
+ detectedGames.push_back(DetectedGame(skySetting.gameId, skySetting.description));
+ }
}
return detectedGames;
diff --git a/engines/sludge/backdrop.cpp b/engines/sludge/backdrop.cpp
index c1042c7f05..0e41230f36 100644
--- a/engines/sludge/backdrop.cpp
+++ b/engines/sludge/backdrop.cpp
@@ -422,6 +422,7 @@ void GraphicsManager::saveLightMap(Common::WriteStream *stream) {
stream->writeByte(0);
}
stream->writeByte(_lightMapMode);
+ stream->writeByte(_fadeMode);
}
bool GraphicsManager::loadLightMap(int ssgVersion, Common::SeekableReadStream *stream) {
@@ -434,6 +435,8 @@ bool GraphicsManager::loadLightMap(int ssgVersion, Common::SeekableReadStream *s
_lightMapMode = stream->readByte() % 3;
}
+ _fadeMode = stream->readByte();
+
return true;
}
@@ -504,6 +507,27 @@ void GraphicsManager::saveHSI(Common::WriteStream *stream) {
Image::writePNG(*stream, _backdropSurface);
}
+void GraphicsManager::saveBackdrop(Common::WriteStream *stream) {
+ stream->writeUint16BE(_cameraX);
+ stream->writeUint16BE(_cameraY);
+ stream->writeFloatLE(_cameraZoom);
+ stream->writeByte(_brightnessLevel);
+ saveHSI(stream);
+}
+
+void GraphicsManager::loadBackdrop(int ssgVersion, Common::SeekableReadStream *stream) {
+ _cameraX = stream->readUint16BE();
+ _cameraY = stream->readUint16BE();
+ if (ssgVersion >= VERSION(2, 0)) {
+ _cameraZoom = stream->readFloatLE();
+ } else {
+ _cameraZoom = 1.0;
+ }
+
+ _brightnessLevel = stream->readByte();
+
+ loadHSI(stream, 0, 0, true);
+}
bool GraphicsManager::getRGBIntoStack(uint x, uint y, StackHandler *sH) {
if (x >= _sceneWidth || y >= _sceneHeight) {
@@ -516,14 +540,14 @@ bool GraphicsManager::getRGBIntoStack(uint x, uint y, StackHandler *sH) {
byte *target = (byte *)_renderSurface.getBasePtr(x, y);
- setVariable(newValue, SVT_INT, target[1]);
+ newValue.setVariable(SVT_INT, target[1]);
if (!addVarToStackQuick(newValue, sH->first)) return false;
sH->last = sH->first;
- setVariable(newValue, SVT_INT, target[2]);
+ newValue.setVariable(SVT_INT, target[2]);
if (!addVarToStackQuick(newValue, sH->first)) return false;
- setVariable(newValue, SVT_INT, target[3]);
+ newValue.setVariable(SVT_INT, target[3]);
if (!addVarToStackQuick(newValue, sH->first)) return false;
return true;
diff --git a/engines/sludge/bg_effects.cpp b/engines/sludge/bg_effects.cpp
index d0c8068a27..3f40fc81e1 100644
--- a/engines/sludge/bg_effects.cpp
+++ b/engines/sludge/bg_effects.cpp
@@ -166,7 +166,7 @@ bool blur_createSettings(int numParams, VariableStack *&stack) {
error = "Third and subsequent parameters in setBackgroundEffect should be arrays";
break;
} else {
- int w = stackSize(justToCheckSizes->thisVar.varData.theStack);
+ int w = justToCheckSizes->thisVar.varData.theStack->getStackSize();
if (a) {
if (w != width) {
error = "Arrays in setBackgroundEffect must be the same size";
@@ -196,7 +196,7 @@ bool blur_createSettings(int numParams, VariableStack *&stack) {
for (int x = 0; x < width; x++) {
int arraySlot = x + (y * width);
// s_matrixEffectData[arraySlot] = (rand() % 4);
- if (!getValueType(s_matrixEffectData[arraySlot], SVT_INT, eachNumber->thisVar)) {
+ if (!eachNumber->thisVar.getValueType(s_matrixEffectData[arraySlot], SVT_INT)) {
error = "";
break;
}
@@ -205,10 +205,10 @@ bool blur_createSettings(int numParams, VariableStack *&stack) {
trimStack(stack);
}
}
- if (error.empty() && !getValueType(s_matrixEffectDivide, SVT_INT, stack->thisVar))
+ if (error.empty() && !stack->thisVar.getValueType(s_matrixEffectDivide, SVT_INT))
error = "";
trimStack(stack);
- if (error.empty() && !getValueType(s_matrixEffectBase, SVT_INT, stack->thisVar))
+ if (error.empty() && !stack->thisVar.getValueType(s_matrixEffectBase, SVT_INT))
error = "";
trimStack(stack);
if (error.empty()) {
diff --git a/engines/sludge/builtin.cpp b/engines/sludge/builtin.cpp
index 7385d4d861..1030643788 100644
--- a/engines/sludge/builtin.cpp
+++ b/engines/sludge/builtin.cpp
@@ -32,6 +32,7 @@
#include "sludge/floor.h"
#include "sludge/fonttext.h"
#include "sludge/freeze.h"
+#include "sludge/function.h"
#include "sludge/graphics.h"
#include "sludge/language.h"
#include "sludge/loadsave.h"
@@ -54,51 +55,16 @@
namespace Sludge {
-int speechMode = 0;
-SpritePalette pastePalette;
-
Variable *launchResult = NULL;
-extern int lastFramesPerSecond, thumbWidth, thumbHeight;
extern bool allowAnyFilename;
-extern bool captureAllKeys;
extern VariableStack *noStack;
extern StatusStuff *nowStatus;
-extern ScreenRegion *overRegion;
extern int numBIFNames, numUserFunc;
extern Common::String *allUserFunc;
extern Common::String *allBIFNames;
-extern byte brightnessLevel;
-extern byte fadeMode;
-extern uint16 saveEncoding;
-
-int paramNum[] = { -1, 0, 1, 1, -1, -1, 1, 3, 4, 1, 0, 0, 8, -1, // SAY->MOVEMOUSE
- -1, 0, 0, -1, -1, 1, 1, 1, 1, 4, 1, 1, 2, 1,// FOCUS->REMOVEREGION
- 2, 2, 0, 0, 2, // ANIMATE->SETSCALE
- -1, 2, 1, 0, 0, 0, 1, 0, 3, // new/push/pop stack, status stuff
- 2, 0, 0, 3, 1, 0, 2, // delFromStack->completeTimers
- -1, -1, -1, 2, 2, 0, 3, 1, // anim, costume, pO, setC, wait, sS, substring, stringLength
- 0, 1, 1, 0, 2, // dark, save, load, quit, rename
- 1, 3, 3, 1, 2, 1, 1, 3, 1, 0, 0, 2, 1, // stackSize, pasteString, startMusic, defvol, vol, stopmus, stopsound, setfont, alignStatus, show x 2, pos'Status, setFloor
- -1, -1, 1, 1, 2, 1, 1, 1, -1, -1, -1, 1, 1, // force, jump, peekstart, peekend, enqueue, getSavedGames, inFont, loopSound, removeChar, stopCharacter
- 1, 0, 3, 3, 1, 2, 1, 2, 2, // launch, howFrozen, pastecol, litcol, checksaved, float, cancelfunc, walkspeed, delAll
- 2, 3, 1, 2, 2, 0, 0, 1, 2, 3, 1, -1, // extras, mixoverlay, pastebloke, getMScreenX/Y, setSound(Default/-)Volume, looppoints, speechMode, setLightMap
- -1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, // think, getCharacterDirection, is(char/region/moving), deleteGame, renameGame, hardScroll, stringWidth, speechSpeed, normalCharacter
- 2, 1, 2, 1, 3, 1, 1, 2, 1, // fetchEvent, setBrightness, spin, fontSpace, burnString, captureAll, cacheSound, setSpinSpeed, transitionMode
- 1, 0, 0, 1, 0, 2, 1, 1, 1, // movie(Start/Abort/Playing), updateDisplay, getSoundCache, savedata, loaddata, savemode, freeSound
- 3, 0, 3, 3, 2, 1, 1, // setParallax, clearParallax, setBlankColour, setBurnColour, getPixelColour, makeFastArray, getCharacterScale
- 0, 2, 0, // getLanguage, launchWith, getFramesPerSecond
- 3, 2, 2, 0, 0, 1, // readThumbnail, setThumbnailSize, hasFlag, snapshot, clearSnapshot, anyFilename
- 2, 1, // regGet, fatal
- 4, 3, -1, 0, // chr AA, max AA, setBackgroundEffect, doBackgroundEffect
- 2, // setCharacterAngleOffset
- 2, 5, // setCharacterTransparency, setCharacterColourise
- 1, // zoomCamera
- 1, 0, 0 // playMovie, stopMovie, pauseMovie
- };
-
bool failSecurityCheck(const Common::String &fn) {
if (fn.empty())
return true;
@@ -121,11 +87,12 @@ bool failSecurityCheck(const Common::String &fn) {
return false;
}
-LoadedFunction *saverFunc;
+extern LoadedFunction *saverFunc;
typedef BuiltReturn (*builtInSludgeFunc)(int numParams, LoadedFunction *fun);
struct builtInFunctionData {
builtInSludgeFunc func;
+ int paramNum;
};
#define builtIn(a) static BuiltReturn builtIn_ ## a (int numParams, LoadedFunction *fun)
@@ -140,15 +107,15 @@ static BuiltReturn sayCore(int numParams, LoadedFunction *fun, bool sayIt) {
switch (numParams) {
case 3:
- if (!getValueType(fileNum, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNum, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
// fall through
case 2:
- newText = getTextFromAnyVar(fun->stack->thisVar);
+ newText = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
- if (!getValueType(objT, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objT, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
p = g_sludge->_speechMan->wrapSpeech(newText, objT, fileNum, sayIt);
@@ -192,13 +159,13 @@ builtIn(unfreeze) {
builtIn(howFrozen) {
UNUSEDALL
- setVariable(fun->reg, SVT_INT, g_sludge->_gfxMan->howFrozen());
+ fun->reg.setVariable(SVT_INT, g_sludge->_gfxMan->howFrozen());
return BR_CONTINUE;
}
builtIn(setCursor) {
UNUSEDALL
- PersonaAnimation *aa = getAnimationFromVar(fun->stack->thisVar);
+ PersonaAnimation *aa = fun->stack->thisVar.getAnimationFromVar();
g_sludge->_cursorMan->pickAnimCursor(aa);
trimStack(fun->stack);
return BR_CONTINUE;
@@ -206,39 +173,39 @@ builtIn(setCursor) {
builtIn(getMouseX) {
UNUSEDALL
- setVariable(fun->reg, SVT_INT, g_sludge->_evtMan->mouseX() + g_sludge->_gfxMan->getCamX());
+ fun->reg.setVariable(SVT_INT, g_sludge->_evtMan->mouseX() + g_sludge->_gfxMan->getCamX());
return BR_CONTINUE;
}
builtIn(getMouseY) {
UNUSEDALL
- setVariable(fun->reg, SVT_INT, g_sludge->_evtMan->mouseY() + g_sludge->_gfxMan->getCamY());
+ fun->reg.setVariable(SVT_INT, g_sludge->_evtMan->mouseY() + g_sludge->_gfxMan->getCamY());
return BR_CONTINUE;
}
builtIn(getMouseScreenX) {
UNUSEDALL
- setVariable(fun->reg, SVT_INT, g_sludge->_evtMan->mouseX() * g_sludge->_gfxMan->getCamZoom());
+ fun->reg.setVariable(SVT_INT, g_sludge->_evtMan->mouseX() * g_sludge->_gfxMan->getCamZoom());
return BR_CONTINUE;
}
builtIn(getMouseScreenY) {
UNUSEDALL
- setVariable(fun->reg, SVT_INT, g_sludge->_evtMan->mouseY() * g_sludge->_gfxMan->getCamZoom());
+ fun->reg.setVariable(SVT_INT, g_sludge->_evtMan->mouseY() * g_sludge->_gfxMan->getCamZoom());
return BR_CONTINUE;
}
builtIn(getStatusText) {
UNUSEDALL
- makeTextVar(fun->reg, statusBarText());
+ fun->reg.makeTextVar(statusBarText());
return BR_CONTINUE;
}
builtIn(getMatchingFiles) {
UNUSEDALL
- Common::String newText = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newText = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
- unlinkVar(fun->reg);
+ fun->reg.unlinkVar();
// Return value
fun->reg.varType = SVT_STACK;
@@ -248,7 +215,7 @@ builtIn(getMatchingFiles) {
fun->reg.varData.theStack->first = NULL;
fun->reg.varData.theStack->last = NULL;
fun->reg.varData.theStack->timesUsed = 1;
- if (!getSavedGamesStack(fun->reg.varData.theStack, newText))
+ if (!fun->reg.varData.theStack->getSavedGamesStack(newText))
return BR_ERROR;
return BR_CONTINUE;
}
@@ -260,7 +227,7 @@ builtIn(saveGame) {
fatal("Can't save game state while the engine is frozen");
}
- g_sludge->loadNow = getTextFromAnyVar(fun->stack->thisVar);
+ g_sludge->loadNow = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
Common::String aaaaa = encodeFilename(g_sludge->loadNow);
@@ -270,14 +237,14 @@ builtIn(saveGame) {
g_sludge->loadNow = ":" + aaaaa;
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
saverFunc = fun;
return BR_KEEP_AND_PAUSE;
}
builtIn(fileExists) {
UNUSEDALL
- g_sludge->loadNow = getTextFromAnyVar(fun->stack->thisVar);
+ g_sludge->loadNow = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
Common::String aaaaa = encodeFilename(g_sludge->loadNow);
g_sludge->loadNow.clear();
@@ -300,13 +267,13 @@ builtIn(fileExists) {
}
// Return value
- setVariable(fun->reg, SVT_INT, exist);
+ fun->reg.setVariable(SVT_INT, exist);
return BR_CONTINUE;
}
builtIn(loadGame) {
UNUSEDALL
- Common::String aaaaa = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String aaaaa = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
g_sludge->loadNow.clear();
g_sludge->loadNow = encodeFilename(aaaaa);
@@ -340,16 +307,16 @@ builtIn(blankScreen) {
builtIn(blankArea) {
UNUSEDALL
int x1, y1, x2, y2;
- if (!getValueType(y2, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y2, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x2, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x2, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(y1, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y1, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x1, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x1, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_gfxMan->blankScreen(x1, y1, x2, y2);
@@ -365,13 +332,13 @@ builtIn(darkBackground) {
builtIn(addOverlay) {
UNUSEDALL
int fileNumber, xPos, yPos;
- if (!getValueType(yPos, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(yPos, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(xPos, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(xPos, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_gfxMan->loadBackDrop(fileNumber, xPos, yPos);
@@ -381,13 +348,13 @@ builtIn(addOverlay) {
builtIn(mixOverlay) {
UNUSEDALL
int fileNumber, xPos, yPos;
- if (!getValueType(yPos, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(yPos, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(xPos, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(xPos, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_gfxMan->mixBackDrop(fileNumber, xPos, yPos);
@@ -397,13 +364,13 @@ builtIn(mixOverlay) {
builtIn(pasteImage) {
UNUSEDALL
int x, y;
- if (!getValueType(y, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- PersonaAnimation *pp = getAnimationFromVar(fun->stack->thisVar);
+ PersonaAnimation *pp = fun->stack->thisVar.getAnimationFromVar();
trimStack(fun->stack);
if (pp == NULL)
return BR_CONTINUE;
@@ -418,10 +385,10 @@ builtIn(pasteImage) {
builtIn(setSceneDimensions) {
UNUSEDALL
int x, y;
- if (!getValueType(y, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
if (g_sludge->_gfxMan->killResizeBackdrop(x, y)) {
@@ -435,10 +402,10 @@ builtIn(setSceneDimensions) {
builtIn(aimCamera) {
UNUSEDALL
int cameraX, cameraY;
- if (!getValueType(cameraY, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(cameraY, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(cameraX, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(cameraX, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
@@ -450,7 +417,7 @@ builtIn(aimCamera) {
builtIn(zoomCamera) {
UNUSEDALL
int z;
- if (!getValueType(z, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(z, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
@@ -476,7 +443,7 @@ builtIn(pickOne) {
// Return value
while (numParams--) {
if (i == numParams)
- copyVariable(fun->stack->thisVar, fun->reg);
+ fun->reg.copyFrom(fun->stack->thisVar);
trimStack(fun->stack);
}
return BR_CONTINUE;
@@ -489,13 +456,13 @@ builtIn(substring) {
//debugOut ("BUILTIN: substring\n");
- if (!getValueType(length, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(length, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(start, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(start, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- wholeString = getTextFromAnyVar(fun->stack->thisVar);
+ wholeString = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
UTF8Converter convert;
@@ -517,21 +484,21 @@ builtIn(substring) {
Common::String newString(wholeString.begin() + startoffset, wholeString.begin() + endoffset);
- makeTextVar(fun->reg, newString);
+ fun->reg.makeTextVar(newString);
return BR_CONTINUE;
}
builtIn(stringLength) {
UNUSEDALL
- Common::String newText = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newText = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, g_sludge->_txtMan->stringLength(newText));
+ fun->reg.setVariable(SVT_INT, g_sludge->_txtMan->stringLength(newText));
return BR_CONTINUE;
}
builtIn(newStack) {
UNUSEDALL
- unlinkVar(fun->reg);
+ fun->reg.unlinkVar();
// Return value
fun->reg.varType = SVT_STACK;
@@ -560,13 +527,13 @@ builtIn(stackSize) {
switch (fun->stack->thisVar.varType) {
case SVT_STACK:
// Return value
- setVariable(fun->reg, SVT_INT, stackSize(fun->stack->thisVar.varData.theStack));
+ fun->reg.setVariable(SVT_INT, fun->stack->thisVar.varData.theStack->getStackSize());
trimStack(fun->stack);
return BR_CONTINUE;
case SVT_FASTARRAY:
// Return value
- setVariable(fun->reg, SVT_INT, fun->stack->thisVar.varData.fastArray->size);
+ fun->reg.setVariable(SVT_INT, fun->stack->thisVar.varData.fastArray->size);
trimStack(fun->stack);
return BR_CONTINUE;
@@ -584,7 +551,7 @@ builtIn(copyStack) {
return BR_ERROR;
}
// Return value
- if (!copyStack(fun->stack->thisVar, fun->reg))
+ if (!fun->reg.copyStack(fun->stack->thisVar))
return BR_ERROR;
trimStack(fun->stack);
return BR_CONTINUE;
@@ -639,10 +606,11 @@ builtIn(deleteFromStack) {
}
// Return value
- setVariable(fun->reg, SVT_INT, deleteVarFromStack(fun->stack->thisVar, fun->stack->next->thisVar.varData.theStack->first, false));
+ fun->reg.setVariable(SVT_INT, deleteVarFromStack(fun->stack->thisVar, fun->stack->next->thisVar.varData.theStack->first, false));
// Horrible hacking because 'last' value might now be wrong!
- fun->stack->next->thisVar.varData.theStack->last = stackFindLast(fun->stack->next->thisVar.varData.theStack->first);
+ VariableStack *nextFirstStack = fun->stack->next->thisVar.varData.theStack->first;
+ fun->stack->next->thisVar.varData.theStack->last = (nextFirstStack == NULL) ? NULL : nextFirstStack->stackFindLast();
trimStack(fun->stack);
trimStack(fun->stack);
@@ -657,10 +625,11 @@ builtIn(deleteAllFromStack) {
}
// Return value
- setVariable(fun->reg, SVT_INT, deleteVarFromStack(fun->stack->thisVar, fun->stack->next->thisVar.varData.theStack->first, true));
+ fun->reg.setVariable(SVT_INT, deleteVarFromStack(fun->stack->thisVar, fun->stack->next->thisVar.varData.theStack->first, true));
// Horrible hacking because 'last' value might now be wrong!
- fun->stack->next->thisVar.varData.theStack->last = stackFindLast(fun->stack->next->thisVar.varData.theStack->first);
+ VariableStack *nextFirstStack = fun->stack->next->thisVar.varData.theStack->first;
+ fun->stack->next->thisVar.varData.theStack->last = (nextFirstStack == NULL) ? NULL : nextFirstStack->stackFindLast();
trimStack(fun->stack);
trimStack(fun->stack);
@@ -679,7 +648,7 @@ builtIn(popFromStack) {
}
// Return value
- copyVariable(fun->stack->thisVar.varData.theStack->first->thisVar, fun->reg);
+ fun->reg.copyFrom(fun->stack->thisVar.varData.theStack->first->thisVar);
trimStack(fun->stack->thisVar.varData.theStack->first);
trimStack(fun->stack);
return BR_CONTINUE;
@@ -697,7 +666,7 @@ builtIn(peekStart) {
}
// Return value
- copyVariable(fun->stack->thisVar.varData.theStack->first->thisVar, fun->reg);
+ fun->reg.copyFrom(fun->stack->thisVar.varData.theStack->first->thisVar);
trimStack(fun->stack);
return BR_CONTINUE;
}
@@ -714,7 +683,7 @@ builtIn(peekEnd) {
}
// Return value
- copyVariable(fun->stack->thisVar.varData.theStack->last->thisVar, fun->reg);
+ fun->reg.copyFrom(fun->stack->thisVar.varData.theStack->last->thisVar);
trimStack(fun->stack);
return BR_CONTINUE;
}
@@ -723,24 +692,24 @@ builtIn(random) {
UNUSEDALL
int num;
- if (!getValueType(num, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(num, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
if (num <= 0)
num = 1;
- setVariable(fun->reg, SVT_INT, 0 /*rand() % num*/); //TODO:false value
+ fun->reg.setVariable(SVT_INT, 0 /*rand() % num*/); //TODO:false value
return BR_CONTINUE;
}
static bool getRGBParams(int &red, int &green, int &blue, LoadedFunction *fun) {
- if (!getValueType(blue, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(blue, SVT_INT))
return false;
trimStack(fun->stack);
- if (!getValueType(green, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(green, SVT_INT))
return false;
trimStack(fun->stack);
- if (!getValueType(red, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(red, SVT_INT))
return false;
trimStack(fun->stack);
return true;
@@ -775,7 +744,7 @@ builtIn(setPasteColour) {
if (!getRGBParams(red, green, blue, fun))
return BR_ERROR;
- setFontColour(pastePalette, (byte)red, (byte)green, (byte)blue);
+ g_sludge->_txtMan->setPasterColor((byte)red, (byte)green, (byte)blue);
return BR_CONTINUE;
}
@@ -787,7 +756,7 @@ builtIn(setBlankColour) {
return BR_ERROR;
g_sludge->_gfxMan->setBlankColor(red, green, blue);
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
return BR_CONTINUE;
}
@@ -799,21 +768,21 @@ builtIn(setBurnColour) {
return BR_ERROR;
g_sludge->_gfxMan->setBurnColor(red, green, blue);
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
return BR_CONTINUE;
}
builtIn(setFont) {
UNUSEDALL
int fileNumber, newHeight;
- if (!getValueType(newHeight, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(newHeight, SVT_INT))
return BR_ERROR;
// newDebug (" Height:", newHeight);
trimStack(fun->stack);
- Common::String newText = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newText = fun->stack->thisVar.getTextFromAnyVar();
// newDebug (" Character supported:", newText);
trimStack(fun->stack);
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE))
return BR_ERROR;
// newDebug (" File:", fileNumber);
trimStack(fun->stack);
@@ -825,28 +794,28 @@ builtIn(setFont) {
builtIn(inFont) {
UNUSEDALL
- Common::String newText = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newText = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
// Return value
- setVariable(fun->reg, SVT_INT, g_sludge->_txtMan->isInFont(newText));
+ fun->reg.setVariable(SVT_INT, g_sludge->_txtMan->isInFont(newText));
return BR_CONTINUE;
}
builtIn(pasteString) {
UNUSEDALL
- Common::String newText = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newText = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
int y, x;
- if (!getValueType(y, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
if (x == IN_THE_CENTRE)
x = g_sludge->_gfxMan->getCenterX(g_sludge->_txtMan->stringWidth(newText));
- g_sludge->_txtMan->pasteStringToBackdrop(newText, x, y, pastePalette);
+ g_sludge->_txtMan->pasteStringToBackdrop(newText, x, y);
return BR_CONTINUE;
}
@@ -858,11 +827,11 @@ builtIn(anim) {
}
// First store the frame numbers and take 'em off the stack
- PersonaAnimation *ba = createPersonaAnim(numParams - 1, fun->stack);
+ PersonaAnimation *ba = new PersonaAnimation(numParams - 1, fun->stack);
// Only remaining paramter is the file number
int fileNumber;
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
@@ -870,10 +839,10 @@ builtIn(anim) {
LoadedSpriteBank *sprBanky = g_sludge->_gfxMan->loadBankForAnim(fileNumber);
if (!sprBanky)
return BR_ERROR; // File not found, fatal done already
- setBankFile(ba, sprBanky);
+ ba->theSprites = sprBanky;
// Return value
- newAnimationVariable(fun->reg, ba);
+ fun->reg.makeAnimationVariable(ba);
return BR_CONTINUE;
}
@@ -893,18 +862,18 @@ builtIn(costume) {
if (!checkNew(newPersona->animation))
return BR_ERROR;
for (iii = numParams - 1; iii >= 0; iii--) {
- newPersona->animation[iii] = getAnimationFromVar(fun->stack->thisVar);
+ newPersona->animation[iii] = fun->stack->thisVar.getAnimationFromVar();
trimStack(fun->stack);
}
// Return value
- newCostumeVariable(fun->reg, newPersona);
+ fun->reg.makeCostumeVariable(newPersona);
return BR_CONTINUE;
}
builtIn(launch) {
UNUSEDALL
- Common::String newTextA = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newTextA = fun->stack->thisVar.getTextFromAnyVar();
Common::String newText = encodeFilename(newTextA);
@@ -922,7 +891,7 @@ builtIn(launch) {
if (g_sludge->launchMe.empty())
return BR_ERROR;
}
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
launchResult = &fun->reg;
return BR_KEEP_AND_PAUSE;
@@ -931,7 +900,7 @@ builtIn(launch) {
builtIn(pause) {
UNUSEDALL
int theTime;
- if (!getValueType(theTime, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(theTime, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
if (theTime > 0) {
@@ -951,10 +920,10 @@ builtIn(completeTimers) {
builtIn(callEvent) {
UNUSEDALL
int obj1, obj2;
- if (!getValueType(obj2, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj2, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj1, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj1, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
@@ -962,10 +931,10 @@ builtIn(callEvent) {
// Return value
if (fNum) {
- setVariable(fun->reg, SVT_FUNC, fNum);
+ fun->reg.setVariable(SVT_FUNC, fNum);
return BR_CALLAFUNC;
}
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
return BR_CONTINUE;
}
@@ -987,13 +956,13 @@ builtIn(_rem_movieStart) {
builtIn(_rem_movieAbort) {
UNUSEDALL
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
return BR_CONTINUE;
}
builtIn(_rem_moviePlaying) {
UNUSEDALL
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
return BR_CONTINUE;
}
@@ -1004,13 +973,13 @@ builtIn(playMovie) {
if (movieIsPlaying)
return BR_PAUSE;
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
r = playMovie(fileNumber);
- setVariable(fun->reg, SVT_INT, r);
+ fun->reg.setVariable(SVT_INT, r);
if (r && (!fun->next)) {
restartFunction(fun);
@@ -1024,7 +993,7 @@ builtIn(stopMovie) {
stopMovie();
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
return BR_CONTINUE;
}
@@ -1033,7 +1002,7 @@ builtIn(pauseMovie) {
pauseMovie();
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
return BR_CONTINUE;
}
@@ -1043,13 +1012,13 @@ builtIn(pauseMovie) {
builtIn(startMusic) {
UNUSEDALL
int fromTrack, musChan, fileNumber;
- if (!getValueType(fromTrack, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fromTrack, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(musChan, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(musChan, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
if (!g_sludge->_soundMan->playMOD(fileNumber, musChan, fromTrack))
@@ -1060,7 +1029,7 @@ builtIn(startMusic) {
builtIn(stopMusic) {
UNUSEDALL
int v;
- if (!getValueType(v, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(v, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_soundMan->stopMOD(v);
@@ -1070,10 +1039,10 @@ builtIn(stopMusic) {
builtIn(setMusicVolume) {
UNUSEDALL
int musChan, v;
- if (!getValueType(v, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(v, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(musChan, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(musChan, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_soundMan->setMusicVolume(musChan, v);
@@ -1083,7 +1052,7 @@ builtIn(setMusicVolume) {
builtIn(setDefaultMusicVolume) {
UNUSEDALL
int v;
- if (!getValueType(v, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(v, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_soundMan->setDefaultMusicVolume(v);
@@ -1093,7 +1062,7 @@ builtIn(setDefaultMusicVolume) {
builtIn(playSound) {
UNUSEDALL
int fileNumber;
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
if (!g_sludge->_soundMan->startSound(fileNumber, false))
@@ -1109,7 +1078,7 @@ builtIn(loopSound) {
return BR_ERROR;
} else if (numParams < 2) {
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
if (!g_sludge->_soundMan->startSound(fileNumber, true))
@@ -1124,12 +1093,12 @@ builtIn(loopSound) {
// Should we loop?
if (fun->stack->thisVar.varType != SVT_FILE) {
- getValueType(doLoop, SVT_INT, fun->stack->thisVar);
+ fun->stack->thisVar.getValueType(doLoop, SVT_INT);
trimStack(fun->stack);
numParams--;
}
while (numParams) {
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar)) {
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE)) {
fatal("Illegal parameter given built-in function loopSound().");
return BR_ERROR;
}
@@ -1162,7 +1131,7 @@ builtIn(loopSound) {
builtIn(stopSound) {
UNUSEDALL
int v;
- if (!getValueType(v, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(v, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_soundMan->huntKillSound(v);
@@ -1172,7 +1141,7 @@ builtIn(stopSound) {
builtIn(setDefaultSoundVolume) {
UNUSEDALL
int v;
- if (!getValueType(v, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(v, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_soundMan->setDefaultSoundVolume(v);
@@ -1182,10 +1151,10 @@ builtIn(setDefaultSoundVolume) {
builtIn(setSoundVolume) {
UNUSEDALL
int musChan, v;
- if (!getValueType(v, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(v, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(musChan, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(musChan, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_soundMan->setSoundVolume(musChan, v);
@@ -1195,13 +1164,13 @@ builtIn(setSoundVolume) {
builtIn(setSoundLoopPoints) {
UNUSEDALL
int musChan, theEnd, theStart;
- if (!getValueType(theEnd, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(theEnd, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(theStart, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(theStart, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(musChan, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(musChan, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_soundMan->setSoundLoop(musChan, theStart, theEnd);
@@ -1215,20 +1184,20 @@ builtIn(setFloor) {
UNUSEDALL
if (fun->stack->thisVar.varType == SVT_FILE) {
int v;
- getValueType(v, SVT_FILE, fun->stack->thisVar);
+ fun->stack->thisVar.getValueType(v, SVT_FILE);
trimStack(fun->stack);
- if (!setFloor(v))
+ if (!g_sludge->_floorMan->setFloor(v))
return BR_ERROR;
} else {
trimStack(fun->stack);
- setFloorNull();
+ g_sludge->_floorMan->setFloorNull();
}
return BR_CONTINUE;
}
builtIn(showFloor) {
UNUSEDALL
- drawFloor();
+ g_sludge->_floorMan->drawFloor();
return BR_CONTINUE;
}
@@ -1236,7 +1205,7 @@ builtIn(setZBuffer) {
UNUSEDALL
if (fun->stack->thisVar.varType == SVT_FILE) {
int v;
- getValueType(v, SVT_FILE, fun->stack->thisVar);
+ fun->stack->thisVar.getValueType(v, SVT_FILE);
trimStack(fun->stack);
if (!g_sludge->_gfxMan->setZBuffer(v))
return BR_ERROR;
@@ -1251,7 +1220,7 @@ builtIn(setLightMap) {
UNUSEDALL
switch (numParams) {
case 2:
- if (!getValueType(g_sludge->_gfxMan->_lightMapMode, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(g_sludge->_gfxMan->_lightMapMode, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_gfxMan->_lightMapMode %= LIGHTMAPMODE_NUM;
@@ -1260,15 +1229,15 @@ builtIn(setLightMap) {
case 1:
if (fun->stack->thisVar.varType == SVT_FILE) {
int v;
- getValueType(v, SVT_FILE, fun->stack->thisVar);
+ fun->stack->thisVar.getValueType(v, SVT_FILE);
trimStack(fun->stack);
if (!g_sludge->_gfxMan->loadLightMap(v))
return BR_ERROR;
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
} else {
trimStack(fun->stack);
g_sludge->_gfxMan->killLightMap();
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
break;
@@ -1284,13 +1253,15 @@ builtIn(setLightMap) {
builtIn(setSpeechMode) {
UNUSEDALL
- if (!getValueType(speechMode, SVT_INT, fun->stack->thisVar))
+ int speechMode;
+ if (!fun->stack->thisVar.getValueType(speechMode, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
if (speechMode < 0 || speechMode > 2) {
fatal("Valid parameters are be SPEECHANDTEXT, SPEECHONLY or TEXTONLY");
return BR_ERROR;
}
+ g_sludge->_speechMan->setSpeechMode(speechMode);
return BR_CONTINUE;
}
@@ -1298,9 +1269,9 @@ builtIn(somethingSpeaking) {
UNUSEDALL
int i = g_sludge->_speechMan->isThereAnySpeechGoingOn();
if (i == -1) {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
} else {
- setVariable(fun->reg, SVT_OBJTYPE, i);
+ fun->reg.setVariable(SVT_OBJTYPE, i);
}
return BR_CONTINUE;
}
@@ -1313,21 +1284,21 @@ builtIn(skipSpeech) {
builtIn(getOverObject) {
UNUSEDALL
- if (overRegion)
+ if (g_sludge->_regionMan->getOverRegion())
// Return value
- setVariable(fun->reg, SVT_OBJTYPE, overRegion->thisType->objectNum);
+ fun->reg.setVariable(SVT_OBJTYPE, g_sludge->_regionMan->getOverRegion()->thisType->objectNum);
else
// Return value
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
return BR_CONTINUE;
}
builtIn(rename) {
UNUSEDALL
- Common::String newText = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newText = fun->stack->thisVar.getTextFromAnyVar();
int objT;
trimStack(fun->stack);
- if (!getValueType(objT, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objT, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
ObjectType *o = g_sludge->_objMan->findObjectType(objT);
@@ -1339,19 +1310,19 @@ builtIn(rename) {
builtIn(getObjectX) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *pers = findPerson(objectNumber);
+ OnScreenPerson *pers = g_sludge->_peopleMan->findPerson(objectNumber);
if (pers) {
- setVariable(fun->reg, SVT_INT, pers->x);
+ fun->reg.setVariable(SVT_INT, pers->x);
} else {
- ScreenRegion *la = getRegionForObject(objectNumber);
+ ScreenRegion *la = g_sludge->_regionMan->getRegionForObject(objectNumber);
if (la) {
- setVariable(fun->reg, SVT_INT, la->sX);
+ fun->reg.setVariable(SVT_INT, la->sX);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
}
return BR_CONTINUE;
@@ -1360,19 +1331,19 @@ builtIn(getObjectX) {
builtIn(getObjectY) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *pers = findPerson(objectNumber);
+ OnScreenPerson *pers = g_sludge->_peopleMan->findPerson(objectNumber);
if (pers) {
- setVariable(fun->reg, SVT_INT, pers->y);
+ fun->reg.setVariable(SVT_INT, pers->y);
} else {
- ScreenRegion *la = getRegionForObject(objectNumber);
+ ScreenRegion *la = g_sludge->_regionMan->getRegionForObject(objectNumber);
if (la) {
- setVariable(fun->reg, SVT_INT, la->sY);
+ fun->reg.setVariable(SVT_INT, la->sY);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
}
return BR_CONTINUE;
@@ -1381,31 +1352,31 @@ builtIn(getObjectY) {
builtIn(addScreenRegion) {
UNUSEDALL
int sX, sY, x1, y1, x2, y2, di, objectNumber;
- if (!getValueType(di, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(di, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(sY, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(sY, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(sX, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(sX, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(y2, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y2, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x2, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x2, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(y1, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y1, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x1, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x1, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- if (addScreenRegion(x1, y1, x2, y2, sX, sY, di, objectNumber))
+ if (g_sludge->_regionMan->addScreenRegion(x1, y1, x2, y2, sX, sY, di, objectNumber))
return BR_CONTINUE;
return BR_ERROR;
@@ -1414,22 +1385,22 @@ builtIn(addScreenRegion) {
builtIn(removeScreenRegion) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- removeScreenRegion(objectNumber);
+ g_sludge->_regionMan->removeScreenRegion(objectNumber);
return BR_CONTINUE;
}
builtIn(showBoxes) {
UNUSEDALL
- showBoxes();
+ g_sludge->_regionMan->showBoxes();
return BR_CONTINUE;
}
builtIn(removeAllScreenRegions) {
UNUSEDALL
- killAllRegions();
+ g_sludge->_regionMan->kill();
return BR_CONTINUE;
}
@@ -1438,21 +1409,21 @@ builtIn(addCharacter) {
Persona *p;
int x, y, objectNumber;
- p = getCostumeFromVar(fun->stack->thisVar);
+ p = fun->stack->thisVar.getCostumeFromVar();
if (p == NULL)
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(y, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- if (addPerson(x, y, objectNumber, p))
+ if (g_sludge->_peopleMan->addPerson(x, y, objectNumber, p))
return BR_CONTINUE;
return BR_ERROR;
}
@@ -1460,109 +1431,109 @@ builtIn(addCharacter) {
builtIn(hideCharacter) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setShown(false, objectNumber);
+ g_sludge->_peopleMan->setShown(false, objectNumber);
return BR_CONTINUE;
}
builtIn(showCharacter) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setShown(true, objectNumber);
+ g_sludge->_peopleMan->setShown(true, objectNumber);
return BR_CONTINUE;
}
builtIn(removeAllCharacters) {
UNUSEDALL
killSpeechTimers();
- killMostPeople();
+ g_sludge->_peopleMan->killMostPeople();
return BR_CONTINUE;
}
builtIn(setCharacterDrawMode) {
UNUSEDALL
int obj, di;
- if (!getValueType(di, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(di, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setDrawMode(di, obj);
+ g_sludge->_peopleMan->setDrawMode(di, obj);
return BR_CONTINUE;
}
builtIn(setCharacterTransparency) {
UNUSEDALL
int obj, x;
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setPersonTransparency(obj, x);
+ g_sludge->_peopleMan->setPersonTransparency(obj, x);
return BR_CONTINUE;
}
builtIn(setCharacterColourise) {
UNUSEDALL
int obj, r, g, b, mix;
- if (!getValueType(mix, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(mix, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(b, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(b, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(g, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(g, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(r, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(r, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setPersonColourise(obj, r, g, b, mix);
+ g_sludge->_peopleMan->setPersonColourise(obj, r, g, b, mix);
return BR_CONTINUE;
}
builtIn(setScale) {
UNUSEDALL
int val1, val2;
- if (!getValueType(val2, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(val2, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(val1, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(val1, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- setScale((int16)val1, (int16)val2);
+ g_sludge->_peopleMan->setScale((int16)val1, (int16)val2);
return BR_CONTINUE;
}
builtIn(stopCharacter) {
UNUSEDALL
int obj;
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
// Return value
- setVariable(fun->reg, SVT_INT, stopPerson(obj));
+ fun->reg.setVariable(SVT_INT, g_sludge->_peopleMan->stopPerson(obj));
return BR_CONTINUE;
}
builtIn(pasteCharacter) {
UNUSEDALL
int obj;
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *thisPerson = findPerson(obj);
+ OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(obj);
if (thisPerson) {
PersonaAnimation *myAnim;
myAnim = thisPerson->myAnim;
@@ -1574,9 +1545,9 @@ builtIn(pasteCharacter) {
int fNum = myAnim->frames[thisPerson->frameNum].frameNum;
g_sludge->_gfxMan->fixScaleSprite(thisPerson->x, thisPerson->y, myAnim->theSprites->bank.sprites[ABS(fNum)], myAnim->theSprites->bank.myPalette, thisPerson, 0, 0, fNum < 0);
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
return BR_CONTINUE;
}
@@ -1584,91 +1555,91 @@ builtIn(pasteCharacter) {
builtIn(animate) {
UNUSEDALL
int obj;
- PersonaAnimation *pp = getAnimationFromVar(fun->stack->thisVar);
+ PersonaAnimation *pp = fun->stack->thisVar.getAnimationFromVar();
if (pp == NULL)
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- animatePerson(obj, pp);
- setVariable(fun->reg, SVT_INT, timeForAnim(pp));
+ g_sludge->_peopleMan->animatePerson(obj, pp);
+ fun->reg.setVariable(SVT_INT, pp->getTotalTime());
return BR_CONTINUE;
}
builtIn(setCostume) {
UNUSEDALL
int obj;
- Persona *pp = getCostumeFromVar(fun->stack->thisVar);
+ Persona *pp = fun->stack->thisVar.getCostumeFromVar();
if (pp == NULL)
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- animatePerson(obj, pp);
+ g_sludge->_peopleMan->animatePerson(obj, pp);
return BR_CONTINUE;
}
builtIn(floatCharacter) {
UNUSEDALL
int obj, di;
- if (!getValueType(di, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(di, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, floatCharacter(di, obj));
+ fun->reg.setVariable(SVT_INT, g_sludge->_peopleMan->floatCharacter(di, obj));
return BR_CONTINUE;
}
builtIn(setCharacterWalkSpeed) {
UNUSEDALL
int obj, di;
- if (!getValueType(di, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(di, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, setCharacterWalkSpeed(di, obj));
+ fun->reg.setVariable(SVT_INT, g_sludge->_peopleMan->setCharacterWalkSpeed(di, obj));
return BR_CONTINUE;
}
builtIn(turnCharacter) {
UNUSEDALL
int obj, di;
- if (!getValueType(di, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(di, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, turnPersonToFace(obj, di));
+ fun->reg.setVariable(SVT_INT, g_sludge->_peopleMan->turnPersonToFace(obj, di));
return BR_CONTINUE;
}
builtIn(setCharacterExtra) {
UNUSEDALL
int obj, di;
- if (!getValueType(di, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(di, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, setPersonExtra(obj, di));
+ fun->reg.setVariable(SVT_INT, g_sludge->_peopleMan->setPersonExtra(obj, di));
return BR_CONTINUE;
}
builtIn(removeCharacter) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- removeOneCharacter(objectNumber);
+ g_sludge->_peopleMan->removeOneCharacter(objectNumber);
return BR_CONTINUE;
}
@@ -1677,23 +1648,23 @@ static BuiltReturn moveChr(int numParams, LoadedFunction *fun, bool force, bool
case 3: {
int x, y, objectNumber;
- if (!getValueType(y, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
if (force) {
- if (forceWalkingPerson(x, y, objectNumber, fun, -1))
+ if (g_sludge->_peopleMan->forceWalkingPerson(x, y, objectNumber, fun, -1))
return BR_PAUSE;
} else if (immediate) {
- jumpPerson(x, y, objectNumber);
+ g_sludge->_peopleMan->jumpPerson(x, y, objectNumber);
} else {
- if (makeWalkingPerson(x, y, objectNumber, fun, -1))
+ if (g_sludge->_peopleMan->makeWalkingPerson(x, y, objectNumber, fun, -1))
return BR_PAUSE;
}
return BR_CONTINUE;
@@ -1703,23 +1674,23 @@ static BuiltReturn moveChr(int numParams, LoadedFunction *fun, bool force, bool
int toObj, objectNumber;
ScreenRegion*reggie;
- if (!getValueType(toObj, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(toObj, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- reggie = getRegionForObject(toObj);
+ reggie = g_sludge->_regionMan->getRegionForObject(toObj);
if (reggie == NULL)
return BR_CONTINUE;
if (force) {
- if (forceWalkingPerson(reggie->sX, reggie->sY, objectNumber, fun, reggie->di))
+ if (g_sludge->_peopleMan->forceWalkingPerson(reggie->sX, reggie->sY, objectNumber, fun, reggie->di))
return BR_PAUSE;
} else if (immediate) {
- jumpPerson(reggie->sX, reggie->sY, objectNumber);
+ g_sludge->_peopleMan->jumpPerson(reggie->sX, reggie->sY, objectNumber);
} else {
- if (makeWalkingPerson(reggie->sX, reggie->sY, objectNumber, fun, reggie->di))
+ if (g_sludge->_peopleMan->makeWalkingPerson(reggie->sX, reggie->sY, objectNumber, fun, reggie->di))
return BR_PAUSE;
}
return BR_CONTINUE;
@@ -1766,7 +1737,7 @@ builtIn(addStatus) {
builtIn(statusText) {
UNUSEDALL
- Common::String newText = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newText = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
setStatusBar(newText);
return BR_CONTINUE;
@@ -1775,7 +1746,7 @@ builtIn(statusText) {
builtIn(lightStatus) {
UNUSEDALL
int val;
- if (!getValueType(val, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(val, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
setLitStatus(val);
@@ -1785,10 +1756,10 @@ builtIn(lightStatus) {
builtIn(positionStatus) {
UNUSEDALL
int x, y;
- if (!getValueType(y, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
positionStatus(x, y);
@@ -1798,7 +1769,7 @@ builtIn(positionStatus) {
builtIn(alignStatus) {
UNUSEDALL
int val;
- if (!getValueType(val, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(val, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
nowStatus->alignStatus = (int16)val;
@@ -1812,7 +1783,7 @@ static bool getFuncNumForCallback(int numParams, LoadedFunction *fun, int &funct
break;
case 1:
- if (!getValueType(functionNum, SVT_FUNC, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(functionNum, SVT_FUNC))
return false;
trimStack(fun->stack);
break;
@@ -1922,18 +1893,18 @@ builtIn(cancelSub) {
builtIn(stringWidth) {
UNUSEDALL
- Common::String theText = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String theText = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
// Return value
- setVariable(fun->reg, SVT_INT, g_sludge->_txtMan->stringWidth(theText));
+ fun->reg.setVariable(SVT_INT, g_sludge->_txtMan->stringWidth(theText));
return BR_CONTINUE;
}
builtIn(hardScroll) {
UNUSEDALL
int v;
- if (!getValueType(v, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(v, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_gfxMan->hardScroll(v);
@@ -1943,80 +1914,76 @@ builtIn(hardScroll) {
builtIn(isScreenRegion) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, getRegionForObject(objectNumber) != NULL);
+ fun->reg.setVariable(SVT_INT, g_sludge->_regionMan->getRegionForObject(objectNumber) != NULL);
return BR_CONTINUE;
}
builtIn(setSpeechSpeed) {
UNUSEDALL
int number;
- if (!getValueType(number, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(number, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_speechMan->setSpeechSpeed(number * 0.01);
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
return BR_CONTINUE;
}
builtIn(setFontSpacing) {
UNUSEDALL
int fontSpaceI;
- if (!getValueType(fontSpaceI, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fontSpaceI, SVT_INT))
return BR_ERROR;
g_sludge->_txtMan->setFontSpace(fontSpaceI);
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
return BR_CONTINUE;
}
builtIn(transitionLevel) {
UNUSEDALL
- int number;
- if (!getValueType(number, SVT_INT, fun->stack->thisVar))
+ int brightnessLevel;
+ if (!fun->stack->thisVar.getValueType(brightnessLevel, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (number < 0)
- brightnessLevel = 0;
- else if (number > 255)
- brightnessLevel = 255;
- else
- brightnessLevel = number;
+ g_sludge->_gfxMan->setBrightnessLevel(brightnessLevel);
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
return BR_CONTINUE;
}
builtIn(captureAllKeys) {
UNUSEDALL
- captureAllKeys = getBoolean(fun->stack->thisVar);
+ // This built-in function doesn't have any effect any more, we capture all keys by default
+ bool captureAllKeysDeprecated = fun->stack->thisVar.getBoolean();
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, captureAllKeys);
+ fun->reg.setVariable(SVT_INT, captureAllKeysDeprecated);
return BR_CONTINUE;
}
builtIn(spinCharacter) {
UNUSEDALL
int number, objectNumber;
- if (!getValueType(number, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(number, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *thisPerson = findPerson(objectNumber);
+ OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(objectNumber);
if (thisPerson) {
thisPerson->wantAngle = number;
thisPerson->spinning = true;
thisPerson->continueAfterWalking = fun;
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
return BR_PAUSE;
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
return BR_CONTINUE;
}
}
@@ -2024,14 +1991,14 @@ builtIn(spinCharacter) {
builtIn(getCharacterDirection) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *thisPerson = findPerson(objectNumber);
+ OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(objectNumber);
if (thisPerson) {
- setVariable(fun->reg, SVT_INT, thisPerson->direction);
+ fun->reg.setVariable(SVT_INT, thisPerson->direction);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
return BR_CONTINUE;
}
@@ -2039,26 +2006,26 @@ builtIn(getCharacterDirection) {
builtIn(isCharacter) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *thisPerson = findPerson(objectNumber);
- setVariable(fun->reg, SVT_INT, thisPerson != NULL);
+ OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(objectNumber);
+ fun->reg.setVariable(SVT_INT, thisPerson != NULL);
return BR_CONTINUE;
}
builtIn(normalCharacter) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *thisPerson = findPerson(objectNumber);
+ OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(objectNumber);
if (thisPerson) {
thisPerson->myAnim = thisPerson->myPersona->animation[thisPerson->direction];
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
return BR_CONTINUE;
}
@@ -2066,14 +2033,14 @@ builtIn(normalCharacter) {
builtIn(isMoving) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *thisPerson = findPerson(objectNumber);
+ OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(objectNumber);
if (thisPerson) {
- setVariable(fun->reg, SVT_INT, thisPerson->walking);
+ fun->reg.setVariable(SVT_INT, thisPerson->walking);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
return BR_CONTINUE;
}
@@ -2081,10 +2048,10 @@ builtIn(isMoving) {
builtIn(fetchEvent) {
UNUSEDALL
int obj1, obj2;
- if (!getValueType(obj2, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj2, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(obj1, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(obj1, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
@@ -2092,9 +2059,9 @@ builtIn(fetchEvent) {
// Return value
if (fNum) {
- setVariable(fun->reg, SVT_FUNC, fNum);
+ fun->reg.setVariable(SVT_FUNC, fNum);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
return BR_CONTINUE;
}
@@ -2102,13 +2069,13 @@ builtIn(fetchEvent) {
builtIn(deleteFile) {
UNUSEDALL
- Common::String namNormal = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String namNormal = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
Common::String nam = encodeFilename(namNormal);
namNormal.clear();
if (failSecurityCheck(nam))
return BR_ERROR;
- setVariable(fun->reg, SVT_INT, remove(nam.c_str()));
+ fun->reg.setVariable(SVT_INT, remove(nam.c_str()));
return BR_CONTINUE;
}
@@ -2118,20 +2085,20 @@ builtIn(renameFile) {
Common::String temp;
temp.clear();
- temp = getTextFromAnyVar(fun->stack->thisVar);
+ temp = fun->stack->thisVar.getTextFromAnyVar();
Common::String newnam = encodeFilename(temp);
trimStack(fun->stack);
if (failSecurityCheck(newnam))
return BR_ERROR;
temp.clear();
- temp = getTextFromAnyVar(fun->stack->thisVar);
+ temp = fun->stack->thisVar.getTextFromAnyVar();
Common::String nam = encodeFilename(temp);
trimStack(fun->stack);
if (failSecurityCheck(nam))
return BR_ERROR;
- setVariable(fun->reg, SVT_INT, rename(nam.c_str(), newnam.c_str()));
+ fun->reg.setVariable(SVT_INT, rename(nam.c_str(), newnam.c_str()));
return BR_CONTINUE;
}
@@ -2139,7 +2106,7 @@ builtIn(renameFile) {
builtIn(cacheSound) {
UNUSEDALL
int fileNumber;
- if (!getValueType(fileNumber, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(fileNumber, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
if (g_sludge->_soundMan->cacheSound(fileNumber) == -1)
@@ -2149,38 +2116,38 @@ builtIn(cacheSound) {
builtIn(burnString) {
UNUSEDALL
- Common::String newText = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newText = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
int y, x;
- if (!getValueType(y, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
if (x == IN_THE_CENTRE)
x = g_sludge->_gfxMan->getCenterX(g_sludge->_txtMan->stringWidth(newText));
- g_sludge->_txtMan->burnStringToBackdrop(newText, x, y, pastePalette);
+ g_sludge->_txtMan->burnStringToBackdrop(newText, x, y);
return BR_CONTINUE;
}
builtIn(setCharacterSpinSpeed) {
UNUSEDALL
int speed, who;
- if (!getValueType(speed, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(speed, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(who, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(who, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *thisPerson = findPerson(who);
+ OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(who);
if (thisPerson) {
thisPerson->spinSpeed = speed;
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
return BR_CONTINUE;
}
@@ -2188,20 +2155,20 @@ builtIn(setCharacterSpinSpeed) {
builtIn(setCharacterAngleOffset) {
UNUSEDALL
int angle, who;
- if (!getValueType(angle, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(angle, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(who, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(who, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *thisPerson = findPerson(who);
+ OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(who);
if (thisPerson) {
thisPerson->angleOffset = angle;
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
return BR_CONTINUE;
}
@@ -2209,11 +2176,11 @@ builtIn(setCharacterAngleOffset) {
builtIn(transitionMode) {
UNUSEDALL
int n;
- if (!getValueType(n, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(n, SVT_INT))
return BR_ERROR;
- fadeMode = n;
+ g_sludge->_gfxMan->setFadeMode(n);
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
return BR_CONTINUE;
}
@@ -2221,7 +2188,7 @@ builtIn(transitionMode) {
builtIn(_rem_updateDisplay) {
UNUSEDALL
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, true);
+ fun->reg.setVariable(SVT_INT, true);
return BR_CONTINUE;
}
@@ -2242,7 +2209,7 @@ builtIn(getSoundCache) {
builtIn(saveCustomData) {
UNUSEDALL
// saveCustomData (thisStack, fileName);
- Common::String fileNameB = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String fileNameB = fun->stack->thisVar.getTextFromAnyVar();
Common::String fileName = encodeFilename(fileNameB);
@@ -2254,7 +2221,7 @@ builtIn(saveCustomData) {
fatal("First parameter isn't a stack");
return BR_ERROR;
}
- if (!stackToFile(fileName, fun->stack->thisVar))
+ if (!CustomSaveHelper::stackToFile(fileName, fun->stack->thisVar))
return BR_ERROR;
trimStack(fun->stack);
return BR_CONTINUE;
@@ -2263,7 +2230,7 @@ builtIn(saveCustomData) {
builtIn(loadCustomData) {
UNUSEDALL
- Common::String newTextA = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String newTextA = fun->stack->thisVar.getTextFromAnyVar();
Common::String newText = encodeFilename(newTextA);
@@ -2271,7 +2238,7 @@ builtIn(loadCustomData) {
return BR_ERROR;
trimStack(fun->stack);
- unlinkVar(fun->reg);
+ fun->reg.unlinkVar();
fun->reg.varType = SVT_STACK;
fun->reg.varData.theStack = new StackHandler;
if (!checkNew(fun->reg.varData.theStack))
@@ -2279,7 +2246,7 @@ builtIn(loadCustomData) {
fun->reg.varData.theStack->first = NULL;
fun->reg.varData.theStack->last = NULL;
fun->reg.varData.theStack->timesUsed = 1;
- if (!fileToStack(newText, fun->reg.varData.theStack))
+ if (!CustomSaveHelper::fileToStack(newText, fun->reg.varData.theStack))
return BR_ERROR;
return BR_CONTINUE;
}
@@ -2287,18 +2254,18 @@ builtIn(loadCustomData) {
builtIn(setCustomEncoding) {
UNUSEDALL
int n;
- if (!getValueType(n, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(n, SVT_INT))
return BR_ERROR;
- saveEncoding = n;
+ CustomSaveHelper::_saveEncoding = n;
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
return BR_CONTINUE;
}
builtIn(freeSound) {
UNUSEDALL
int v;
- if (!getValueType(v, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(v, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
g_sludge->_soundMan->huntKillFreeSound(v);
@@ -2312,19 +2279,19 @@ builtIn(parallaxAdd) {
return BR_ERROR;
} else {
int wrapX, wrapY, v;
- if (!getValueType(wrapY, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(wrapY, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(wrapX, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(wrapX, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(v, SVT_FILE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(v, SVT_FILE))
return BR_ERROR;
trimStack(fun->stack);
if (!g_sludge->_gfxMan->loadParallax(v, wrapX, wrapY))
return BR_ERROR;
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
}
return BR_CONTINUE;
}
@@ -2332,21 +2299,21 @@ builtIn(parallaxAdd) {
builtIn(parallaxClear) {
UNUSEDALL
g_sludge->_gfxMan->killParallax();
- setVariable(fun->reg, SVT_INT, 1);
+ fun->reg.setVariable(SVT_INT, 1);
return BR_CONTINUE;
}
builtIn(getPixelColour) {
UNUSEDALL
int x, y;
- if (!getValueType(y, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- unlinkVar(fun->reg);
+ fun->reg.unlinkVar();
fun->reg.varType = SVT_STACK;
fun->reg.varData.theStack = new StackHandler;
if (!checkNew(fun->reg.varData.theStack))
@@ -2364,7 +2331,7 @@ builtIn(makeFastArray) {
UNUSEDALL
switch (fun->stack->thisVar.varType) {
case SVT_STACK: {
- bool success = makeFastArrayFromStack(fun->reg, fun->stack->thisVar.varData.theStack);
+ bool success = fun->reg.makeFastArrayFromStack(fun->stack->thisVar.varData.theStack);
trimStack(fun->stack);
return success ? BR_CONTINUE : BR_ERROR;
}
@@ -2373,7 +2340,7 @@ builtIn(makeFastArray) {
case SVT_INT: {
int i = fun->stack->thisVar.varData.intValue;
trimStack(fun->stack);
- return makeFastArraySize(fun->reg, i) ? BR_CONTINUE : BR_ERROR;
+ return fun->reg.makeFastArraySize(i) ? BR_CONTINUE : BR_ERROR;
}
break;
@@ -2387,22 +2354,22 @@ builtIn(makeFastArray) {
builtIn(getCharacterScale) {
UNUSEDALL
int objectNumber;
- if (!getValueType(objectNumber, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objectNumber, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
- OnScreenPerson *pers = findPerson(objectNumber);
+ OnScreenPerson *pers = g_sludge->_peopleMan->findPerson(objectNumber);
if (pers) {
- setVariable(fun->reg, SVT_INT, pers->scale * 100);
+ fun->reg.setVariable(SVT_INT, pers->scale * 100);
} else {
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
}
return BR_CONTINUE;
}
builtIn(getLanguageID) {
UNUSEDALL
- setVariable(fun->reg, SVT_INT, g_sludge->getLanguageID());
+ fun->reg.setVariable(SVT_INT, g_sludge->getLanguageID());
return BR_CONTINUE;
}
@@ -2413,7 +2380,7 @@ builtIn(_rem_launchWith) {
trimStack(fun->stack);
// To support some windows only games
- Common::String filename = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String filename = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
if (filename.hasSuffix(".exe")) {
@@ -2432,28 +2399,28 @@ builtIn(_rem_launchWith) {
}
g_sludge->launchNext.clear();
- setVariable(fun->reg, SVT_INT, false);
+ fun->reg.setVariable(SVT_INT, false);
return BR_CONTINUE;
}
builtIn(getFramesPerSecond) {
UNUSEDALL
- setVariable(fun->reg, SVT_INT, lastFramesPerSecond);
+ fun->reg.setVariable(SVT_INT, g_sludge->_timer.getLastFps());
return BR_CONTINUE;
}
builtIn(showThumbnail) {
UNUSEDALL
int x, y;
- if (!getValueType(y, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(y, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(x, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(x, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
// Encode the name!Encode the name!
- Common::String aaaaa = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String aaaaa = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
Common::String file = encodeFilename(aaaaa);
g_sludge->_gfxMan->showThumbnail(file, x, y);
@@ -2462,13 +2429,14 @@ builtIn(showThumbnail) {
builtIn(setThumbnailSize) {
UNUSEDALL
- if (!getValueType(thumbHeight, SVT_INT, fun->stack->thisVar))
+ int thumbHeight, thumbWidth;
+ if (!fun->stack->thisVar.getValueType(thumbHeight, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(thumbWidth, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(thumbWidth, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!g_sludge->_gfxMan->checkSizeValide(thumbWidth, thumbHeight)) {
+ if (!g_sludge->_gfxMan->setThumbnailSize(thumbWidth, thumbHeight)) {
Common::String buff = Common::String::format("%i x %i", thumbWidth, thumbWidth);
fatal("Invalid thumbnail size", buff);
return BR_ERROR;
@@ -2479,16 +2447,16 @@ builtIn(setThumbnailSize) {
builtIn(hasFlag) {
UNUSEDALL
int objNum, flagIndex;
- if (!getValueType(flagIndex, SVT_INT, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(flagIndex, SVT_INT))
return BR_ERROR;
trimStack(fun->stack);
- if (!getValueType(objNum, SVT_OBJTYPE, fun->stack->thisVar))
+ if (!fun->stack->thisVar.getValueType(objNum, SVT_OBJTYPE))
return BR_ERROR;
trimStack(fun->stack);
ObjectType *objT = g_sludge->_objMan->findObjectType(objNum);
if (!objT)
return BR_ERROR;
- setVariable(fun->reg, SVT_INT, objT->flags & (1 << flagIndex));
+ fun->reg.setVariable(SVT_INT, objT->flags & (1 << flagIndex));
return BR_CONTINUE;
}
@@ -2506,9 +2474,9 @@ builtIn(snapshotClear) {
builtIn(bodgeFilenames) {
UNUSEDALL
bool lastValue = allowAnyFilename;
- allowAnyFilename = getBoolean(fun->stack->thisVar);
+ allowAnyFilename = fun->stack->thisVar.getBoolean();
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, lastValue);
+ fun->reg.setVariable(SVT_INT, lastValue);
return BR_CONTINUE;
}
@@ -2517,14 +2485,14 @@ builtIn(_rem_registryGetString) {
UNUSEDALL
trimStack(fun->stack);
trimStack(fun->stack);
- setVariable(fun->reg, SVT_INT, 0);
+ fun->reg.setVariable(SVT_INT, 0);
return BR_CONTINUE;
}
builtIn(quitWithFatalError) {
UNUSEDALL
- Common::String mess = getTextFromAnyVar(fun->stack->thisVar);
+ Common::String mess = fun->stack->thisVar.getTextFromAnyVar();
trimStack(fun->stack);
fatal(mess);
return BR_ERROR;
@@ -2555,14 +2523,14 @@ builtIn(_rem_setMaximumAA) {
builtIn(setBackgroundEffect) {
UNUSEDALL
bool done = blur_createSettings(numParams, fun->stack);
- setVariable(fun->reg, SVT_INT, done ? 1 : 0);
+ fun->reg.setVariable(SVT_INT, done ? 1 : 0);
return BR_CONTINUE;
}
builtIn(doBackgroundEffect) {
UNUSEDALL
bool done = blurScreen();
- setVariable(fun->reg, SVT_INT, done ? 1 : 0);
+ fun->reg.setVariable(SVT_INT, done ? 1 : 0);
return BR_CONTINUE;
}
@@ -2584,9 +2552,9 @@ BuiltReturn callBuiltIn(int whichFunc, int numParams, LoadedFunction *fun) {
}
if (whichFunc < NUM_FUNCS) {
- if (paramNum[whichFunc] != -1) {
- if (paramNum[whichFunc] != numParams) {
- Common::String buff = Common::String::format("Built in function must have %i parameter%s", paramNum[whichFunc], (paramNum[whichFunc] == 1) ? "" : "s");
+ if (builtInFunctionArray[whichFunc].paramNum != -1) {
+ if (builtInFunctionArray[whichFunc].paramNum != numParams) {
+ Common::String buff = Common::String::format("Built in function must have %i parameter%s", builtInFunctionArray[whichFunc].paramNum, (builtInFunctionArray[whichFunc].paramNum == 1) ? "" : "s");
Common::String msg = buff;
fatal(msg);
return BR_ERROR;
diff --git a/engines/sludge/builtin.h b/engines/sludge/builtin.h
index b2274c22e9..b7fa8b86ef 100644
--- a/engines/sludge/builtin.h
+++ b/engines/sludge/builtin.h
@@ -23,6 +23,8 @@
#ifndef SLUDGE_BUILTIN_H
#define SLUDGE_BUILTIN_H
+#include "sludge/allfiles.h"
+
namespace Sludge {
struct LoadedFunction;
diff --git a/engines/sludge/csludge.h b/engines/sludge/csludge.h
index 435a220a2d..cf0d6aaf43 100644
--- a/engines/sludge/csludge.h
+++ b/engines/sludge/csludge.h
@@ -25,7 +25,7 @@
namespace Sludge {
-enum sludgeCommand {
+enum SludgeCommand {
SLU_UNKNOWN,
SLU_RETURN,
SLU_BRANCH,
diff --git a/engines/sludge/cursors.cpp b/engines/sludge/cursors.cpp
index 0c7745e9ff..0ec46e2f17 100644
--- a/engines/sludge/cursors.cpp
+++ b/engines/sludge/cursors.cpp
@@ -44,18 +44,24 @@ CursorManager::~CursorManager() {
}
void CursorManager::init() {
- _mouseCursorAnim = makeNullAnim();
+ _mouseCursorAnim = new PersonaAnimation();
_mouseCursorFrameNum = 0;
_mouseCursorCountUp = 0;
}
void CursorManager::kill() {
- deleteAnim(_mouseCursorAnim);
+ if (_mouseCursorAnim) {
+ delete _mouseCursorAnim;
+ _mouseCursorAnim = nullptr;
+ }
_mouseCursorAnim = nullptr;
}
void CursorManager::pickAnimCursor(PersonaAnimation *pp) {
- deleteAnim(_mouseCursorAnim);
+ if (_mouseCursorAnim) {
+ delete _mouseCursorAnim;
+ _mouseCursorAnim = nullptr;
+ }
_mouseCursorAnim = pp;
_mouseCursorFrameNum = 0;
_mouseCursorCountUp = 0;
@@ -107,18 +113,21 @@ void CursorManager::pasteCursor(int x, int y, PersonaAnimation *c) {
void CursorManager::freeze(FrozenStuffStruct *frozenStuff) {
frozenStuff->mouseCursorAnim = _mouseCursorAnim;
frozenStuff->mouseCursorFrameNum = _mouseCursorFrameNum;
- _mouseCursorAnim = makeNullAnim();
+ _mouseCursorAnim = new PersonaAnimation();
_mouseCursorFrameNum = 0;
}
void CursorManager::resotre(FrozenStuffStruct *frozenStuff) {
- deleteAnim(_mouseCursorAnim);
+ if (_mouseCursorAnim) {
+ delete _mouseCursorAnim;
+ _mouseCursorAnim = nullptr;
+ }
_mouseCursorAnim = frozenStuff->mouseCursorAnim;
_mouseCursorFrameNum = frozenStuff->mouseCursorFrameNum;
}
void CursorManager::saveCursor(Common::WriteStream *stream) {
- saveAnim(_mouseCursorAnim, stream);
+ _mouseCursorAnim->save(stream);
stream->writeUint16BE(_mouseCursorFrameNum);
}
@@ -126,7 +135,7 @@ bool CursorManager::loadCursor(Common::SeekableReadStream *stream) {
_mouseCursorAnim = new PersonaAnimation;
if (!checkNew(_mouseCursorAnim))
return false;
- if (!loadAnim(_mouseCursorAnim, stream))
+ if (!_mouseCursorAnim->load(stream))
return false;
_mouseCursorFrameNum = stream->readUint16BE();
return true;
diff --git a/engines/sludge/cursors.h b/engines/sludge/cursors.h
index 4229900a94..f3c71c2560 100644
--- a/engines/sludge/cursors.h
+++ b/engines/sludge/cursors.h
@@ -53,7 +53,7 @@ public:
private:
SludgeEngine *_vm;
- PersonaAnimation *_mouseCursorAnim;
+ PersonaAnimation *_mouseCursorAnim;
int _mouseCursorFrameNum;
int _mouseCursorCountUp;
};
diff --git a/engines/sludge/detection.cpp b/engines/sludge/detection.cpp
index a530a5c796..8c5c0ac13d 100644
--- a/engines/sludge/detection.cpp
+++ b/engines/sludge/detection.cpp
@@ -86,11 +86,11 @@ public:
virtual const char *getName() const {
return "Sludge Engine";
}
-
+
virtual const char *getOriginalCopyright() const {
return "Copyright (C) 2000-2014 Hungry Software and contributors";
}
-
+
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
const Sludge::SludgeGameDescription *gd = (const Sludge::SludgeGameDescription *)desc;
if (gd) {
@@ -100,10 +100,10 @@ public:
}
// for fall back detection
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
};
-const ADGameDescription *SludgeMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ADDetectedGame SludgeMetaEngine::fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
// reset fallback description
s_fallbackDesc.desc.gameId = "sludge";
s_fallbackDesc.desc.extra = "";
@@ -147,9 +147,19 @@ const ADGameDescription *SludgeMetaEngine::fallbackDetect(const FileMap &allFile
s_fallbackFileNameBuffer[50] = '\0';
s_fallbackDesc.desc.filesDescriptions[0].fileName = s_fallbackFileNameBuffer;
- return (const ADGameDescription *)&s_fallbackDesc;
+ ADDetectedGame game;
+ game.desc = &s_fallbackDesc.desc;
+
+ FileProperties tmp;
+ if (getFileProperties(file->getParent(), allFiles, s_fallbackDesc.desc, fileName, tmp)) {
+ game.hasUnknownFiles = true;
+ game.matchedFiles[fileName] = tmp;
+ }
+
+ return game;
}
- return 0;
+
+ return ADDetectedGame();
}
#if PLUGIN_ENABLED_DYNAMIC(SLUDGE)
diff --git a/engines/sludge/event.cpp b/engines/sludge/event.cpp
index d5c453bdc1..098720b4c6 100644
--- a/engines/sludge/event.cpp
+++ b/engines/sludge/event.cpp
@@ -25,6 +25,7 @@
#include "sludge/event.h"
#include "sludge/freeze.h"
+#include "sludge/function.h"
#include "sludge/graphics.h"
#include "sludge/newfatal.h"
#include "sludge/region.h"
@@ -36,8 +37,6 @@ namespace Sludge {
extern Variable *launchResult;
extern VariableStack *noStack;
-extern ScreenRegion *overRegion;
-extern ScreenRegion *lastRegion;
EventManager::EventManager(SludgeEngine *vm) {
_vm = vm;
@@ -152,14 +151,14 @@ void EventManager::checkInput() {
bool EventManager::handleInput() {
static int l = 0;
- if (!g_sludge->launchMe.empty()) {
+ if (!_vm->launchMe.empty()) {
if (l) {
// Still paused because of spawned thingy...
} else {
l = 1;
- setVariable(*launchResult, SVT_INT, 0/*launch(launchMe) > 31*/); //TODO:false value
- g_sludge->launchMe.clear();
+ launchResult->setVariable(SVT_INT, 0/*launch(launchMe) > 31*/); //TODO:false value
+ _vm->launchMe.clear();
launchResult = nullptr;
}
return true;
@@ -167,8 +166,8 @@ bool EventManager::handleInput() {
l = 0;
}
- if (!overRegion)
- getOverRegion();
+ if (!_vm->_regionMan->getOverRegion())
+ _vm->_regionMan->updateOverRegion();
if (_input.justMoved) {
if (_currentEvents->func[kMoveMouse]) {
@@ -178,16 +177,16 @@ bool EventManager::handleInput() {
}
_input.justMoved = false;
- if (lastRegion != overRegion && _currentEvents->func[kFocus]) {
+ if (_vm-> _regionMan->isRegionChanged()&& _currentEvents->func[kFocus]) {
VariableStack *tempStack = new VariableStack;
if (!checkNew(tempStack))
return false;
- initVarNew(tempStack->thisVar);
+ ScreenRegion *overRegion = _vm->_regionMan->getOverRegion();
if (overRegion) {
- setVariable(tempStack->thisVar, SVT_OBJTYPE, overRegion->thisType->objectNum);
+ tempStack->thisVar.setVariable(SVT_OBJTYPE, overRegion->thisType->objectNum);
} else {
- setVariable(tempStack->thisVar, SVT_INT, 0);
+ tempStack->thisVar.setVariable(SVT_INT, 0);
}
tempStack->next = nullptr;
if (!startNewFunctionNum(_currentEvents->func[kFocus], 1, nullptr, tempStack))
@@ -321,8 +320,7 @@ bool EventManager::handleInput() {
VariableStack *tempStack = new VariableStack;
if (!checkNew(tempStack))
return false;
- initVarNew(tempStack->thisVar);
- makeTextVar(tempStack->thisVar, tempString);
+ tempStack->thisVar.makeTextVar(tempString);
tempStack->next = nullptr;
if (!startNewFunctionNum(_currentEvents->func[kSpace], 1, nullptr, tempStack))
return false;
@@ -333,7 +331,7 @@ bool EventManager::handleInput() {
_input.rightRelease = false;
_input.leftRelease = false;
_input.keyPressed = 0;
- lastRegion = overRegion;
+ _vm->_regionMan->updateLastRegion();
return true;
}
diff --git a/engines/sludge/event.h b/engines/sludge/event.h
index 015e9ea1cb..c07f7b87ad 100644
--- a/engines/sludge/event.h
+++ b/engines/sludge/event.h
@@ -69,7 +69,7 @@ public:
int &mouseY() { return _input.mouseY; }
// Events
- void setEventFunction(EventFunctions event, int funcNum) { _currentEvents->func[event] = funcNum; } ;
+ void setEventFunction(EventFunctions event, int funcNum) { _currentEvents->func[event] = funcNum; };
void loadHandlers(Common::SeekableReadStream *stream);
void saveHandlers(Common::WriteStream *stream);
bool freeze(FrozenStuffStruct *frozenStuff);
diff --git a/engines/sludge/fileset.cpp b/engines/sludge/fileset.cpp
index fcdec32335..c9c3e7a43b 100644
--- a/engines/sludge/fileset.cpp
+++ b/engines/sludge/fileset.cpp
@@ -48,12 +48,14 @@ void ResourceManager::init() {
_startOfSubIndex = 0;
_startOfObjectIndex = 0;
_startIndex = 0;
+ _allResourceNames.clear();
}
void ResourceManager::kill() {
if (_bigDataFile) {
delete _bigDataFile;
_bigDataFile = nullptr;
}
+ _allResourceNames.clear();
}
bool ResourceManager::openSubSlice(int num) {
@@ -216,6 +218,31 @@ void ResourceManager::finishAccess() {
_sliceBusy = false;
}
+void ResourceManager::readResourceNames(Common::SeekableReadStream *readStream) {
+ int numResourceNames = readStream->readUint16BE();
+ debugC(2, kSludgeDebugDataLoad, "numResourceNames %i", numResourceNames);
+ _allResourceNames.reserve(numResourceNames);
+
+ for (int fn = 0; fn < numResourceNames; fn++) {
+ _allResourceNames[fn].clear();
+ _allResourceNames[fn] = readString(readStream);
+ debugC(2, kSludgeDebugDataLoad, "Resource %i: %s", fn, _allResourceNames[fn].c_str());
+ }
+}
+
+const Common::String ResourceManager::resourceNameFromNum(int i) {
+ if (i == -1)
+ return "";
+
+ if (_allResourceNames.empty())
+ return "RESOURCE";
+
+ if (i < (int)_allResourceNames.size())
+ return _allResourceNames[i];
+
+ return "Unknown resource";
+}
+
void ResourceManager::setData(Common::File *fp) {
_bigDataFile = fp;
_startIndex = fp->pos();
diff --git a/engines/sludge/fileset.h b/engines/sludge/fileset.h
index 83200ceeb8..fb6a696f47 100644
--- a/engines/sludge/fileset.h
+++ b/engines/sludge/fileset.h
@@ -44,15 +44,23 @@ public:
bool openObjectSlice(int num);
Common::String getNumberedString(int value);
+ // Access control flag
bool startAccess();
void finishAccess();
+ // Resource names
+ void readResourceNames(Common::SeekableReadStream *readStream);
+ const Common::String resourceNameFromNum(int i);
+ bool hasResourceNames() { return !_allResourceNames.empty(); }
+
private:
bool _sliceBusy;
Common::File *_bigDataFile;
uint32 _startOfDataIndex, _startOfTextIndex, _startOfSubIndex, _startOfObjectIndex;
int32 _startIndex;
+ Common::Array<Common::String> _allResourceNames;
+
private:
static uint32 _cp1250ToUTF32[128];
Common::String convertString(const Common::String &s);
diff --git a/engines/sludge/floor.cpp b/engines/sludge/floor.cpp
index 71aa75cbe7..c51fcc4309 100644
--- a/engines/sludge/floor.cpp
+++ b/engines/sludge/floor.cpp
@@ -28,23 +28,33 @@
#include "sludge/graphics.h"
#include "sludge/moreio.h"
#include "sludge/newfatal.h"
+#include "sludge/people.h"
#include "sludge/sludge.h"
+#define ANGLEFIX (180.0 / 3.14157)
+
namespace Sludge {
-Floor *currentFloor = NULL;
+FloorManager::FloorManager(SludgeEngine *vm) {
+ _vm = vm;
+ _currentFloor = nullptr;
+}
-bool pointInFloorPolygon(FloorPolygon &floorPoly, int x, int y) {
+FloorManager::~FloorManager() {
+ kill();
+}
+
+bool FloorManager::pointInFloorPolygon(FloorPolygon &floorPoly, int x, int y) {
int i = 0, j, c = 0;
float xp_i, yp_i;
float xp_j, yp_j;
for (j = floorPoly.numVertices - 1; i < floorPoly.numVertices; j = i++) {
- xp_i = currentFloor->vertex[floorPoly.vertexID[i]].x;
- yp_i = currentFloor->vertex[floorPoly.vertexID[i]].y;
- xp_j = currentFloor->vertex[floorPoly.vertexID[j]].x;
- yp_j = currentFloor->vertex[floorPoly.vertexID[j]].y;
+ xp_i = _currentFloor->vertex[floorPoly.vertexID[i]].x;
+ yp_i = _currentFloor->vertex[floorPoly.vertexID[i]].y;
+ xp_j = _currentFloor->vertex[floorPoly.vertexID[j]].x;
+ yp_j = _currentFloor->vertex[floorPoly.vertexID[j]].y;
if ((((yp_i <= y) && (y < yp_j)) || ((yp_j <= y) && (y < yp_i))) && (x < (xp_j - xp_i) * (y - yp_i) / (yp_j - yp_i) + xp_i)) {
c = !c;
@@ -53,7 +63,7 @@ bool pointInFloorPolygon(FloorPolygon &floorPoly, int x, int y) {
return c;
}
-bool getMatchingCorners(FloorPolygon &a, FloorPolygon &b, int &cornerA, int &cornerB) {
+bool FloorManager::getMatchingCorners(FloorPolygon &a, FloorPolygon &b, int &cornerA, int &cornerB) {
int sharedVertices = 0;
int i, j;
@@ -73,7 +83,7 @@ bool getMatchingCorners(FloorPolygon &a, FloorPolygon &b, int &cornerA, int &cor
return false;
}
-bool polysShareSide(FloorPolygon &a, FloorPolygon &b) {
+bool FloorManager::polysShareSide(FloorPolygon &a, FloorPolygon &b) {
int sharedVertices = 0;
int i, j;
@@ -89,46 +99,45 @@ bool polysShareSide(FloorPolygon &a, FloorPolygon &b) {
return false;
}
-void noFloor() {
- currentFloor->numPolygons = 0;
- currentFloor->polygon = NULL;
- currentFloor->vertex = NULL;
- currentFloor->matrix = NULL;
-}
-
-bool initFloor() {
- currentFloor = new Floor;
- if (!checkNew(currentFloor))
+bool FloorManager::init() {
+ _currentFloor = new Floor;
+ if (!checkNew(_currentFloor))
return false;
- noFloor();
+ _currentFloor->numPolygons = 0;
+ _currentFloor->polygon = nullptr;
+ _currentFloor->vertex = nullptr;
+ _currentFloor->matrix = nullptr;
return true;
}
-void killFloor() {
- if (currentFloor) {
- for (int i = 0; i < currentFloor->numPolygons; i++) {
- delete []currentFloor->polygon[i].vertexID;
- delete []currentFloor->matrix[i];
+void FloorManager::setFloorNull() {
+ if (_currentFloor) {
+ for (int i = 0; i < _currentFloor->numPolygons; i++) {
+ delete[] _currentFloor->polygon[i].vertexID;
+ delete[] _currentFloor->matrix[i];
}
- delete []currentFloor->polygon;
- currentFloor->polygon = NULL;
- delete []currentFloor->vertex;
- currentFloor->vertex = NULL;
- delete []currentFloor->matrix;
- currentFloor->matrix = NULL;
+ delete[] _currentFloor->polygon;
+ _currentFloor->polygon = nullptr;
+ delete[] _currentFloor->vertex;
+ _currentFloor->vertex = nullptr;
+ delete[] _currentFloor->matrix;
+ _currentFloor->matrix = nullptr;
}
}
-void setFloorNull() {
- killFloor();
- noFloor();
+void FloorManager::kill() {
+ setFloorNull();
+ if (_currentFloor) {
+ delete _currentFloor;
+ _currentFloor = nullptr;
+ }
}
-bool setFloor(int fileNum) {
+bool FloorManager::setFloor(int fileNum) {
int i, j;
- killFloor();
+ setFloorNull();
setResourceForFatal(fileNum);
@@ -137,73 +146,73 @@ bool setFloor(int fileNum) {
// Find out how many polygons there are and reserve memory
- currentFloor->originalNum = fileNum;
- currentFloor->numPolygons = g_sludge->_resMan->getData()->readByte();
- currentFloor->polygon = new FloorPolygon[currentFloor->numPolygons];
- if (!checkNew(currentFloor->polygon))
+ _currentFloor->originalNum = fileNum;
+ _currentFloor->numPolygons = g_sludge->_resMan->getData()->readByte();
+ _currentFloor->polygon = new FloorPolygon[_currentFloor->numPolygons];
+ if (!checkNew(_currentFloor->polygon))
return false;
// Read in each polygon
- for (i = 0; i < currentFloor->numPolygons; i++) {
+ for (i = 0; i < _currentFloor->numPolygons; i++) {
// Find out how many vertex IDs there are and reserve memory
- currentFloor->polygon[i].numVertices = g_sludge->_resMan->getData()->readByte();
- currentFloor->polygon[i].vertexID = new int[currentFloor->polygon[i].numVertices];
- if (!checkNew(currentFloor->polygon[i].vertexID))
+ _currentFloor->polygon[i].numVertices = g_sludge->_resMan->getData()->readByte();
+ _currentFloor->polygon[i].vertexID = new int[_currentFloor->polygon[i].numVertices];
+ if (!checkNew(_currentFloor->polygon[i].vertexID))
return false;
// Read in each vertex ID
- for (j = 0; j < currentFloor->polygon[i].numVertices; j++) {
- currentFloor->polygon[i].vertexID[j] = g_sludge->_resMan->getData()->readUint16BE();
+ for (j = 0; j < _currentFloor->polygon[i].numVertices; j++) {
+ _currentFloor->polygon[i].vertexID[j] = g_sludge->_resMan->getData()->readUint16BE();
}
}
// Find out how many vertices there are and reserve memory
i = g_sludge->_resMan->getData()->readUint16BE();
- currentFloor->vertex = new Common::Point[i];
- if (!checkNew(currentFloor->vertex))
+ _currentFloor->vertex = new Common::Point[i];
+ if (!checkNew(_currentFloor->vertex))
return false;
for (j = 0; j < i; j++) {
- currentFloor->vertex[j].x = g_sludge->_resMan->getData()->readUint16BE();
- currentFloor->vertex[j].y = g_sludge->_resMan->getData()->readUint16BE();
+ _currentFloor->vertex[j].x = g_sludge->_resMan->getData()->readUint16BE();
+ _currentFloor->vertex[j].y = g_sludge->_resMan->getData()->readUint16BE();
}
g_sludge->_resMan->finishAccess();
// Now build the movement martix
- currentFloor->matrix = new int *[currentFloor->numPolygons];
- int **distanceMatrix = new int *[currentFloor->numPolygons];
+ _currentFloor->matrix = new int *[_currentFloor->numPolygons];
+ int **distanceMatrix = new int *[_currentFloor->numPolygons];
- if (!checkNew(currentFloor->matrix))
+ if (!checkNew(_currentFloor->matrix))
return false;
- for (i = 0; i < currentFloor->numPolygons; i++) {
- currentFloor->matrix[i] = new int[currentFloor->numPolygons];
- distanceMatrix[i] = new int[currentFloor->numPolygons];
- if (!checkNew(currentFloor->matrix[i]))
+ for (i = 0; i < _currentFloor->numPolygons; i++) {
+ _currentFloor->matrix[i] = new int[_currentFloor->numPolygons];
+ distanceMatrix[i] = new int[_currentFloor->numPolygons];
+ if (!checkNew(_currentFloor->matrix[i]))
return false;
- for (j = 0; j < currentFloor->numPolygons; j++) {
- currentFloor->matrix[i][j] = -1;
+ for (j = 0; j < _currentFloor->numPolygons; j++) {
+ _currentFloor->matrix[i][j] = -1;
distanceMatrix[i][j] = 10000;
}
}
- for (i = 0; i < currentFloor->numPolygons; i++) {
- for (j = 0; j < currentFloor->numPolygons; j++) {
+ for (i = 0; i < _currentFloor->numPolygons; i++) {
+ for (j = 0; j < _currentFloor->numPolygons; j++) {
if (i != j) {
- if (polysShareSide(currentFloor->polygon[i], currentFloor->polygon[j])) {
- currentFloor->matrix[i][j] = j;
+ if (polysShareSide(_currentFloor->polygon[i], _currentFloor->polygon[j])) {
+ _currentFloor->matrix[i][j] = j;
distanceMatrix[i][j] = 1;
}
} else {
- currentFloor->matrix[i][j] = -2;
+ _currentFloor->matrix[i][j] = -2;
distanceMatrix[i][j] = 0;
}
}
@@ -214,17 +223,16 @@ bool setFloor(int fileNum) {
do {
lookForDistance++;
-// debugMatrix ();
madeChange = false;
- for (i = 0; i < currentFloor->numPolygons; i++) {
- for (j = 0; j < currentFloor->numPolygons; j++) {
- if (currentFloor->matrix[i][j] == -1) {
+ for (i = 0; i < _currentFloor->numPolygons; i++) {
+ for (j = 0; j < _currentFloor->numPolygons; j++) {
+ if (_currentFloor->matrix[i][j] == -1) {
// OK, so we don't know how to get from i to j...
- for (int d = 0; d < currentFloor->numPolygons; d++) {
+ for (int d = 0; d < _currentFloor->numPolygons; d++) {
if (d != i && d != j) {
- if (currentFloor->matrix[i][d] == d && currentFloor->matrix[d][j] >= 0 && distanceMatrix[d][j] <= lookForDistance) {
- currentFloor->matrix[i][j] = d;
+ if (_currentFloor->matrix[i][d] == d && _currentFloor->matrix[d][j] >= 0 && distanceMatrix[d][j] <= lookForDistance) {
+ _currentFloor->matrix[i][j] = d;
distanceMatrix[i][j] = lookForDistance + 1;
madeChange = true;
}
@@ -235,44 +243,44 @@ bool setFloor(int fileNum) {
}
} while (madeChange);
- for (i = 0; i < currentFloor->numPolygons; i++) {
+ for (i = 0; i < _currentFloor->numPolygons; i++) {
delete[] distanceMatrix[i];
}
delete []distanceMatrix;
- distanceMatrix = NULL;
+ distanceMatrix = nullptr;
setResourceForFatal(-1);
return true;
}
-void drawFloor() {
+void FloorManager::drawFloor() {
int i, j, nV;
- for (i = 0; i < currentFloor->numPolygons; i++) {
- nV = currentFloor->polygon[i].numVertices;
+ for (i = 0; i < _currentFloor->numPolygons; i++) {
+ nV = _currentFloor->polygon[i].numVertices;
if (nV > 1) {
for (j = 1; j < nV; j++) {
- g_sludge->_gfxMan->drawLine(currentFloor->vertex[currentFloor->polygon[i].vertexID[j - 1]].x, currentFloor->vertex[currentFloor->polygon[i].vertexID[j - 1]].y,
- currentFloor->vertex[currentFloor->polygon[i].vertexID[j]].x, currentFloor->vertex[currentFloor->polygon[i].vertexID[j]].y);
+ g_sludge->_gfxMan->drawLine(_currentFloor->vertex[_currentFloor->polygon[i].vertexID[j - 1]].x, _currentFloor->vertex[_currentFloor->polygon[i].vertexID[j - 1]].y,
+ _currentFloor->vertex[_currentFloor->polygon[i].vertexID[j]].x, _currentFloor->vertex[_currentFloor->polygon[i].vertexID[j]].y);
}
- g_sludge->_gfxMan->drawLine(currentFloor->vertex[currentFloor->polygon[i].vertexID[0]].x, currentFloor->vertex[currentFloor->polygon[i].vertexID[0]].y,
- currentFloor->vertex[currentFloor->polygon[i].vertexID[nV - 1]].x, currentFloor->vertex[currentFloor->polygon[i].vertexID[nV - 1]].y);
+ g_sludge->_gfxMan->drawLine(_currentFloor->vertex[_currentFloor->polygon[i].vertexID[0]].x, _currentFloor->vertex[_currentFloor->polygon[i].vertexID[0]].y,
+ _currentFloor->vertex[_currentFloor->polygon[i].vertexID[nV - 1]].x, _currentFloor->vertex[_currentFloor->polygon[i].vertexID[nV - 1]].y);
}
}
}
-int inFloor(int x, int y) {
+int FloorManager::inFloor(int x, int y) {
int i, r = -1;
- for (i = 0; i < currentFloor->numPolygons; i++)
- if (pointInFloorPolygon(currentFloor->polygon[i], x, y))
+ for (i = 0; i < _currentFloor->numPolygons; i++)
+ if (pointInFloorPolygon(_currentFloor->polygon[i], x, y))
r = i;
return r;
}
-bool closestPointOnLine(int &closestX, int &closestY, int x1, int y1, int x2, int y2, int xP, int yP) {
+bool FloorManager::closestPointOnLine(int &closestX, int &closestY, int x1, int y1, int x2, int y2, int xP, int yP) {
int xDiff = x2 - x1;
int yDiff = y2 - y1;
@@ -293,4 +301,126 @@ bool closestPointOnLine(int &closestX, int &closestY, int x1, int y1, int x2, in
return false;
}
+bool FloorManager::handleClosestPoint(int &setX, int &setY, int &setPoly) {
+ int gotX = 320, gotY = 200, gotPoly = -1, i, j, xTest1, yTest1, xTest2, yTest2, closestX, closestY, oldJ, currentDistance = 0xFFFFF, thisDistance;
+
+ for (i = 0; i < _currentFloor->numPolygons; i++) {
+ oldJ = _currentFloor->polygon[i].numVertices - 1;
+ for (j = 0; j < _currentFloor->polygon[i].numVertices; j++) {
+ xTest1 = _currentFloor->vertex[_currentFloor->polygon[i].vertexID[j]].x;
+ yTest1 = _currentFloor->vertex[_currentFloor->polygon[i].vertexID[j]].y;
+ xTest2 = _currentFloor->vertex[_currentFloor->polygon[i].vertexID[oldJ]].x;
+ yTest2 = _currentFloor->vertex[_currentFloor->polygon[i].vertexID[oldJ]].y;
+ closestPointOnLine(closestX, closestY, xTest1, yTest1, xTest2, yTest2, setX, setY);
+ xTest1 = setX - closestX;
+ yTest1 = setY - closestY;
+ thisDistance = xTest1 * xTest1 + yTest1 * yTest1;
+
+ if (thisDistance < currentDistance) {
+ currentDistance = thisDistance;
+ gotX = closestX;
+ gotY = closestY;
+ gotPoly = i;
+ }
+ oldJ = j;
+ }
+ }
+
+ if (gotPoly == -1)
+ return false;
+ setX = gotX;
+ setY = gotY;
+ setPoly = gotPoly;
+ return true;
+}
+
+bool FloorManager::doBorderStuff(OnScreenPerson *moveMe) {
+ if (moveMe->inPoly == moveMe->walkToPoly) {
+ moveMe->inPoly = -1;
+ moveMe->thisStepX = moveMe->walkToX;
+ moveMe->thisStepY = moveMe->walkToY;
+ } else {
+ // The section in which we need to be next...
+ int newPoly = _currentFloor->matrix[moveMe->inPoly][moveMe->walkToPoly];
+ if (newPoly == -1)
+ return false;
+
+ // Grab the index of the second matching corner...
+ int ID, ID2;
+ if (!getMatchingCorners(_currentFloor->polygon[moveMe->inPoly], _currentFloor->polygon[newPoly], ID, ID2))
+ return fatal("Not a valid floor plan!");
+
+ // Remember that we're walking to the new polygon...
+ moveMe->inPoly = newPoly;
+
+ // Calculate the destination position on the coincidantal line...
+ int x1 = moveMe->x, y1 = moveMe->y;
+ int x2 = moveMe->walkToX, y2 = moveMe->walkToY;
+ int x3 = _currentFloor->vertex[ID].x, y3 = _currentFloor->vertex[ID].y;
+ int x4 = _currentFloor->vertex[ID2].x, y4 = _currentFloor->vertex[ID2].y;
+
+ int xAB = x1 - x2;
+ int yAB = y1 - y2;
+ int xCD = x4 - x3;
+ int yCD = y4 - y3;
+
+ double m = (yAB * (x3 - x1) - xAB * (y3 - y1));
+ m /= ((xAB * yCD) - (yAB * xCD));
+
+ if (m > 0 && m < 1) {
+ moveMe->thisStepX = x3 + m * xCD;
+ moveMe->thisStepY = y3 + m * yCD;
+ } else {
+ int dx13 = x1 - x3, dx14 = x1 - x4, dx23 = x2 - x3, dx24 = x2 - x4;
+ int dy13 = y1 - y3, dy14 = y1 - y4, dy23 = y2 - y3, dy24 = y2 - y4;
+
+ dx13 *= dx13;
+ dx14 *= dx14;
+ dx23 *= dx23;
+ dx24 *= dx24;
+ dy13 *= dy13;
+ dy14 *= dy14;
+ dy23 *= dy23;
+ dy24 *= dy24;
+
+ if (sqrt((double)dx13 + dy13) + sqrt((double)dx23 + dy23) < sqrt((double)dx14 + dy14) + sqrt((double)dx24 + dy24)) {
+ moveMe->thisStepX = x3;
+ moveMe->thisStepY = y3;
+ } else {
+ moveMe->thisStepX = x4;
+ moveMe->thisStepY = y4;
+ }
+ }
+ }
+
+ float yDiff = moveMe->thisStepY - moveMe->y;
+ float xDiff = moveMe->x - moveMe->thisStepX;
+ if (xDiff || yDiff) {
+ moveMe->wantAngle = 180 + ANGLEFIX * atan2(xDiff, yDiff * 2);
+ moveMe->spinning = true;
+ }
+
+ moveMe->makeTalker();
+ return true;
+}
+
+void FloorManager::save(Common::WriteStream *stream) {
+ if (_currentFloor->numPolygons) {
+ stream->writeByte(1);
+ stream->writeUint16BE(_currentFloor->originalNum);
+ } else {
+ stream->writeByte(0);
+ }
+}
+
+bool FloorManager::load(Common::SeekableReadStream *stream) {
+ if (stream->readByte()) {
+ if (!setFloor(stream->readUint16BE()))
+ return false;
+ } else {
+ setFloorNull();
+ }
+ return true;
+}
+
} // End of namespace Sludge
diff --git a/engines/sludge/floor.h b/engines/sludge/floor.h
index 4db7e22deb..22c8b12f30 100644
--- a/engines/sludge/floor.h
+++ b/engines/sludge/floor.h
@@ -26,6 +26,9 @@
namespace Sludge {
+class SludgeEngine;
+struct OnScreenPerson;
+
struct FloorPolygon {
int numVertices;
int *vertexID;
@@ -39,13 +42,37 @@ struct Floor {
int **matrix;
};
-bool initFloor();
-void setFloorNull();
-bool setFloor(int fileNum);
-void drawFloor();
-int inFloor(int x, int y);
-bool getMatchingCorners(FloorPolygon &, FloorPolygon &, int &, int &);
-bool closestPointOnLine(int &closestX, int &closestY, int x1, int y1, int x2, int y2, int xP, int yP);
+class FloorManager {
+public:
+ FloorManager(SludgeEngine *vm);
+ ~FloorManager();
+
+ bool init();
+ void kill();
+
+ void setFloorNull();
+ bool setFloor(int fileNum);
+ void drawFloor();
+ int inFloor(int x, int y);
+ bool isFloorNoPolygon() { return !_currentFloor || _currentFloor->numPolygons == 0; }
+
+ // For Person collision detection
+ bool handleClosestPoint(int &setX, int &setY, int &setPoly);
+ bool doBorderStuff(OnScreenPerson *moveMe);
+
+ // Save & load
+ void save(Common::WriteStream *stream);
+ bool load(Common::SeekableReadStream *stream);
+
+private:
+ Floor *_currentFloor;
+ SludgeEngine *_vm;
+
+ bool getMatchingCorners(FloorPolygon &, FloorPolygon &, int &, int &);
+ bool closestPointOnLine(int &closestX, int &closestY, int x1, int y1, int x2, int y2, int xP, int yP);
+ bool pointInFloorPolygon(FloorPolygon &floorPoly, int x, int y);
+ bool polysShareSide(FloorPolygon &a, FloorPolygon &b);
+};
} // End of namespace Sludge
diff --git a/engines/sludge/fonttext.cpp b/engines/sludge/fonttext.cpp
index 0f63c6e24f..da380f4f0b 100644
--- a/engines/sludge/fonttext.cpp
+++ b/engines/sludge/fonttext.cpp
@@ -48,11 +48,13 @@ void TextManager::init() {
_loadedFontNum = 0;
_fontSpace = -1;
+ _pastePalette.init();
_fontTable.clear();
}
void TextManager::kill() {
GraphicsManager::forgetSpriteBank(_theFont);
+ _pastePalette.kill();
}
bool TextManager::isInFont(const Common::String &theText) {
@@ -110,7 +112,7 @@ void TextManager::pasteString(const Common::String &theText, int xOff, int y, Sp
}
}
-void TextManager::pasteStringToBackdrop(const Common::String &theText, int xOff, int y, SpritePalette &thePal) {
+void TextManager::pasteStringToBackdrop(const Common::String &theText, int xOff, int y) {
if (_fontTable.empty())
return;
@@ -120,12 +122,12 @@ void TextManager::pasteStringToBackdrop(const Common::String &theText, int xOff,
for (uint32 i = 0; i < str32.size(); ++i) {
uint32 c = str32[i];
Sprite *mySprite = &_theFont.sprites[fontInTable(c)];
- g_sludge->_gfxMan->pasteSpriteToBackDrop(xOff, y, *mySprite, thePal);
+ g_sludge->_gfxMan->pasteSpriteToBackDrop(xOff, y, *mySprite, _pastePalette);
xOff += mySprite->surface.w + _fontSpace;
}
}
-void TextManager::burnStringToBackdrop(const Common::String &theText, int xOff, int y, SpritePalette &thePal) {
+void TextManager::burnStringToBackdrop(const Common::String &theText, int xOff, int y) {
if (_fontTable.empty())
return;
@@ -135,17 +137,11 @@ void TextManager::burnStringToBackdrop(const Common::String &theText, int xOff,
for (uint i = 0; i < str32.size(); ++i) {
uint32 c = str32[i];
Sprite *mySprite = &_theFont.sprites[fontInTable(c)];
- g_sludge->_gfxMan->burnSpriteToBackDrop(xOff, y, *mySprite, thePal);
+ g_sludge->_gfxMan->burnSpriteToBackDrop(xOff, y, *mySprite, _pastePalette);
xOff += mySprite->surface.w + _fontSpace;
}
}
-void setFontColour(SpritePalette &sP, byte r, byte g, byte b) {
- sP.originalRed = r;
- sP.originalGreen = g;
- sP.originalBlue = b;
-}
-
bool TextManager::loadFont(int filenum, const Common::String &charOrder, int h) {
_fontOrder.setUTF8String(charOrder);
diff --git a/engines/sludge/fonttext.h b/engines/sludge/fonttext.h
index 26b12d9f11..7018c75213 100644
--- a/engines/sludge/fonttext.h
+++ b/engines/sludge/fonttext.h
@@ -46,12 +46,14 @@ public:
bool loadFont(int filenum, const Common::String &charOrder, int);
void pasteString(const Common::String &theText, int, int, SpritePalette &);
- void pasteStringToBackdrop(const Common::String &theText, int xOff, int y, SpritePalette &thePal);
- void burnStringToBackdrop(const Common::String &theText, int xOff, int y, SpritePalette &thePal);
+ void pasteStringToBackdrop(const Common::String &theText, int xOff, int y);
+ void burnStringToBackdrop(const Common::String &theText, int xOff, int y);
bool isInFont(const Common::String &theText);
+ // setter & getter
void setFontSpace(int fontSpace) { _fontSpace = fontSpace; }
int getFontHeight() const { return _fontHeight; }
+ void setPasterColor(byte r, byte g, byte b) { _pastePalette.setColor(r, g, b); }
// load & save
void saveFont(Common::WriteStream *stream);
@@ -62,6 +64,7 @@ private:
int _fontHeight, _numFontColours, _loadedFontNum;
UTF8Converter _fontOrder;
int16 _fontSpace;
+ SpritePalette _pastePalette;
Common::HashMap<uint32, uint32> _fontTable;
@@ -69,8 +72,6 @@ private:
};
-void setFontColour(SpritePalette &sP, byte r, byte g, byte b);
-
} // End of namespace Sludge
#endif
diff --git a/engines/sludge/freeze.cpp b/engines/sludge/freeze.cpp
index e90f2700d8..9f8c85e828 100644
--- a/engines/sludge/freeze.cpp
+++ b/engines/sludge/freeze.cpp
@@ -41,10 +41,6 @@
namespace Sludge {
-extern OnScreenPerson *allPeople;
-extern ScreenRegion *allScreenRegions;
-extern ScreenRegion *overRegion;
-
void GraphicsManager::freezeGraphics() {
int w = _winWidth;
@@ -87,18 +83,14 @@ bool GraphicsManager::freeze() {
_backdropSurface.copyFrom(_freezeSurface);
_backdropExists = true;
- newFreezer->allPeople = allPeople;
- allPeople = NULL;
+ _vm->_peopleMan->freeze(newFreezer);
- StatusStuff *newStatusStuff = new StatusStuff ;
+ StatusStuff *newStatusStuff = new StatusStuff;
if (!checkNew(newStatusStuff))
return false;
newFreezer->frozenStatus = copyStatusBarStuff(newStatusStuff);
- newFreezer->allScreenRegions = allScreenRegions;
- allScreenRegions = NULL;
- overRegion = NULL;
-
+ _vm->_regionMan->freeze(newFreezer);
_vm->_cursorMan->freeze(newFreezer);
_vm->_speechMan->freeze(newFreezer);
_vm->_evtMan->freeze(newFreezer);
@@ -136,11 +128,8 @@ void GraphicsManager::unfreeze(bool killImage) {
_vm->_evtMan->mouseX() = (int)(_vm->_evtMan->mouseX() / _cameraZoom);
_vm->_evtMan->mouseY() = (int)(_vm->_evtMan->mouseY() / _cameraZoom);
- killAllPeople();
- allPeople = _frozenStuff->allPeople;
-
- killAllRegions();
- allScreenRegions = _frozenStuff->allScreenRegions;
+ g_sludge->_peopleMan->resotre(_frozenStuff);
+ g_sludge->_regionMan->resotre(_frozenStuff);
killLightMap();
@@ -171,7 +160,6 @@ void GraphicsManager::unfreeze(bool killImage) {
_vm->_speechMan->restore(_frozenStuff);
_frozenStuff = _frozenStuff->next;
- overRegion = NULL;
// free current frozen screen struct
if (killMe->backdropSurface.getPixels())
diff --git a/engines/sludge/freeze.h b/engines/sludge/freeze.h
index 830c2d8a72..4a7740887f 100644
--- a/engines/sludge/freeze.h
+++ b/engines/sludge/freeze.h
@@ -30,14 +30,18 @@ struct OnScreenPerson;
struct PersonaAnimation;
struct ScreenRegion;
struct SpeechStruct;
-struct StatusStuff ;
+struct StatusStuff;
struct EventHandlers;
+struct ScreenRegion;
+
+typedef Common::List<ScreenRegion *> ScreenRegionList;
+typedef Common::List<OnScreenPerson *> OnScreenPersonList;
class Parallax;
struct FrozenStuffStruct {
- OnScreenPerson *allPeople;
- ScreenRegion *allScreenRegions;
+ OnScreenPersonList *allPeople;
+ ScreenRegionList *allScreenRegions;
Graphics::Surface backdropSurface;
Graphics::Surface lightMapSurface;
Graphics::Surface *zBufferSprites;
diff --git a/engines/sludge/function.cpp b/engines/sludge/function.cpp
new file mode 100644
index 0000000000..553e59d76c
--- /dev/null
+++ b/engines/sludge/function.cpp
@@ -0,0 +1,788 @@
+/* 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 "sludge/builtin.h"
+#include "sludge/function.h"
+#include "sludge/loadsave.h"
+#include "sludge/newfatal.h"
+#include "sludge/people.h"
+#include "sludge/sludge.h"
+#include "sludge/sound.h"
+#include "sludge/speech.h"
+
+namespace Sludge {
+
+int numBIFNames = 0;
+Common::String *allBIFNames = NULL;
+int numUserFunc = 0;
+Common::String *allUserFunc = NULL;
+
+LoadedFunction *saverFunc;
+LoadedFunction *allRunningFunctions = NULL;
+VariableStack *noStack = NULL;
+Variable *globalVars = NULL;
+
+const char *sludgeText[] = { "?????", "RETURN", "BRANCH", "BR_ZERO",
+ "SET_GLOBAL", "SET_LOCAL", "LOAD_GLOBAL", "LOAD_LOCAL", "PLUS", "MINUS",
+ "MULT", "DIVIDE", "AND", "OR", "EQUALS", "NOT_EQ", "MODULUS",
+ "LOAD_VALUE", "LOAD_BUILT", "LOAD_FUNC", "CALLIT", "LOAD_STRING",
+ "LOAD_FILE", "LOAD_OBJTYPE", "NOT", "LOAD_NULL", "STACK_PUSH",
+ "LESSTHAN", "MORETHAN", "NEGATIVE", "U", "LESS_EQUAL", "MORE_EQUAL",
+ "INC_LOCAL", "DEC_LOCAL", "INC_GLOBAL", "DEC_GLOBAL", "INDEXSET",
+ "INDEXGET", "INC_INDEX", "DEC_INDEX", "QUICK_PUSH" };
+
+void pauseFunction(LoadedFunction *fun) {
+ LoadedFunction **huntAndDestroy = &allRunningFunctions;
+ while (*huntAndDestroy) {
+ if (fun == *huntAndDestroy) {
+ (*huntAndDestroy) = (*huntAndDestroy)->next;
+ fun->next = NULL;
+ } else {
+ huntAndDestroy = &(*huntAndDestroy)->next;
+ }
+ }
+}
+
+void restartFunction(LoadedFunction *fun) {
+ fun->next = allRunningFunctions;
+ allRunningFunctions = fun;
+}
+
+void killSpeechTimers() {
+ LoadedFunction *thisFunction = allRunningFunctions;
+
+ while (thisFunction) {
+ if (thisFunction->freezerLevel == 0 && thisFunction->isSpeech
+ && thisFunction->timeLeft) {
+ thisFunction->timeLeft = 0;
+ thisFunction->isSpeech = false;
+ }
+ thisFunction = thisFunction->next;
+ }
+
+ g_sludge->_speechMan->kill();
+}
+
+void completeTimers() {
+ LoadedFunction *thisFunction = allRunningFunctions;
+
+ while (thisFunction) {
+ if (thisFunction->freezerLevel == 0)
+ thisFunction->timeLeft = 0;
+ thisFunction = thisFunction->next;
+ }
+}
+
+void finishFunction(LoadedFunction *fun) {
+ int a;
+
+ pauseFunction(fun);
+ if (fun->stack)
+ fatal(ERROR_NON_EMPTY_STACK);
+ delete[] fun->compiledLines;
+ for (a = 0; a < fun->numLocals; a++)
+ fun->localVars[a].unlinkVar();
+ delete[] fun->localVars;
+ fun->reg.unlinkVar();
+ delete fun;
+ fun = NULL;
+}
+
+void abortFunction(LoadedFunction *fun) {
+ int a;
+
+ pauseFunction(fun);
+ while (fun->stack)
+ trimStack(fun->stack);
+ delete []fun->compiledLines;
+ for (a = 0; a < fun->numLocals; a++)
+ fun->localVars[a].unlinkVar();
+ delete []fun->localVars;
+ fun->reg.unlinkVar();
+ if (fun->calledBy)
+ abortFunction(fun->calledBy);
+ delete fun;
+ fun = NULL;
+}
+
+int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself) {
+ int n = 0;
+ killedMyself = false;
+
+ LoadedFunction *fun = allRunningFunctions;
+ while (fun) {
+ if (fun->originalNumber == funcNum) {
+ fun->cancelMe = true;
+ n++;
+ if (fun == myself)
+ killedMyself = true;
+ }
+ fun = fun->next;
+ }
+ return n;
+}
+
+void freezeSubs() {
+ LoadedFunction *thisFunction = allRunningFunctions;
+
+ while (thisFunction) {
+ if (thisFunction->unfreezable) {
+ //msgBox ("SLUDGE debugging bollocks!", "Trying to freeze an unfreezable function!");
+ } else {
+ thisFunction->freezerLevel++;
+ }
+ thisFunction = thisFunction->next;
+ }
+}
+
+void unfreezeSubs() {
+ LoadedFunction *thisFunction = allRunningFunctions;
+
+ while (thisFunction) {
+ if (thisFunction->freezerLevel)
+ thisFunction->freezerLevel--;
+ thisFunction = thisFunction->next;
+ }
+}
+
+bool continueFunction(LoadedFunction *fun) {
+ bool keepLooping = true;
+ bool advanceNow;
+ uint param;
+ SludgeCommand com;
+
+ if (fun->cancelMe) {
+ abortFunction(fun);
+ return true;
+ }
+
+ while (keepLooping) {
+ advanceNow = true;
+ debugC(1, kSludgeDebugStackMachine, "Executing command line %i : ", fun->runThisLine);
+ param = fun->compiledLines[fun->runThisLine].param;
+ com = fun->compiledLines[fun->runThisLine].theCommand;
+
+ if (numBIFNames) {
+ setFatalInfo((fun->originalNumber < numUserFunc) ? allUserFunc[fun->originalNumber] : "Unknown user function", (com < numSludgeCommands) ? sludgeText[com] : ERROR_UNKNOWN_MCODE);
+ }
+
+ switch (com) {
+ case SLU_RETURN:
+ if (fun->calledBy) {
+ LoadedFunction *returnTo = fun->calledBy;
+ if (fun->returnSomething)
+ returnTo->reg.copyFrom(fun->reg);
+ finishFunction(fun);
+ fun = returnTo;
+ restartFunction(fun);
+ } else {
+ finishFunction(fun);
+ advanceNow = false; // So we don't do anything else with "fun"
+ keepLooping = false; // So we drop out of the loop
+ }
+ break;
+
+ case SLU_CALLIT:
+ switch (fun->reg.varType) {
+ case SVT_FUNC:
+ pauseFunction(fun);
+ if (numBIFNames)
+ setFatalInfo(
+ (fun->originalNumber < numUserFunc) ?
+ allUserFunc[fun->originalNumber] :
+ "Unknown user function",
+ (fun->reg.varData.intValue < numUserFunc) ?
+ allUserFunc[fun->reg.varData.intValue] :
+ "Unknown user function");
+
+ if (!startNewFunctionNum(fun->reg.varData.intValue, param, fun,
+ fun->stack))
+ return false;
+ fun = allRunningFunctions;
+ advanceNow = false; // So we don't do anything else with "fun"
+ break;
+
+ case SVT_BUILT: {
+ debugC(1, kSludgeDebugStackMachine, "Built-in init value: %i",
+ fun->reg.varData.intValue);
+ BuiltReturn br = callBuiltIn(fun->reg.varData.intValue, param,
+ fun);
+
+ switch (br) {
+ case BR_ERROR:
+ return fatal(
+ "Unknown error. This shouldn't happen. Please notify the SLUDGE developers.");
+
+ case BR_PAUSE:
+ pauseFunction(fun);
+ // fall through
+
+ case BR_KEEP_AND_PAUSE:
+ keepLooping = false;
+ break;
+
+ case BR_ALREADY_GONE:
+ keepLooping = false;
+ advanceNow = false;
+ break;
+
+ case BR_CALLAFUNC: {
+ int i = fun->reg.varData.intValue;
+ fun->reg.setVariable(SVT_INT, 1);
+ pauseFunction(fun);
+ if (numBIFNames)
+ setFatalInfo(
+ (fun->originalNumber < numUserFunc) ?
+ allUserFunc[fun->originalNumber] :
+ "Unknown user function",
+ (i < numUserFunc) ?
+ allUserFunc[i] :
+ "Unknown user function");
+ if (!startNewFunctionNum(i, 0, fun, noStack, false))
+ return false;
+ fun = allRunningFunctions;
+ advanceNow = false; // So we don't do anything else with "fun"
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ return fatal(ERROR_CALL_NONFUNCTION);
+ }
+ break;
+
+ // These all grab things and shove 'em into the register
+
+ case SLU_LOAD_NULL:
+ fun->reg.setVariable(SVT_NULL, 0);
+ break;
+
+ case SLU_LOAD_FILE:
+ fun->reg.setVariable(SVT_FILE, param);
+ break;
+
+ case SLU_LOAD_VALUE:
+ fun->reg.setVariable(SVT_INT, param);
+ break;
+
+ case SLU_LOAD_LOCAL:
+ if (!fun->reg.copyFrom(fun->localVars[param]))
+ return false;
+ break;
+
+ case SLU_AND:
+ fun->reg.setVariable(SVT_INT,
+ fun->reg.getBoolean() && fun->stack->thisVar.getBoolean());
+ trimStack(fun->stack);
+ break;
+
+ case SLU_OR:
+ fun->reg.setVariable(SVT_INT,
+ fun->reg.getBoolean() || fun->stack->thisVar.getBoolean());
+ trimStack(fun->stack);
+ break;
+
+ case SLU_LOAD_FUNC:
+ fun->reg.setVariable(SVT_FUNC, param);
+ break;
+
+ case SLU_LOAD_BUILT:
+ fun->reg.setVariable(SVT_BUILT, param);
+ break;
+
+ case SLU_LOAD_OBJTYPE:
+ fun->reg.setVariable(SVT_OBJTYPE, param);
+ break;
+
+ case SLU_UNREG:
+ break;
+
+ case SLU_LOAD_STRING:
+ if (!fun->reg.loadStringToVar(param)) {
+ return false;
+ }
+ break;
+
+ case SLU_INDEXGET:
+ case SLU_INCREMENT_INDEX:
+ case SLU_DECREMENT_INDEX:
+ switch (fun->stack->thisVar.varType) {
+ case SVT_NULL:
+ if (com == SLU_INDEXGET) {
+ fun->reg.setVariable(SVT_NULL, 0);
+ trimStack(fun->stack);
+ } else {
+ return fatal(ERROR_INCDEC_UNKNOWN);
+ }
+ break;
+
+ case SVT_FASTARRAY:
+ case SVT_STACK:
+ if (fun->stack->thisVar.varData.theStack->first == NULL) {
+ return fatal(ERROR_INDEX_EMPTY);
+ } else {
+ int ii;
+ if (!fun->reg.getValueType(ii, SVT_INT))
+ return false;
+ Variable *grab =
+ (fun->stack->thisVar.varType == SVT_FASTARRAY) ?
+ fun->stack->thisVar.varData.fastArray->fastArrayGetByIndex(ii) :
+ fun->stack->thisVar.varData.theStack->first->stackGetByIndex(ii);
+
+ trimStack(fun->stack);
+
+ if (!grab) {
+ fun->reg.setVariable(SVT_NULL, 0);
+ } else {
+ int kk;
+ switch (com) {
+ case SLU_INCREMENT_INDEX:
+ if (!grab->getValueType(kk, SVT_INT))
+ return false;
+ fun->reg.setVariable(SVT_INT, kk);
+ grab->varData.intValue = kk + 1;
+ break;
+
+ case SLU_DECREMENT_INDEX:
+ if (!grab->getValueType(kk, SVT_INT))
+ return false;
+ fun->reg.setVariable(SVT_INT, kk);
+ grab->varData.intValue = kk - 1;
+ break;
+
+ default:
+ if (!fun->reg.copyFrom(*grab))
+ return false;
+ }
+ }
+ }
+ break;
+
+ default:
+ return fatal(ERROR_INDEX_NONSTACK);
+ }
+ break;
+
+ case SLU_INDEXSET:
+ switch (fun->stack->thisVar.varType) {
+ case SVT_STACK:
+ if (fun->stack->thisVar.varData.theStack->first == NULL) {
+ return fatal(ERROR_INDEX_EMPTY);
+ } else {
+ int ii;
+ if (!fun->reg.getValueType(ii, SVT_INT))
+ return false;
+ if (!fun->stack->thisVar.varData.theStack->first->stackSetByIndex(ii, fun->stack->next->thisVar)) {
+ return false;
+ }
+ trimStack(fun->stack);
+ trimStack(fun->stack);
+ }
+ break;
+
+ case SVT_FASTARRAY: {
+ int ii;
+ if (!fun->reg.getValueType(ii, SVT_INT))
+ return false;
+ Variable *v = fun->stack->thisVar.varData.fastArray->fastArrayGetByIndex(ii);
+ if (v == NULL)
+ return fatal("Not within bounds of fast array.");
+ if (!v->copyFrom(fun->stack->next->thisVar))
+ return false;
+ trimStack(fun->stack);
+ trimStack(fun->stack);
+ }
+ break;
+
+ default:
+ return fatal(ERROR_INDEX_NONSTACK);
+ }
+ break;
+
+ // What can we do with the register? Well, we can copy it into a local
+ // variable, a global or onto the stack...
+
+ case SLU_INCREMENT_LOCAL: {
+ int ii;
+ if (!fun->localVars[param].getValueType(ii, SVT_INT))
+ return false;
+ fun->reg.setVariable(SVT_INT, ii);
+ fun->localVars[param].setVariable(SVT_INT, ii + 1);
+ }
+ break;
+
+ case SLU_INCREMENT_GLOBAL: {
+ int ii;
+ if (!globalVars[param].getValueType(ii, SVT_INT))
+ return false;
+ fun->reg.setVariable(SVT_INT, ii);
+ globalVars[param].setVariable(SVT_INT, ii + 1);
+ }
+ break;
+
+ case SLU_DECREMENT_LOCAL: {
+ int ii;
+ if (!fun->localVars[param].getValueType(ii, SVT_INT))
+ return false;
+ fun->reg.setVariable(SVT_INT, ii);
+ fun->localVars[param].setVariable(SVT_INT, ii - 1);
+ }
+ break;
+
+ case SLU_DECREMENT_GLOBAL: {
+ int ii;
+ if (!globalVars[param].getValueType(ii, SVT_INT))
+ return false;
+ fun->reg.setVariable(SVT_INT, ii);
+ globalVars[param].setVariable(SVT_INT, ii - 1);
+ }
+ break;
+
+ case SLU_SET_LOCAL:
+ if (!fun->localVars[param].copyFrom(fun->reg))
+ return false;
+ break;
+
+ case SLU_SET_GLOBAL:
+ if (!globalVars[param].copyFrom(fun->reg))
+ return false;
+ break;
+
+ case SLU_LOAD_GLOBAL:
+ if (!fun->reg.copyFrom(globalVars[param]))
+ return false;
+ break;
+
+ case SLU_STACK_PUSH:
+ if (!addVarToStack(fun->reg, fun->stack))
+ return false;
+ break;
+
+ case SLU_QUICK_PUSH:
+ if (!addVarToStackQuick(fun->reg, fun->stack))
+ return false;
+ break;
+
+ case SLU_NOT:
+ fun->reg.setVariable(SVT_INT, !fun->reg.getBoolean());
+ break;
+
+ case SLU_BR_ZERO:
+ if (!fun->reg.getBoolean()) {
+ advanceNow = false;
+ fun->runThisLine = param;
+ }
+ break;
+
+ case SLU_BRANCH:
+ advanceNow = false;
+ fun->runThisLine = param;
+ break;
+
+ case SLU_NEGATIVE: {
+ int i;
+ if (!fun->reg.getValueType(i, SVT_INT))
+ return false;
+ fun->reg.setVariable(SVT_INT, -i);
+ }
+ break;
+
+ // All these things rely on there being somet' on the stack
+
+ case SLU_MULT:
+ case SLU_PLUS:
+ case SLU_MINUS:
+ case SLU_MODULUS:
+ case SLU_DIVIDE:
+ case SLU_EQUALS:
+ case SLU_NOT_EQ:
+ case SLU_LESSTHAN:
+ case SLU_MORETHAN:
+ case SLU_LESS_EQUAL:
+ case SLU_MORE_EQUAL:
+ if (fun->stack) {
+ int firstValue, secondValue;
+
+ switch (com) {
+ case SLU_PLUS:
+ fun->reg.addVariablesInSecond(fun->stack->thisVar);
+ trimStack(fun->stack);
+ break;
+
+ case SLU_EQUALS:
+ fun->reg.compareVariablesInSecond(fun->stack->thisVar);
+ trimStack(fun->stack);
+ break;
+
+ case SLU_NOT_EQ:
+ fun->reg.compareVariablesInSecond(fun->stack->thisVar);
+ trimStack(fun->stack);
+ fun->reg.varData.intValue = !fun->reg.varData.intValue;
+ break;
+
+ default:
+ if (!fun->stack->thisVar.getValueType(firstValue, SVT_INT))
+ return false;
+ if (!fun->reg.getValueType(secondValue, SVT_INT))
+ return false;
+ trimStack(fun->stack);
+
+ switch (com) {
+ case SLU_MULT:
+ fun->reg.setVariable(SVT_INT,
+ firstValue * secondValue);
+ break;
+
+ case SLU_MINUS:
+ fun->reg.setVariable(SVT_INT,
+ firstValue - secondValue);
+ break;
+
+ case SLU_MODULUS:
+ fun->reg.setVariable(SVT_INT,
+ firstValue % secondValue);
+ break;
+
+ case SLU_DIVIDE:
+ fun->reg.setVariable(SVT_INT,
+ firstValue / secondValue);
+ break;
+
+ case SLU_LESSTHAN:
+ fun->reg.setVariable(SVT_INT,
+ firstValue < secondValue);
+ break;
+
+ case SLU_MORETHAN:
+ fun->reg.setVariable(SVT_INT,
+ firstValue > secondValue);
+ break;
+
+ case SLU_LESS_EQUAL:
+ fun->reg.setVariable(SVT_INT,
+ firstValue <= secondValue);
+ break;
+
+ case SLU_MORE_EQUAL:
+ fun->reg.setVariable(SVT_INT,
+ firstValue >= secondValue);
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else {
+ return fatal(ERROR_NOSTACK);
+ }
+ break;
+
+ default:
+ return fatal(ERROR_UNKNOWN_CODE);
+ }
+
+ if (advanceNow)
+ fun->runThisLine++;
+
+ }
+ return true;
+}
+
+void killAllFunctions() {
+ while (allRunningFunctions)
+ finishFunction(allRunningFunctions);
+}
+
+bool loadFunctionCode(LoadedFunction *newFunc) {
+ uint numLines, numLinesRead;
+
+ if (!g_sludge->_resMan->openSubSlice(newFunc->originalNumber))
+ return false;
+
+ debugC(3, kSludgeDebugDataLoad, "Load function code");
+
+ Common::SeekableReadStream *readStream = g_sludge->_resMan->getData();
+ newFunc->unfreezable = readStream->readByte();
+ numLines = readStream->readUint16BE();
+ debugC(3, kSludgeDebugDataLoad, "numLines: %i", numLines);
+ newFunc->numArgs = readStream->readUint16BE();
+ debugC(3, kSludgeDebugDataLoad, "numArgs: %i", newFunc->numArgs);
+ newFunc->numLocals = readStream->readUint16BE();
+ debugC(3, kSludgeDebugDataLoad, "numLocals: %i", newFunc->numLocals);
+ newFunc->compiledLines = new LineOfCode[numLines];
+ if (!checkNew(newFunc->compiledLines))
+ return false;
+
+ for (numLinesRead = 0; numLinesRead < numLines; numLinesRead++) {
+ newFunc->compiledLines[numLinesRead].theCommand = (SludgeCommand)readStream->readByte();
+ newFunc->compiledLines[numLinesRead].param = readStream->readUint16BE();
+ debugC(3, kSludgeDebugDataLoad, "command line %i: %i", numLinesRead,
+ newFunc->compiledLines[numLinesRead].theCommand);
+ }
+ g_sludge->_resMan->finishAccess();
+
+ // Now we need to reserve memory for the local variables
+ newFunc->localVars = new Variable[newFunc->numLocals];
+ if (!checkNew(newFunc->localVars))
+ return false;
+
+ return true;
+}
+
+int startNewFunctionNum(uint funcNum, uint numParamsExpected,
+ LoadedFunction *calledBy, VariableStack *&vStack, bool returnSommet) {
+ LoadedFunction *newFunc = new LoadedFunction;
+ checkNew(newFunc);
+ newFunc->originalNumber = funcNum;
+
+ loadFunctionCode(newFunc);
+
+ if (newFunc->numArgs != (int) numParamsExpected)
+ return fatal("Wrong number of parameters!");
+ if (newFunc->numArgs > newFunc->numLocals)
+ return fatal("More arguments than local Variable space!");
+
+ // Now, lets copy the parameters from the calling function's stack...
+
+ while (numParamsExpected) {
+ numParamsExpected--;
+ if (vStack == NULL)
+ return fatal(
+ "Corrupted file!The stack's empty and there were still parameters expected");
+ newFunc->localVars[numParamsExpected].copyFrom(vStack->thisVar);
+ trimStack(vStack);
+ }
+
+ newFunc->cancelMe = false;
+ newFunc->timeLeft = 0;
+ newFunc->returnSomething = returnSommet;
+ newFunc->calledBy = calledBy;
+ newFunc->stack = NULL;
+ newFunc->freezerLevel = 0;
+ newFunc->runThisLine = 0;
+ newFunc->isSpeech = 0;
+
+ restartFunction(newFunc);
+ return 1;
+}
+
+bool runAllFunctions() {
+
+ LoadedFunction *thisFunction = allRunningFunctions;
+ LoadedFunction *nextFunction;
+
+ while (thisFunction) {
+ nextFunction = thisFunction->next;
+
+ if (!thisFunction->freezerLevel) {
+ if (thisFunction->timeLeft) {
+ if (thisFunction->timeLeft < 0) {
+ if (!g_sludge->_soundMan->stillPlayingSound(
+ g_sludge->_speechMan->getLastSpeechSound())) {
+ thisFunction->timeLeft = 0;
+ }
+ } else if (!--(thisFunction->timeLeft)) {
+ }
+ } else {
+ if (thisFunction->isSpeech) {
+ thisFunction->isSpeech = false;
+ g_sludge->_speechMan->kill();
+ }
+ if (!continueFunction(thisFunction))
+ return false;
+ }
+ }
+
+ thisFunction = nextFunction;
+ }
+
+ return true;
+}
+
+void saveFunction(LoadedFunction *fun, Common::WriteStream *stream) {
+ int a;
+ stream->writeUint16BE(fun->originalNumber);
+ if (fun->calledBy) {
+ stream->writeByte(1);
+ saveFunction(fun->calledBy, stream);
+ } else {
+ stream->writeByte(0);
+ }
+ stream->writeUint32LE(fun->timeLeft);
+ stream->writeUint16BE(fun->runThisLine);
+ stream->writeByte(fun->cancelMe);
+ stream->writeByte(fun->returnSomething);
+ stream->writeByte(fun->isSpeech);
+ fun->reg.save(stream);
+
+ if (fun->freezerLevel) {
+ fatal(ERROR_GAME_SAVE_FROZEN);
+ }
+ saveStack(fun->stack, stream);
+ for (a = 0; a < fun->numLocals; a++) {
+ fun->localVars[a].save(stream);
+ }
+}
+
+LoadedFunction *loadFunction(Common::SeekableReadStream *stream) {
+ int a;
+
+ // Reserve memory...
+
+ LoadedFunction *buildFunc = new LoadedFunction;
+ if (!checkNew(buildFunc))
+ return NULL;
+
+ // See what it was called by and load if we need to...
+
+ buildFunc->originalNumber = stream->readUint16BE();
+ buildFunc->calledBy = NULL;
+ if (stream->readByte()) {
+ buildFunc->calledBy = loadFunction(stream);
+ if (!buildFunc->calledBy)
+ return NULL;
+ }
+
+ buildFunc->timeLeft = stream->readUint32LE();
+ buildFunc->runThisLine = stream->readUint16BE();
+ buildFunc->freezerLevel = 0;
+ buildFunc->cancelMe = stream->readByte();
+ buildFunc->returnSomething = stream->readByte();
+ buildFunc->isSpeech = stream->readByte();
+ buildFunc->reg.load(stream);
+ loadFunctionCode(buildFunc);
+
+ buildFunc->stack = loadStack(stream, NULL);
+
+ for (a = 0; a < buildFunc->numLocals; a++) {
+ buildFunc->localVars[a].load(stream);
+ }
+
+ return buildFunc;
+}
+
+} // End of namespace Sludge
diff --git a/engines/sludge/function.h b/engines/sludge/function.h
new file mode 100644
index 0000000000..005760a960
--- /dev/null
+++ b/engines/sludge/function.h
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef SLUDGE_FUNCTION_H
+#define SLUDGE_FUNCTION_H
+
+#include "sludge/allfiles.h"
+#include "sludge/csludge.h"
+#include "sludge/variable.h"
+
+namespace Sludge {
+
+struct Variable;
+struct VariableStack;
+
+struct LineOfCode {
+ SludgeCommand theCommand;
+ int32 param;
+};
+
+struct LoadedFunction {
+ int originalNumber;
+ LineOfCode *compiledLines;
+ int numLocals, timeLeft, numArgs;
+ Variable *localVars;
+ VariableStack *stack;
+ Variable reg;
+ uint runThisLine;
+ LoadedFunction *calledBy;
+ LoadedFunction *next;
+ bool returnSomething, isSpeech, unfreezable, cancelMe;
+ byte freezerLevel;
+};
+
+bool runAllFunctions();
+int startNewFunctionNum(uint, uint, LoadedFunction *, VariableStack*&, bool = true);
+void restartFunction(LoadedFunction *fun);
+bool loadFunctionCode(LoadedFunction *newFunc);
+void killAllFunctions();
+
+void finishFunction(LoadedFunction *fun);
+void abortFunction(LoadedFunction *fun);
+
+void freezeSubs();
+void unfreezeSubs();
+void completeTimers();
+void killSpeechTimers();
+int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself);
+
+LoadedFunction *loadFunction(Common::SeekableReadStream *stream);
+void saveFunction(LoadedFunction *fun, Common::WriteStream *stream);
+
+} // End of namespace Sludge
+
+#endif
diff --git a/engines/sludge/functionlist.h b/engines/sludge/functionlist.h
index 025f80a844..c7858a2d03 100644
--- a/engines/sludge/functionlist.h
+++ b/engines/sludge/functionlist.h
@@ -29,178 +29,178 @@
namespace Sludge {
-#define FUNC(special,name) {builtIn_ ## name},
+#define FUNC(special,name,paramNum) {builtIn_ ## name, paramNum},
static builtInFunctionData builtInFunctionArray[] = {
- FUNC(true, say)
- FUNC(true, skipSpeech)
- FUNC(true, statusText)
- FUNC(true, pause)
- FUNC(true, onLeftMouse)
- FUNC(true, onRightMouse)
- FUNC(true, setCursor)
- FUNC(true, addOverlay)
- FUNC(true, addCharacter)
- FUNC(true, playSound)
- FUNC(true, getMouseX)
- FUNC(true, getMouseY)
- FUNC(true, addScreenRegion)
- FUNC(true, onMoveMouse)
- FUNC(true, onFocusChange)
- FUNC(true, getOverObject)
- FUNC(true, blankScreen)
- FUNC(true, moveCharacter)
- FUNC(true, onKeyboard)
- FUNC(true, getObjectX)
- FUNC(true, getObjectY)
- FUNC(true, random)
- FUNC(true, spawnSub)
- FUNC(true, blankArea)
- FUNC(true, hideCharacter)
- FUNC(true, showCharacter)
- FUNC(true, callEvent)
- FUNC(true, removeScreenRegion)
- FUNC(true, animate)
- FUNC(true, turnCharacter)
- FUNC(true, removeAllCharacters)
- FUNC(true, removeAllScreenRegions)
- FUNC(true, setScale)
- FUNC(true, newStack)
- FUNC(true, pushToStack)
- FUNC(true, popFromStack)
- FUNC(true, clearStatus)
- FUNC(true, addStatus)
- FUNC(true, removeLastStatus)
- FUNC(true, lightStatus)
- FUNC(true, getStatusText)
- FUNC(true, setStatusColour)
- FUNC(true, deleteFromStack)
- FUNC(true, freeze)
- FUNC(true, unfreeze)
- FUNC(true, pasteImage)
- FUNC(true, copyStack)
- FUNC(true, completeTimers)
- FUNC(true, setCharacterDrawMode)
- FUNC(true, anim)
- FUNC(true, costume)
- FUNC(true, pickOne)
- FUNC(true, setCostume)
- FUNC(true, wait)
- FUNC(true, somethingSpeaking)
- FUNC(true, substring)
- FUNC(true, stringLength)
- FUNC(true, darkBackground)
- FUNC(true, saveGame)
- FUNC(true, loadGame)
- FUNC(true, quitGame)
- FUNC(true, rename)
- FUNC(true, stackSize)
- FUNC(true, pasteString)
- FUNC(true, startMusic)
- FUNC(true, setDefaultMusicVolume)
- FUNC(true, setMusicVolume)
- FUNC(true, stopMusic)
- FUNC(true, stopSound)
- FUNC(true, setFont)
- FUNC(true, alignStatus)
- FUNC(true, showFloor)
- FUNC(true, showBoxes)
- FUNC(true, positionStatus)
- FUNC(true, setFloor)
- FUNC(true, forceCharacter)
- FUNC(true, jumpCharacter)
- FUNC(true, peekStart)
- FUNC(true, peekEnd)
- FUNC(true, enqueue)
- FUNC(true, setZBuffer)
- FUNC(true, getMatchingFiles)
- FUNC(true, inFont)
- FUNC(true, onLeftMouseUp)
- FUNC(true, onRightMouseUp)
- FUNC(true, loopSound)
- FUNC(true, removeCharacter)
- FUNC(true, stopCharacter)
- FUNC(true, launch)
- FUNC(true, howFrozen)
- FUNC(true, setPasteColour)
- FUNC(true, setLitStatusColour)
- FUNC(true, fileExists)
- FUNC(true, floatCharacter)
- FUNC(true, cancelSub)
- FUNC(true, setCharacterWalkSpeed)
- FUNC(true, deleteAllFromStack)
- FUNC(true, setCharacterExtra)
- FUNC(true, mixOverlay)
- FUNC(true, pasteCharacter)
- FUNC(true, setSceneDimensions)
- FUNC(true, aimCamera)
- FUNC(true, getMouseScreenX)
- FUNC(true, getMouseScreenY)
- FUNC(true, setDefaultSoundVolume)
- FUNC(true, setSoundVolume)
- FUNC(true, setSoundLoopPoints)
- FUNC(true, setSpeechMode)
- FUNC(true, setLightMap)
- FUNC(true, think)
- FUNC(true, getCharacterDirection)
- FUNC(true, isCharacter)
- FUNC(true, isScreenRegion)
- FUNC(true, isMoving)
- FUNC(true, deleteFile)
- FUNC(true, renameFile)
- FUNC(true, hardScroll)
- FUNC(true, stringWidth)
- FUNC(true, setSpeechSpeed)
- FUNC(true, normalCharacter)
- FUNC(true, fetchEvent)
- FUNC(true, transitionLevel)
- FUNC(true, spinCharacter)
- FUNC(true, setFontSpacing)
- FUNC(true, burnString)
- FUNC(true, captureAllKeys)
- FUNC(true, cacheSound)
- FUNC(true, setCharacterSpinSpeed)
- FUNC(true, transitionMode)
- FUNC(false, _rem_movieStart)
- FUNC(false, _rem_movieAbort)
- FUNC(false, _rem_moviePlaying)
- FUNC(false, _rem_updateDisplay)
- FUNC(true, getSoundCache)
- FUNC(true, saveCustomData)
- FUNC(true, loadCustomData)
- FUNC(true, setCustomEncoding)
- FUNC(true, freeSound)
- FUNC(true, parallaxAdd)
- FUNC(true, parallaxClear)
- FUNC(true, setBlankColour)
- FUNC(true, setBurnColour)
- FUNC(true, getPixelColour)
- FUNC(true, makeFastArray)
- FUNC(true, getCharacterScale)
- FUNC(true, getLanguageID)
- FUNC(false, _rem_launchWith)
- FUNC(true, getFramesPerSecond)
- FUNC(true, showThumbnail)
- FUNC(true, setThumbnailSize)
- FUNC(true, hasFlag)
- FUNC(true, snapshotGrab)
- FUNC(true, snapshotClear)
- FUNC(true, bodgeFilenames)
- FUNC(false, _rem_registryGetString)
- FUNC(true, quitWithFatalError)
- FUNC(true, _rem_setCharacterAA)
- FUNC(true, _rem_setMaximumAA)
- FUNC(true, setBackgroundEffect)
- FUNC(true, doBackgroundEffect)
- FUNC(true, setCharacterAngleOffset)
- FUNC(true, setCharacterTransparency)
- FUNC(true, setCharacterColourise)
- FUNC(true, zoomCamera)
- FUNC(true, playMovie)
- FUNC(true, stopMovie)
- FUNC(true, pauseMovie)
+ FUNC(true, say, -1)
+ FUNC(true, skipSpeech, 0)
+ FUNC(true, statusText, 1)
+ FUNC(true, pause, 1)
+ FUNC(true, onLeftMouse, -1)
+ FUNC(true, onRightMouse, -1)
+ FUNC(true, setCursor, 1)
+ FUNC(true, addOverlay, 3)
+ FUNC(true, addCharacter, 4)
+ FUNC(true, playSound, 1)
+ FUNC(true, getMouseX, 0)
+ FUNC(true, getMouseY, 0)
+ FUNC(true, addScreenRegion, 8)
+ FUNC(true, onMoveMouse, -1)
+ FUNC(true, onFocusChange, -1)
+ FUNC(true, getOverObject, 0)
+ FUNC(true, blankScreen, 0)
+ FUNC(true, moveCharacter, -1)
+ FUNC(true, onKeyboard, -1)
+ FUNC(true, getObjectX, 1)
+ FUNC(true, getObjectY, 1)
+ FUNC(true, random, 1)
+ FUNC(true, spawnSub, 1)
+ FUNC(true, blankArea, 4)
+ FUNC(true, hideCharacter, 1)
+ FUNC(true, showCharacter, 1)
+ FUNC(true, callEvent, 2)
+ FUNC(true, removeScreenRegion, 1)
+ FUNC(true, animate, 2)
+ FUNC(true, turnCharacter, 2)
+ FUNC(true, removeAllCharacters, 0)
+ FUNC(true, removeAllScreenRegions, 0)
+ FUNC(true, setScale, 2)
+ FUNC(true, newStack, -1)
+ FUNC(true, pushToStack, 2)
+ FUNC(true, popFromStack, 1)
+ FUNC(true, clearStatus, 0)
+ FUNC(true, addStatus, 0)
+ FUNC(true, removeLastStatus, 0)
+ FUNC(true, lightStatus, 1)
+ FUNC(true, getStatusText, 0)
+ FUNC(true, setStatusColour, 3)
+ FUNC(true, deleteFromStack, 2)
+ FUNC(true, freeze, 0)
+ FUNC(true, unfreeze, 0)
+ FUNC(true, pasteImage, 3)
+ FUNC(true, copyStack, 1)
+ FUNC(true, completeTimers, 0)
+ FUNC(true, setCharacterDrawMode, 2)
+ FUNC(true, anim, -1)
+ FUNC(true, costume, -1)
+ FUNC(true, pickOne, -1)
+ FUNC(true, setCostume, 2)
+ FUNC(true, wait, 2)
+ FUNC(true, somethingSpeaking, 0)
+ FUNC(true, substring, 3)
+ FUNC(true, stringLength, 1)
+ FUNC(true, darkBackground, 0)
+ FUNC(true, saveGame, 1)
+ FUNC(true, loadGame, 1)
+ FUNC(true, quitGame, 0)
+ FUNC(true, rename, 2)
+ FUNC(true, stackSize, 1)
+ FUNC(true, pasteString, 3)
+ FUNC(true, startMusic, 3)
+ FUNC(true, setDefaultMusicVolume, 1)
+ FUNC(true, setMusicVolume, 2)
+ FUNC(true, stopMusic, 1)
+ FUNC(true, stopSound, 1)
+ FUNC(true, setFont, 3)
+ FUNC(true, alignStatus, 1)
+ FUNC(true, showFloor, 0)
+ FUNC(true, showBoxes, 0)
+ FUNC(true, positionStatus, 2)
+ FUNC(true, setFloor, 1)
+ FUNC(true, forceCharacter, -1)
+ FUNC(true, jumpCharacter, -1)
+ FUNC(true, peekStart, 1)
+ FUNC(true, peekEnd, 1)
+ FUNC(true, enqueue, 2)
+ FUNC(true, setZBuffer, 1)
+ FUNC(true, getMatchingFiles, 1)
+ FUNC(true, inFont, 1)
+ FUNC(true, onLeftMouseUp, -1)
+ FUNC(true, onRightMouseUp, -1)
+ FUNC(true, loopSound, -1)
+ FUNC(true, removeCharacter, 1)
+ FUNC(true, stopCharacter, 1)
+ FUNC(true, launch, 1)
+ FUNC(true, howFrozen, 0)
+ FUNC(true, setPasteColour, 3)
+ FUNC(true, setLitStatusColour, 3)
+ FUNC(true, fileExists, 1)
+ FUNC(true, floatCharacter, 2)
+ FUNC(true, cancelSub, 1)
+ FUNC(true, setCharacterWalkSpeed, 2)
+ FUNC(true, deleteAllFromStack, 2)
+ FUNC(true, setCharacterExtra, 2)
+ FUNC(true, mixOverlay, 3)
+ FUNC(true, pasteCharacter, 1)
+ FUNC(true, setSceneDimensions, 2)
+ FUNC(true, aimCamera, 2)
+ FUNC(true, getMouseScreenX, 0)
+ FUNC(true, getMouseScreenY, 0)
+ FUNC(true, setDefaultSoundVolume, 1)
+ FUNC(true, setSoundVolume, 2)
+ FUNC(true, setSoundLoopPoints, 3)
+ FUNC(true, setSpeechMode, 1)
+ FUNC(true, setLightMap, -1)
+ FUNC(true, think, -1)
+ FUNC(true, getCharacterDirection, 1)
+ FUNC(true, isCharacter, 1)
+ FUNC(true, isScreenRegion, 1)
+ FUNC(true, isMoving, 1)
+ FUNC(true, deleteFile, 1)
+ FUNC(true, renameFile, 2)
+ FUNC(true, hardScroll, 1)
+ FUNC(true, stringWidth, 1)
+ FUNC(true, setSpeechSpeed, 1)
+ FUNC(true, normalCharacter, 1)
+ FUNC(true, fetchEvent, 2)
+ FUNC(true, transitionLevel, 1)
+ FUNC(true, spinCharacter, 2)
+ FUNC(true, setFontSpacing, 1)
+ FUNC(true, burnString, 3)
+ FUNC(true, captureAllKeys, 1)
+ FUNC(true, cacheSound, 1)
+ FUNC(true, setCharacterSpinSpeed, 2)
+ FUNC(true, transitionMode, 1)
+ FUNC(false, _rem_movieStart, 1)
+ FUNC(false, _rem_movieAbort, 0)
+ FUNC(false, _rem_moviePlaying, 0)
+ FUNC(false, _rem_updateDisplay, 1)
+ FUNC(true, getSoundCache, 0)
+ FUNC(true, saveCustomData, 2)
+ FUNC(true, loadCustomData, 1)
+ FUNC(true, setCustomEncoding, 1)
+ FUNC(true, freeSound, 1)
+ FUNC(true, parallaxAdd, 3)
+ FUNC(true, parallaxClear, 0)
+ FUNC(true, setBlankColour, 3)
+ FUNC(true, setBurnColour, 3)
+ FUNC(true, getPixelColour, 2)
+ FUNC(true, makeFastArray, 1)
+ FUNC(true, getCharacterScale, 1)
+ FUNC(true, getLanguageID, 0)
+ FUNC(false, _rem_launchWith, 2)
+ FUNC(true, getFramesPerSecond, 0)
+ FUNC(true, showThumbnail, 3)
+ FUNC(true, setThumbnailSize, 2)
+ FUNC(true, hasFlag, 2)
+ FUNC(true, snapshotGrab, 0)
+ FUNC(true, snapshotClear, 0)
+ FUNC(true, bodgeFilenames, 1)
+ FUNC(false, _rem_registryGetString, 2)
+ FUNC(true, quitWithFatalError, 1)
+ FUNC(true, _rem_setCharacterAA, 4)
+ FUNC(true, _rem_setMaximumAA, 3)
+ FUNC(true, setBackgroundEffect, -1)
+ FUNC(true, doBackgroundEffect, 0)
+ FUNC(true, setCharacterAngleOffset, 2)
+ FUNC(true, setCharacterTransparency, 2)
+ FUNC(true, setCharacterColourise, 5)
+ FUNC(true, zoomCamera, 1)
+ FUNC(true, playMovie, 1)
+ FUNC(true, stopMovie, 0)
+ FUNC(true, pauseMovie, 0)
};
#undef FUNC
-int NUM_FUNCS = (sizeof (builtInFunctionArray) / sizeof (builtInFunctionArray[0]));
+const static int NUM_FUNCS = (sizeof (builtInFunctionArray) / sizeof (builtInFunctionArray[0]));
} // End of namespace Sludge
diff --git a/engines/sludge/graphics.cpp b/engines/sludge/graphics.cpp
index 578e6f65fe..72301b3475 100644
--- a/engines/sludge/graphics.cpp
+++ b/engines/sludge/graphics.cpp
@@ -83,6 +83,15 @@ void GraphicsManager::init() {
_currentBurnR = 0;
_currentBurnG = 0;
_currentBurnB = 0;
+
+ // Thumbnail
+ _thumbWidth = 0;
+ _thumbHeight = 0;
+
+ // Transition
+ resetRandW();
+ _brightnessLevel = 255;
+ _fadeMode = 2;
}
void GraphicsManager::kill() {
@@ -157,6 +166,8 @@ bool GraphicsManager::initGfx() {
void GraphicsManager::display() {
g_system->copyRectToScreen((byte *)_renderSurface.getPixels(), _renderSurface.pitch, 0, 0, _renderSurface.w, _renderSurface.h);
g_system->updateScreen();
+ if (_brightnessLevel < 255)
+ fixBrightness();
}
void GraphicsManager::clear() {
diff --git a/engines/sludge/graphics.h b/engines/sludge/graphics.h
index 16973a1658..8bc47cdab4 100644
--- a/engines/sludge/graphics.h
+++ b/engines/sludge/graphics.h
@@ -91,6 +91,8 @@ public:
void drawVerticalLine(uint, uint, uint);
void hardScroll(int distance);
bool getRGBIntoStack(uint x, uint y, StackHandler *sH);
+ void saveBackdrop(Common::WriteStream *stream); // To game save
+ void loadBackdrop(int ssgVersion, Common::SeekableReadStream *streamn); // From game save
// Lightmap
int _lightMapMode;
@@ -109,11 +111,6 @@ public:
int getCamX() { return _cameraX; }
int getCamY() { return _cameraY; }
float getCamZoom() { return _cameraZoom; }
- void setCamera(int camerX, int camerY, float camerZ) {
- _cameraX = camerX;
- _cameraY = camerY;
- _cameraZoom = camerZ;
- }
void aimCamera(int cameraX, int cameraY);
void zoomCamera(int z);
@@ -167,11 +164,18 @@ public:
void saveColors(Common::WriteStream *stream);
void loadColors(Common::SeekableReadStream *stream);
- // Thumb nail
+ // Thumbnail
+ bool setThumbnailSize(int thumbWidth, int thumbHeight);
bool saveThumbnail(Common::WriteStream *stream);
bool skipThumbnail(Common::SeekableReadStream *stream);
void showThumbnail(const Common::String &filename, int x, int y);
+ // Transition
+ void setBrightnessLevel(int brightnessLevel);
+ void setFadeMode(int fadeMode) { _fadeMode = fadeMode; };
+ void fixBrightness();
+ void resetRandW();
+
private:
SludgeEngine *_vm;
@@ -222,6 +226,14 @@ private:
// Colors
uint _currentBlankColour;
byte _currentBurnR, _currentBurnG, _currentBurnB;
+
+ // Thumbnail
+ int _thumbWidth;
+ int _thumbHeight;
+
+ // Transition
+ byte _brightnessLevel;
+ byte _fadeMode;
};
} // End of namespace Sludge
diff --git a/engines/sludge/loadsave.cpp b/engines/sludge/loadsave.cpp
index 4cabbc79da..453e78f3e5 100644
--- a/engines/sludge/loadsave.cpp
+++ b/engines/sludge/loadsave.cpp
@@ -29,6 +29,7 @@
#include "sludge/event.h"
#include "sludge/floor.h"
#include "sludge/fonttext.h"
+#include "sludge/function.h"
#include "sludge/graphics.h"
#include "sludge/language.h"
#include "sludge/loadsave.h"
@@ -37,6 +38,7 @@
#include "sludge/objtypes.h"
#include "sludge/people.h"
#include "sludge/region.h"
+#include "sludge/savedata.h"
#include "sludge/sludge.h"
#include "sludge/sludger.h"
#include "sludge/sound.h"
@@ -54,291 +56,31 @@ namespace Sludge {
// From elsewhere
//----------------------------------------------------------------------
+extern LoadedFunction *saverFunc; // In function.cpp
extern LoadedFunction *allRunningFunctions; // In sludger.cpp
-extern const char *typeName[]; // In variable.cpp
extern int numGlobals; // In sludger.cpp
extern Variable *globalVars; // In sludger.cpp
-extern Floor *currentFloor; // In floor.cpp
extern FILETIME fileTime; // In sludger.cpp
-extern byte brightnessLevel; // " " "
-extern byte fadeMode; // In transition.cpp
-extern bool captureAllKeys;
extern bool allowAnyFilename;
-extern uint16 saveEncoding; // in savedata.cpp
//----------------------------------------------------------------------
-// Globals (so we know what's saved already and what's a reference
-//----------------------------------------------------------------------
-
-struct stackLibrary {
- StackHandler *stack;
- stackLibrary *next;
-};
-
-int stackLibTotal = 0;
-stackLibrary *stackLib = NULL;
-
-//----------------------------------------------------------------------
-// For saving and loading stacks...
-//----------------------------------------------------------------------
-void saveStack(VariableStack *vs, Common::WriteStream *stream) {
- int elements = 0;
- int a;
-
- VariableStack *search = vs;
- while (search) {
- elements++;
- search = search->next;
- }
-
- stream->writeUint16BE(elements);
- search = vs;
- for (a = 0; a < elements; a++) {
- saveVariable(&search->thisVar, stream);
- search = search->next;
- }
-}
-
-VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last) {
- int elements = stream->readUint16BE();
- int a;
- VariableStack *first = NULL;
- VariableStack **changeMe = &first;
-
- for (a = 0; a < elements; a++) {
- VariableStack *nS = new VariableStack;
- if (!checkNew(nS))
- return NULL;
- loadVariable(&(nS->thisVar), stream);
- if (last && a == elements - 1) {
- *last = nS;
- }
- nS->next = NULL;
- (*changeMe) = nS;
- changeMe = &(nS->next);
- }
-
- return first;
-}
-
-bool saveStackRef(StackHandler *vs, Common::WriteStream *stream) {
- stackLibrary *s = stackLib;
- int a = 0;
- while (s) {
- if (s->stack == vs) {
- stream->writeByte(1);
- stream->writeUint16BE(stackLibTotal - a);
- return true;
- }
- s = s->next;
- a++;
- }
- stream->writeByte(0);
- saveStack(vs->first, stream);
- s = new stackLibrary;
- stackLibTotal++;
- if (!checkNew(s))
- return false;
- s->next = stackLib;
- s->stack = vs;
- stackLib = s;
- return true;
-}
-
-void clearStackLib() {
- stackLibrary *k;
- while (stackLib) {
- k = stackLib;
- stackLib = stackLib->next;
- delete k;
- }
- stackLibTotal = 0;
-}
-
-StackHandler *getStackFromLibrary(int n) {
- n = stackLibTotal - n;
- while (n) {
- stackLib = stackLib->next;
- n--;
- }
- return stackLib->stack;
-}
-
-StackHandler *loadStackRef(Common::SeekableReadStream *stream) {
- StackHandler *nsh;
-
- if (stream->readByte()) { // It's one we've loaded already...
- nsh = getStackFromLibrary(stream->readUint16BE());
- nsh->timesUsed++;
- } else {
- // Load the new stack
-
- nsh = new StackHandler;
- if (!checkNew(nsh))
- return NULL;
- nsh->last = NULL;
- nsh->first = loadStack(stream, &nsh->last);
- nsh->timesUsed = 1;
-
- // Add it to the library of loaded stacks
-
- stackLibrary *s = new stackLibrary;
- if (!checkNew(s))
- return NULL;
- s->stack = nsh;
- s->next = stackLib;
- stackLib = s;
- stackLibTotal++;
- }
- return nsh;
-}
-
-//----------------------------------------------------------------------
-// For saving and loading variables...
+// Save everything
//----------------------------------------------------------------------
-bool saveVariable(Variable *from, Common::WriteStream *stream) {
- stream->writeByte(from->varType);
- switch (from->varType) {
- case SVT_INT:
- case SVT_FUNC:
- case SVT_BUILT:
- case SVT_FILE:
- case SVT_OBJTYPE:
- stream->writeUint32LE(from->varData.intValue);
- return true;
-
- case SVT_STRING:
- writeString(from->varData.theString, stream);
- return true;
-
- case SVT_STACK:
- return saveStackRef(from->varData.theStack, stream);
-
- case SVT_COSTUME:
- saveCostume(from->varData.costumeHandler, stream);
- return false;
-
- case SVT_ANIM:
- saveAnim(from->varData.animHandler, stream);
- return false;
-
- case SVT_NULL:
- return false;
-
- default:
- fatal("Can't save variables of this type:", (from->varType < SVT_NUM_TYPES) ? typeName[from->varType] : "bad ID");
- }
- return true;
-}
-bool loadVariable(Variable *to, Common::SeekableReadStream *stream) {
- to->varType = (VariableType)stream->readByte();
- switch (to->varType) {
- case SVT_INT:
- case SVT_FUNC:
- case SVT_BUILT:
- case SVT_FILE:
- case SVT_OBJTYPE:
- to->varData.intValue = stream->readUint32LE();
- return true;
-
- case SVT_STRING:
- to->varData.theString = createCString(readString(stream));
- return true;
-
- case SVT_STACK:
- to->varData.theStack = loadStackRef(stream);
- return true;
-
- case SVT_COSTUME:
- to->varData.costumeHandler = new Persona;
- if (!checkNew(to->varData.costumeHandler))
+bool handleSaveLoad() {
+ if (!g_sludge->loadNow.empty()) {
+ if (g_sludge->loadNow[0] == ':') {
+ saveGame(g_sludge->loadNow.c_str() + 1);
+ saverFunc->reg.setVariable(SVT_INT, 1);
+ } else {
+ if (!loadGame(g_sludge->loadNow))
return false;
- loadCostume(to->varData.costumeHandler, stream);
- return true;
-
- case SVT_ANIM:
- to->varData.animHandler = new PersonaAnimation ;
- if (!checkNew(to->varData.animHandler))
- return false;
- loadAnim(to->varData.animHandler, stream);
- return true;
-
- default:
- break;
+ }
+ g_sludge->loadNow.clear();
}
return true;
}
-//----------------------------------------------------------------------
-// For saving and loading functions
-//----------------------------------------------------------------------
-void saveFunction(LoadedFunction *fun, Common::WriteStream *stream) {
- int a;
- stream->writeUint16BE(fun->originalNumber);
- if (fun->calledBy) {
- stream->writeByte(1);
- saveFunction(fun->calledBy, stream);
- } else {
- stream->writeByte(0);
- }
- stream->writeUint32LE(fun->timeLeft);
- stream->writeUint16BE(fun->runThisLine);
- stream->writeByte(fun->cancelMe);
- stream->writeByte(fun->returnSomething);
- stream->writeByte(fun->isSpeech);
- saveVariable(&(fun->reg), stream);
-
- if (fun->freezerLevel) {
- fatal(ERROR_GAME_SAVE_FROZEN);
- }
- saveStack(fun->stack, stream);
- for (a = 0; a < fun->numLocals; a++) {
- saveVariable(&(fun->localVars[a]), stream);
- }
-}
-
-LoadedFunction *loadFunction(Common::SeekableReadStream *stream) {
- int a;
-
- // Reserve memory...
-
- LoadedFunction *buildFunc = new LoadedFunction;
- if (!checkNew(buildFunc))
- return NULL;
-
- // See what it was called by and load if we need to...
-
- buildFunc->originalNumber = stream->readUint16BE();
- buildFunc->calledBy = NULL;
- if (stream->readByte()) {
- buildFunc->calledBy = loadFunction(stream);
- if (!buildFunc->calledBy)
- return NULL;
- }
-
- buildFunc->timeLeft = stream->readUint32LE();
- buildFunc->runThisLine = stream->readUint16BE();
- buildFunc->freezerLevel = 0;
- buildFunc->cancelMe = stream->readByte();
- buildFunc->returnSomething = stream->readByte();
- buildFunc->isSpeech = stream->readByte();
- loadVariable(&(buildFunc->reg), stream);
- loadFunctionCode(buildFunc);
-
- buildFunc->stack = loadStack(stream, NULL);
-
- for (a = 0; a < buildFunc->numLocals; a++) {
- loadVariable(&(buildFunc->localVars[a]), stream);
- }
-
- return buildFunc;
-}
-
-//----------------------------------------------------------------------
-// Save everything
-//----------------------------------------------------------------------
-
bool saveGame(const Common::String &fname) {
Common::OutSaveFile *fp = g_system->getSavefileManager()->openForSaving(fname);
@@ -359,23 +101,18 @@ bool saveGame(const Common::String &fname) {
// DON'T ADD ANYTHING NEW BEFORE THIS POINT!
fp->writeByte(allowAnyFilename);
- fp->writeByte(captureAllKeys);
+ fp->writeByte(false); // deprecated captureAllKeys
fp->writeByte(true);
g_sludge->_txtMan->saveFont(fp);
// Save backdrop
- fp->writeUint16BE(g_sludge->_gfxMan->getCamX());
- fp->writeUint16BE(g_sludge->_gfxMan->getCamY());
- fp->writeFloatLE(g_sludge->_gfxMan->getCamZoom());
-
- fp->writeByte(brightnessLevel);
- g_sludge->_gfxMan->saveHSI(fp);
+ g_sludge->_gfxMan->saveBackdrop(fp);
// Save event handlers
g_sludge->_evtMan->saveHandlers(fp);
// Save regions
- saveRegions(fp);
+ g_sludge->_regionMan->saveRegions(fp);
g_sludge->_cursorMan->saveCursor(fp);
@@ -395,28 +132,21 @@ bool saveGame(const Common::String &fname) {
}
for (int a = 0; a < numGlobals; a++) {
- saveVariable(&globalVars[a], fp);
+ globalVars[a].save(fp);
}
- savePeople(fp);
+ g_sludge->_peopleMan->savePeople(fp);
- if (currentFloor->numPolygons) {
- fp->writeByte(1);
- fp->writeUint16BE(currentFloor->originalNum);
- } else {
- fp->writeByte(0);
- }
+ g_sludge->_floorMan->save(fp);
g_sludge->_gfxMan->saveZBuffer(fp);
g_sludge->_gfxMan->saveLightMap(fp);
- fp->writeByte(fadeMode);
-
g_sludge->_speechMan->save(fp);
saveStatusBars(fp);
g_sludge->_soundMan->saveSounds(fp);
- fp->writeUint16BE(saveEncoding);
+ fp->writeUint16BE(CustomSaveHelper::_saveEncoding);
blur_saveSettings(fp);
@@ -498,28 +228,18 @@ bool loadGame(const Common::String &fname) {
if (ssgVersion >= VERSION(1, 4)) {
allowAnyFilename = fp->readByte();
}
- captureAllKeys = fp->readByte();
- fp->readByte(); // updateDisplay (part of movie playing)
+ fp->readByte(); // deprecated captureAllKeys
+ fp->readByte(); // updateDisplay (part of movie playing)
g_sludge->_txtMan->loadFont(ssgVersion, fp);
- killAllPeople();
- killAllRegions();
-
- int camerX = fp->readUint16BE();
- int camerY = fp->readUint16BE();
- float camerZ;
- if (ssgVersion >= VERSION(2, 0)) {
- camerZ = fp->readFloatLE();
- } else {
- camerZ = 1.0;
- }
+ g_sludge->_regionMan->kill();
- brightnessLevel = fp->readByte();
+ g_sludge->_gfxMan->loadBackdrop(ssgVersion, fp);
- g_sludge->_gfxMan->loadHSI(fp, 0, 0, true);
g_sludge->_evtMan->loadHandlers(fp);
- loadRegions(fp);
+
+ g_sludge->_regionMan->loadRegions(fp);
if (!g_sludge->_cursorMan->loadCursor(fp)) {
return false;
@@ -537,17 +257,15 @@ bool loadGame(const Common::String &fname) {
}
for (int a = 0; a < numGlobals; a++) {
- unlinkVar(globalVars[a]);
- loadVariable(&globalVars[a], fp);
+ globalVars[a].unlinkVar();
+ globalVars[a].load(fp);
}
- loadPeople(fp);
+ g_sludge->_peopleMan->loadPeople(fp);
- if (fp->readByte()) {
- if (!setFloor(fp->readUint16BE()))
- return false;
- } else
- setFloorNull();
+ if (!g_sludge->_floorMan->load(fp)) {
+ return false;
+ }
if (!g_sludge->_gfxMan->loadZBuffer(fp))
return false;
@@ -556,12 +274,11 @@ bool loadGame(const Common::String &fname) {
return false;
}
- fadeMode = fp->readByte();
g_sludge->_speechMan->load(fp);
loadStatusBars(fp);
g_sludge->_soundMan->loadSounds(fp);
- saveEncoding = fp->readUint16BE();
+ CustomSaveHelper::_saveEncoding = fp->readUint16BE();
if (ssgVersion >= VERSION(1, 6)) {
if (ssgVersion < VERSION(2, 0)) {
@@ -600,8 +317,6 @@ bool loadGame(const Common::String &fname) {
delete fp;
- g_sludge->_gfxMan->setCamera(camerX, camerY, camerZ);
-
clearStackLib();
return true;
}
diff --git a/engines/sludge/loadsave.h b/engines/sludge/loadsave.h
index 269fadb507..4077950cfb 100644
--- a/engines/sludge/loadsave.h
+++ b/engines/sludge/loadsave.h
@@ -24,23 +24,10 @@
namespace Sludge {
-struct LoadedFunction;
-struct Variable;
-struct VariableStack;
-
+bool handleSaveLoad();
bool saveGame(const Common::String &fname);
bool loadGame(const Common::String &fname);
-bool saveVariable(Variable *from, Common::WriteStream *stream);
-bool loadVariable(Variable *to, Common::SeekableReadStream *stream);
-
-VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last);
-bool saveStackRef(StackHandler *vs, Common::WriteStream *stream);
-StackHandler *loadStackRef(Common::SeekableReadStream *stream);
-
-LoadedFunction *loadFunction(Common::SeekableReadStream *stream);
-void saveFunction(LoadedFunction *fun, Common::WriteStream *stream);
-
} // End of namespace Sludge
#endif
diff --git a/engines/sludge/main_loop.cpp b/engines/sludge/main_loop.cpp
index 905d91d9c2..8f6e1f9cfb 100644
--- a/engines/sludge/main_loop.cpp
+++ b/engines/sludge/main_loop.cpp
@@ -28,8 +28,10 @@
#include "sludge/backdrop.h"
#include "sludge/event.h"
#include "sludge/floor.h"
+#include "sludge/function.h"
#include "sludge/graphics.h"
#include "sludge/language.h"
+#include "sludge/loadsave.h"
#include "sludge/newfatal.h"
#include "sludge/objtypes.h"
#include "sludge/people.h"
@@ -39,15 +41,12 @@
#include "sludge/sludge.h"
#include "sludge/sludger.h"
#include "sludge/speech.h"
-#include "sludge/transition.h"
#include "sludge/timing.h"
namespace Sludge {
extern VariableStack *noStack;
-int dialogValue = 0;
-
int main_loop(Common::String filename) {
if (!initSludge(filename)) {
@@ -63,9 +62,10 @@ int main_loop(Common::String filename) {
while (!g_sludge->_evtMan->quit()) {
g_sludge->_evtMan->checkInput();
- walkAllPeople();
+ g_sludge->_peopleMan->walkAllPeople();
if (g_sludge->_evtMan->handleInput()) {
- runSludge();
+ runAllFunctions();
+ handleSaveLoad();
}
sludgeDisplay();
g_sludge->_soundMan->handleSoundLists();
diff --git a/engines/sludge/module.mk b/engines/sludge/module.mk
index a083ec4a95..d904e6c4c3 100644
--- a/engines/sludge/module.mk
+++ b/engines/sludge/module.mk
@@ -12,6 +12,7 @@ MODULE_OBJS := \
floor.o \
freeze.o \
fonttext.o \
+ function.o \
graphics.o \
hsi.o \
imgloader.o \
diff --git a/engines/sludge/moreio.cpp b/engines/sludge/moreio.cpp
index 1512574207..ee9ab8e0f0 100644
--- a/engines/sludge/moreio.cpp
+++ b/engines/sludge/moreio.cpp
@@ -167,4 +167,15 @@ Common::String decodeFilename(const Common::String &nameIn) {
return newName;
}
+char *createCString(const Common::String &s) {
+ uint n = s.size() + 1;
+ char *res = new char[n];
+ if (!checkNew(res)) {
+ fatal("createCString : Unable to copy String");
+ return NULL;
+ }
+ memcpy(res, s.c_str(), n);
+ return res;
+}
+
} // End of namespace Sludge
diff --git a/engines/sludge/moreio.h b/engines/sludge/moreio.h
index 09235ae8a6..237a918626 100644
--- a/engines/sludge/moreio.h
+++ b/engines/sludge/moreio.h
@@ -31,6 +31,8 @@ void writeString(Common::String s, Common::WriteStream *stream);
Common::String encodeFilename(const Common::String &nameIn);
Common::String decodeFilename(const Common::String &nameIn);
+char *createCString(const Common::String &s);
+
} // End of namespace Sludge
#endif
diff --git a/engines/sludge/movie.cpp b/engines/sludge/movie.cpp
index 271728da75..2c43c3cceb 100644
--- a/engines/sludge/movie.cpp
+++ b/engines/sludge/movie.cpp
@@ -911,7 +911,8 @@ int playMovie(int fileNumber) {
glBindFramebuffer(GL_FRAMEBUFFER, old_fbo);
movieIsPlaying = nothing;
- for (int i = 0; i < 10; i++) Wait_Frame();
+ for (int i = 0; i < 10; i++)
+ Wait_Frame();
huntKillFreeSound(fileNumber);
if (vpx_codec_destroy(&codec))
diff --git a/engines/sludge/newfatal.cpp b/engines/sludge/newfatal.cpp
index edd4a88073..a5069ae306 100644
--- a/engines/sludge/newfatal.cpp
+++ b/engines/sludge/newfatal.cpp
@@ -24,34 +24,17 @@
#include "sludge/allfiles.h"
#include "sludge/errors.h"
+#include "sludge/fileset.h"
+#include "sludge/newfatal.h"
#include "sludge/sludge.h"
#include "sludge/sound.h"
#include "sludge/version.h"
-namespace Sludge {
-
-const char emergencyMemoryMessage[] = "Out of memory displaying error message!";
-
-extern int numResourceNames /* = 0*/;
-extern Common::String *allResourceNames /*= ""*/;
-
-int resourceForFatal = -1;
-
-const Common::String resourceNameFromNum(int i) {
- if (i == -1)
- return NULL;
- if (numResourceNames == 0)
- return "RESOURCE";
- if (i < numResourceNames)
- return allResourceNames[i];
- return "Unknown resource";
+namespace Common {
+DECLARE_SINGLETON(Sludge::FatalMsgManager);
}
-bool hasFatal() {
- if (!g_sludge->fatalMessage.empty())
- return true;
- return false;
-}
+namespace Sludge {
int inFatal(const Common::String &str) {
g_sludge->_soundMan->killSoundStuff();
@@ -59,35 +42,55 @@ int inFatal(const Common::String &str) {
return true;
}
-int checkNew(const void *mem) {
- if (mem == NULL) {
- inFatal(ERROR_OUT_OF_MEMORY);
- return 0;
- }
- return 1;
+FatalMsgManager::FatalMsgManager() {
+ reset();
}
-void setFatalInfo(const Common::String &userFunc, const Common::String &BIF) {
- g_sludge->fatalInfo = "Currently in this sub: " + userFunc + "\nCalling: " + BIF;
- debugC(0, kSludgeDebugFatal, "%s", g_sludge->fatalInfo.c_str());
+FatalMsgManager::~FatalMsgManager() {
}
-void setResourceForFatal(int n) {
- resourceForFatal = n;
+void FatalMsgManager::reset() {
+ _fatalMessage = "";
+ _fatalInfo = "Initialisation error! Something went wrong before we even got started!";
+ _resourceForFatal = -1;
}
-int fatal(const Common::String &str1) {
- if (numResourceNames && resourceForFatal != -1) {
- Common::String r = resourceNameFromNum(resourceForFatal);
- Common::String newStr = g_sludge->fatalInfo + "\nResource: " + r + "\n\n" + str1;
+bool FatalMsgManager::hasFatal() {
+ if (!_fatalMessage.empty())
+ return true;
+ return false;
+}
+
+void FatalMsgManager::setFatalInfo(const Common::String &userFunc, const Common::String &BIF) {
+ _fatalInfo = "Currently in this sub: " + userFunc + "\nCalling: " + BIF;
+ debugC(0, kSludgeDebugFatal, "%s", _fatalInfo.c_str());
+}
+
+void FatalMsgManager::setResourceForFatal(int n) {
+ _resourceForFatal = n;
+}
+
+int FatalMsgManager::fatal(const Common::String &str1) {
+ ResourceManager *resMan = g_sludge->_resMan;
+ if (resMan->hasResourceNames() && _resourceForFatal != -1) {
+ Common::String r = resMan->resourceNameFromNum(_resourceForFatal);
+ Common::String newStr = _fatalInfo + "\nResource: " + r + "\n\n" + str1;
inFatal(newStr);
} else {
- Common::String newStr = g_sludge->fatalInfo + "\n\n" + str1;
+ Common::String newStr = _fatalInfo + "\n\n" + str1;
inFatal(newStr);
}
return 0;
}
+int checkNew(const void *mem) {
+ if (mem == NULL) {
+ inFatal(ERROR_OUT_OF_MEMORY);
+ return 0;
+ }
+ return 1;
+}
+
int fatal(const Common::String &str1, const Common::String &str2) {
Common::String newStr = str1 + " " + str2;
fatal(newStr);
diff --git a/engines/sludge/newfatal.h b/engines/sludge/newfatal.h
index fc91110758..81ca4b7616 100644
--- a/engines/sludge/newfatal.h
+++ b/engines/sludge/newfatal.h
@@ -23,19 +23,49 @@
#define SLUDGE_NEWFATAL_H
#include "common/str.h"
+#include "common/singleton.h"
#include "sludge/errors.h"
namespace Sludge {
-bool hasFatal();
+class FatalMsgManager : public Common::Singleton<Sludge::FatalMsgManager>{
+public:
+ FatalMsgManager();
+ ~FatalMsgManager();
+
+ void reset();
+
+ bool hasFatal();
+ int fatal(const Common::String &str);
+ void setFatalInfo(const Common::String &userFunc, const Common::String &BIF);
+ void setResourceForFatal(int n);
+
+private:
+ Common::String _fatalMessage;
+ Common::String _fatalInfo;
+
+ int _resourceForFatal;
+};
+
+inline bool hasFatal() {
+ return FatalMsgManager::instance().hasFatal();
+}
+
+inline int fatal(const Common::String &str) {
+ return FatalMsgManager::instance().fatal(str);
+}
+
+inline void setFatalInfo(const Common::String &userFunc, const Common::String &BIF) {
+ FatalMsgManager::instance().setFatalInfo(userFunc, BIF);
+}
+
+inline void setResourceForFatal(int n) {
+ FatalMsgManager::instance().setResourceForFatal(n);
+}
-int fatal(const Common::String &str);
-int fatal(const Common::String &str1, const Common::String &str2);
int checkNew(const void *mem);
-void setFatalInfo(const Common::String &userFunc, const Common::String &BIF);
-void setResourceForFatal(int n);
-const Common::String resourceNameFromNum(int i);
+int fatal(const Common::String &str1, const Common::String &str2);
} // End of namespace Sludge
diff --git a/engines/sludge/people.cpp b/engines/sludge/people.cpp
index 4aec5fa8b7..433ab2d895 100644
--- a/engines/sludge/people.cpp
+++ b/engines/sludge/people.cpp
@@ -22,6 +22,7 @@
#include "sludge/allfiles.h"
#include "sludge/floor.h"
+#include "sludge/function.h"
#include "sludge/graphics.h"
#include "sludge/loadsave.h"
#include "sludge/moreio.h"
@@ -39,7 +40,6 @@
#include "sludge/version.h"
#include "sludge/zbuffer.h"
-#define ANGLEFIX (180.0 / 3.14157)
#define ANI_STAND 0
#define ANI_WALK 1
#define ANI_TALK 2
@@ -47,108 +47,174 @@
namespace Sludge {
extern VariableStack *noStack;
-
extern int ssgVersion;
-ScreenRegion personRegion;
-extern ScreenRegion *lastRegion;
-extern Floor *currentFloor;
-
-OnScreenPerson *allPeople = NULL;
-int16 scaleHorizon = 75;
-int16 scaleDivide = 150;
-extern ScreenRegion *allScreenRegions;
-
-void setFrames(OnScreenPerson &m, int a) {
- m.myAnim = m.myPersona->animation[(a * m.myPersona->numDirections) + m.direction];
+PersonaAnimation::PersonaAnimation() {
+ theSprites = nullptr;
+ numFrames = 0;
+ frames = nullptr;
}
-PersonaAnimation *createPersonaAnim(int num, VariableStack *&stacky) {
- PersonaAnimation *newP = new PersonaAnimation ;
- checkNew(newP);
-
- newP->numFrames = num;
- newP->frames = new AnimFrame [num];
- checkNew(newP->frames);
+PersonaAnimation::~PersonaAnimation() {
+ if (numFrames) {
+ delete[] frames;
+ frames = nullptr;
+ }
+}
+PersonaAnimation::PersonaAnimation(int num, VariableStack *&stacky) {
+ theSprites = nullptr;
+ numFrames = num;
+ frames = new AnimFrame[num];
int a = num, frameNum, howMany;
while (a) {
a--;
- newP->frames[a].noise = 0;
+ frames[a].noise = 0;
if (stacky->thisVar.varType == SVT_FILE) {
- newP->frames[a].noise = stacky->thisVar.varData.intValue;
+ frames[a].noise = stacky->thisVar.varData.intValue;
} else if (stacky->thisVar.varType == SVT_FUNC) {
- newP->frames[a].noise = -stacky->thisVar.varData.intValue;
+ frames[a].noise = -stacky->thisVar.varData.intValue;
} else if (stacky->thisVar.varType == SVT_STACK) {
- getValueType(frameNum, SVT_INT, stacky->thisVar.varData.theStack->first->thisVar);
- getValueType(howMany, SVT_INT, stacky->thisVar.varData.theStack->first->next->thisVar);
+ stacky->thisVar.varData.theStack->first->thisVar.getValueType(frameNum, SVT_INT);
+ stacky->thisVar.varData.theStack->first->next->thisVar.getValueType(howMany, SVT_INT);
} else {
- getValueType(frameNum, SVT_INT, stacky->thisVar);
+ stacky->thisVar.getValueType(frameNum, SVT_INT);
howMany = 1;
}
trimStack(stacky);
- newP->frames[a].frameNum = frameNum;
- newP->frames[a].howMany = howMany;
+ frames[a].frameNum = frameNum;
+ frames[a].howMany = howMany;
}
-
- return newP;
}
-PersonaAnimation *makeNullAnim() {
- PersonaAnimation *newAnim = new PersonaAnimation ;
- if (!checkNew(newAnim))
- return NULL;
-
- newAnim->theSprites = NULL;
- newAnim->numFrames = 0;
- newAnim->frames = NULL;
- return newAnim;
-}
-
-PersonaAnimation *copyAnim(PersonaAnimation *orig) {
+PersonaAnimation::PersonaAnimation(PersonaAnimation *orig) {
int num = orig->numFrames;
- PersonaAnimation *newAnim = new PersonaAnimation ;
- if (!checkNew(newAnim))
- return NULL;
-
// Copy the easy bits...
- newAnim->theSprites = orig->theSprites;
- newAnim->numFrames = num;
+ theSprites = orig->theSprites;
+ numFrames = num;
if (num) {
-
- // Argh!Frames!We need a whole NEW array of AnimFrame structures...
-
- newAnim->frames = new AnimFrame [num];
- if (!checkNew(newAnim->frames))
- return NULL;
+ // Argh! Frames! We need a whole NEW array of AnimFrame structures...
+ frames = new AnimFrame[num];
for (int a = 0; a < num; a++) {
- newAnim->frames[a].frameNum = orig->frames[a].frameNum;
- newAnim->frames[a].howMany = orig->frames[a].howMany;
- newAnim->frames[a].noise = orig->frames[a].noise;
+ frames[a].frameNum = orig->frames[a].frameNum;
+ frames[a].howMany = orig->frames[a].howMany;
+ frames[a].noise = orig->frames[a].noise;
}
} else {
- newAnim->frames = NULL;
+ frames = nullptr;
}
+}
- return newAnim;
+int PersonaAnimation::getTotalTime() {
+ int total = 0;
+ for (int a = 0; a < numFrames; a++) {
+ total += frames[a].howMany;
+ }
+ return total;
}
-void deleteAnim(PersonaAnimation *orig) {
+bool PersonaAnimation::save(Common::WriteStream *stream) {
+ stream->writeUint16BE(numFrames);
+ if (numFrames) {
+ stream->writeUint32LE(theSprites->ID);
- if (orig) {
- if (orig->numFrames) {
- delete[] orig->frames;
+ for (int a = 0; a < numFrames; a++) {
+ stream->writeUint32LE(frames[a].frameNum);
+ stream->writeUint32LE(frames[a].howMany);
+ stream->writeUint32LE(frames[a].noise);
}
- delete orig;
- orig = NULL;
}
+ return true;
+}
+
+bool PersonaAnimation::load(Common::SeekableReadStream *stream) {
+ numFrames = stream->readUint16BE();
+
+ if (numFrames) {
+ int a = stream->readUint32LE();
+ frames = new AnimFrame [numFrames];
+ if (!checkNew(frames))
+ return false;
+ theSprites = g_sludge->_gfxMan->loadBankForAnim(a);
+
+ for (a = 0; a < numFrames; a++) {
+ frames[a].frameNum = stream->readUint32LE();
+ frames[a].howMany = stream->readUint32LE();
+ if (ssgVersion >= VERSION(2, 0)) {
+ frames[a].noise = stream->readUint32LE();
+ } else {
+ frames[a].noise = 0;
+ }
+ }
+ } else {
+ theSprites = NULL;
+ frames = NULL;
+ }
+ return true;
+}
+
+bool Persona::save(Common::WriteStream *stream) {
+ int a;
+ stream->writeUint16BE(numDirections);
+ for (a = 0; a < numDirections * 3; a++) {
+ if (!animation[a]->save(stream))
+ return false;
+ }
+ return true;
+}
+
+bool Persona::load(Common::SeekableReadStream *stream) {
+ int a;
+ numDirections = stream->readUint16BE();
+ animation = new PersonaAnimation *[numDirections * 3];
+ if (!checkNew(animation))
+ return false;
+ for (a = 0; a < numDirections * 3; a++) {
+ animation[a] = new PersonaAnimation;
+ if (!checkNew(animation[a]))
+ return false;
+
+ if (!animation[a]->load(stream))
+ return false;
+ }
+ return true;
+}
+
+void OnScreenPerson::setFrames(int a) {
+ myAnim = myPersona->animation[(a * myPersona->numDirections) + direction];
+}
+
+void OnScreenPerson::makeTalker() {
+ setFrames(ANI_TALK);
+}
+
+void OnScreenPerson::makeSilent() {
+ setFrames(ANI_STAND);
}
-void turnMeAngle(OnScreenPerson *thisPerson, int direc) {
+PeopleManager::PeopleManager(SludgeEngine *vm) {
+ _vm = vm;
+ _allPeople = new OnScreenPersonList;
+ _scaleHorizon = 75;
+ _scaleDivide = 150;
+ _personRegion = new ScreenRegion;
+}
+
+PeopleManager::~PeopleManager() {
+ kill();
+
+ delete _personRegion;
+ _personRegion = nullptr;
+
+ delete _allPeople;
+ _allPeople = nullptr;
+}
+
+void PeopleManager::turnMeAngle(OnScreenPerson *thisPerson, int direc) {
int d = thisPerson->myPersona->numDirections;
thisPerson->angle = direc;
direc += (180 / d) + 180 + thisPerson->angleOffset;
@@ -157,16 +223,14 @@ void turnMeAngle(OnScreenPerson *thisPerson, int direc) {
thisPerson->direction = (direc * d) / 360;
}
-bool initPeople() {
- personRegion.sX = 0;
- personRegion.sY = 0;
- personRegion.di = -1;
- allScreenRegions = NULL;
-
+bool PeopleManager::init() {
+ _personRegion->sX = 0;
+ _personRegion->sY = 0;
+ _personRegion->di = -1;
return true;
}
-void spinStep(OnScreenPerson *thisPerson) {
+void PeopleManager::spinStep(OnScreenPerson *thisPerson) {
int diff = (thisPerson->angle + 360) - thisPerson->wantAngle;
int eachSlice = thisPerson->spinSpeed ? thisPerson->spinSpeed : (360 / thisPerson->myPersona->numDirections);
while (diff > 180) {
@@ -183,7 +247,7 @@ void spinStep(OnScreenPerson *thisPerson) {
}
}
-void rethinkAngle(OnScreenPerson *thisPerson) {
+void PeopleManager::rethinkAngle(OnScreenPerson *thisPerson) {
int d = thisPerson->myPersona->numDirections;
int direc = thisPerson->angle + (180 / d) + 180 + thisPerson->angleOffset;
while (direc >= 360)
@@ -191,7 +255,7 @@ void rethinkAngle(OnScreenPerson *thisPerson) {
thisPerson->direction = (direc * d) / 360;
}
-bool turnPersonToFace(int thisNum, int direc) {
+bool PeopleManager::turnPersonToFace(int thisNum, int direc) {
OnScreenPerson *thisPerson = findPerson(thisNum);
if (thisPerson) {
if (thisPerson->continueAfterWalking)
@@ -200,13 +264,14 @@ bool turnPersonToFace(int thisNum, int direc) {
thisPerson->walking = false;
thisPerson->spinning = false;
turnMeAngle(thisPerson, direc);
- setFrames(*thisPerson, g_sludge->_speechMan->isCurrentTalker(thisPerson) ? ANI_TALK : ANI_STAND);
+ _vm->_speechMan->isCurrentTalker(thisPerson) ?
+ thisPerson->makeTalker() : thisPerson->makeSilent();
return true;
}
return false;
}
-bool setPersonExtra(int thisNum, int extra) {
+bool PeopleManager::setPersonExtra(int thisNum, int extra) {
OnScreenPerson *thisPerson = findPerson(thisNum);
if (thisPerson) {
thisPerson->extra = extra;
@@ -217,35 +282,34 @@ bool setPersonExtra(int thisNum, int extra) {
return false;
}
-void setScale(int16 h, int16 d) {
- scaleHorizon = h;
- scaleDivide = d;
+void PeopleManager::setScale(int16 h, int16 d) {
+ _scaleHorizon = h;
+ _scaleDivide = d;
}
-void moveAndScale(OnScreenPerson &me, float x, float y) {
+void PeopleManager::moveAndScale(OnScreenPerson &me, float x, float y) {
me.x = x;
me.y = y;
- if (!(me.extra & EXTRA_NOSCALE) && scaleDivide)
- me.scale = (me.y - scaleHorizon) / scaleDivide;
+ if (!(me.extra & EXTRA_NOSCALE) && _scaleDivide)
+ me.scale = (me.y - _scaleHorizon) / _scaleDivide;
}
-OnScreenPerson *findPerson(int v) {
- OnScreenPerson *thisPerson = allPeople;
- while (thisPerson) {
- if (v == thisPerson->thisType->objectNum)
- break;
- thisPerson = thisPerson->next;
+OnScreenPerson *PeopleManager::findPerson(int v) {
+ for (OnScreenPersonList::iterator it = _allPeople->begin(); it != _allPeople->end(); ++it) {
+ if (v == (*it)->thisType->objectNum) {
+ return (*it);
+ }
}
- return thisPerson;
+ return nullptr;
}
-void movePerson(int x, int y, int objNum) {
+void PeopleManager::movePerson(int x, int y, int objNum) {
OnScreenPerson *moveMe = findPerson(objNum);
if (moveMe)
moveAndScale(*moveMe, x, y);
}
-void setShown(bool h, int ob) {
+void PeopleManager::setShown(bool h, int ob) {
OnScreenPerson *moveMe = findPerson(ob);
if (moveMe)
moveMe->show = h;
@@ -275,7 +339,7 @@ enum drawModes {
numDrawModes
};
-void setMyDrawMode(OnScreenPerson *moveMe, int h) {
+void PeopleManager::setMyDrawMode(OnScreenPerson *moveMe, int h) {
switch (h) {
case drawModeTransparent3:
moveMe->r = moveMe->g = moveMe->b = 0;
@@ -381,7 +445,7 @@ void setMyDrawMode(OnScreenPerson *moveMe, int h) {
}
-void setDrawMode(int h, int ob) {
+void PeopleManager::setDrawMode(int h, int ob) {
OnScreenPerson *moveMe = findPerson(ob);
if (!moveMe)
return;
@@ -389,7 +453,7 @@ void setDrawMode(int h, int ob) {
setMyDrawMode(moveMe, h);
}
-void setPersonTransparency(int ob, byte x) {
+void PeopleManager::setPersonTransparency(int ob, byte x) {
OnScreenPerson *moveMe = findPerson(ob);
if (!moveMe)
return;
@@ -399,7 +463,7 @@ void setPersonTransparency(int ob, byte x) {
moveMe->transparency = x;
}
-void setPersonColourise(int ob, byte r, byte g, byte b, byte colourmix) {
+void PeopleManager::setPersonColourise(int ob, byte r, byte g, byte b, byte colourmix) {
OnScreenPerson *moveMe = findPerson(ob);
if (!moveMe)
return;
@@ -410,44 +474,29 @@ void setPersonColourise(int ob, byte r, byte g, byte b, byte colourmix) {
moveMe->colourmix = colourmix;
}
-extern ScreenRegion *overRegion;
-
-void shufflePeople() {
- OnScreenPerson **thisReference = &allPeople;
- OnScreenPerson *A, *B;
+struct PeopleYComperator {
+ bool operator()(const OnScreenPerson *p1, const OnScreenPerson *p2) {
+ float y1 = p1->extra & EXTRA_FRONT ? p1->y + 1000 : p1->y;
+ float y2 = p2->extra & EXTRA_FRONT ? p2->y + 1000 : p2->y;
+ return y1 < y2;
+ }
+};
- if (!allPeople)
+void PeopleManager::shufflePeople() {
+ if (_allPeople->empty())
return;
- while ((*thisReference)->next) {
- float y1 = (*thisReference)->y;
- if ((*thisReference)->extra & EXTRA_FRONT)
- y1 += 1000;
-
- float y2 = (*thisReference)->next->y;
- if ((*thisReference)->next->extra & EXTRA_FRONT)
- y2 += 1000;
-
- if (y1 > y2) {
- A = (*thisReference);
- B = (*thisReference)->next;
- A->next = B->next;
- B->next = A;
- (*thisReference) = B;
- } else {
- thisReference = &((*thisReference)->next);
- }
- }
+ Common::sort(_allPeople->begin(), _allPeople->end(), PeopleYComperator());
}
-void drawPeople() {
+void PeopleManager::drawPeople() {
shufflePeople();
- OnScreenPerson *thisPerson = allPeople;
- PersonaAnimation *myAnim = NULL;
- overRegion = NULL;
+ PersonaAnimation *myAnim = NULL;
+ _vm->_regionMan->resetOverRegion();
- while (thisPerson) {
+ for (OnScreenPersonList::iterator it = _allPeople->begin(); it != _allPeople->end(); ++it) {
+ OnScreenPerson * thisPerson = (*it);
if (thisPerson->show) {
myAnim = thisPerson->myAnim;
if (myAnim != thisPerson->lastUsedAnim) {
@@ -455,7 +504,7 @@ void drawPeople() {
thisPerson->frameNum = 0;
thisPerson->frameTick = myAnim->frames[0].howMany;
if (myAnim->frames[thisPerson->frameNum].noise > 0) {
- g_sludge->_soundMan->startSound(myAnim->frames[thisPerson->frameNum].noise, false);
+ _vm->_soundMan->startSound(myAnim->frames[thisPerson->frameNum].noise, false);
thisPerson->frameNum++;
thisPerson->frameNum %= thisPerson->myAnim->numFrames;
thisPerson->frameTick = thisPerson->myAnim->frames[thisPerson->frameNum].howMany;
@@ -476,13 +525,13 @@ void drawPeople() {
}
if (m != 2) {
bool r = false;
- r = g_sludge->_gfxMan->scaleSprite(myAnim->theSprites->bank.sprites[fNum], myAnim->theSprites->bank.myPalette, thisPerson, m);
+ r = _vm->_gfxMan->scaleSprite(myAnim->theSprites->bank.sprites[fNum], myAnim->theSprites->bank.myPalette, thisPerson, m);
if (r) {
if (!thisPerson->thisType->screenName.empty()) {
- if (personRegion.thisType != thisPerson->thisType)
- lastRegion = NULL;
- personRegion.thisType = thisPerson->thisType;
- overRegion = &personRegion;
+ if (_personRegion->thisType != thisPerson->thisType)
+ _vm->_regionMan->resetLastRegion();
+ _personRegion->thisType = thisPerson->thisType;
+ _vm->_regionMan->setOverRegion(_personRegion);
}
}
}
@@ -493,7 +542,7 @@ void drawPeople() {
thisPerson->frameTick = thisPerson->myAnim->frames[thisPerson->frameNum].howMany;
if (thisPerson->show && myAnim && myAnim->frames) {
if (myAnim->frames[thisPerson->frameNum].noise > 0) {
- g_sludge->_soundMan->startSound(myAnim->frames[thisPerson->frameNum].noise, false);
+ _vm->_soundMan->startSound(myAnim->frames[thisPerson->frameNum].noise, false);
thisPerson->frameNum++;
thisPerson->frameNum %= thisPerson->myAnim->numFrames;
thisPerson->frameTick = thisPerson->myAnim->frames[thisPerson->frameNum].howMany;
@@ -506,132 +555,10 @@ void drawPeople() {
}
}
}
- thisPerson = thisPerson->next;
- }
-}
-
-void makeTalker(OnScreenPerson &me) {
- setFrames(me, ANI_TALK);
-}
-
-void makeSilent(OnScreenPerson &me) {
- setFrames(me, ANI_STAND);
-}
-
-bool handleClosestPoint(int &setX, int &setY, int &setPoly) {
- int gotX = 320, gotY = 200, gotPoly = -1, i, j, xTest1, yTest1, xTest2, yTest2, closestX, closestY, oldJ, currentDistance = 0xFFFFF, thisDistance;
-
-// FILE * dbug = fopen ("debug_closest.txt", "at");
-// fprintf (dbug, "\nGetting closest point to %i, %i\n", setX, setY);
-
- for (i = 0; i < currentFloor->numPolygons; i++) {
- oldJ = currentFloor->polygon[i].numVertices - 1;
- for (j = 0; j < currentFloor->polygon[i].numVertices; j++) {
-// fprintf (dbug, "Polygon %i, line %i... ", i, j);
- xTest1 = currentFloor->vertex[currentFloor->polygon[i].vertexID[j]].x;
- yTest1 = currentFloor->vertex[currentFloor->polygon[i].vertexID[j]].y;
- xTest2 = currentFloor->vertex[currentFloor->polygon[i].vertexID[oldJ]].x;
- yTest2 = currentFloor->vertex[currentFloor->polygon[i].vertexID[oldJ]].y;
- closestPointOnLine(closestX, closestY, xTest1, yTest1, xTest2, yTest2, setX, setY);
-// fprintf (dbug, "closest point is %i, %i... ", closestX, closestY);
- xTest1 = setX - closestX;
- yTest1 = setY - closestY;
- thisDistance = xTest1 * xTest1 + yTest1 * yTest1;
-// fprintf (dbug, "Distance squared %i\n", thisDistance);
-
- if (thisDistance < currentDistance) {
-// fprintf (dbug, "** We have a new winner!**\n");
-
- currentDistance = thisDistance;
- gotX = closestX;
- gotY = closestY;
- gotPoly = i;
- }
- oldJ = j;
- }
}
-// fclose (dbug);
-
- if (gotPoly == -1)
- return false;
- setX = gotX;
- setY = gotY;
- setPoly = gotPoly;
-
- return true;
}
-bool doBorderStuff(OnScreenPerson *moveMe) {
- if (moveMe->inPoly == moveMe->walkToPoly) {
- moveMe->inPoly = -1;
- moveMe->thisStepX = moveMe->walkToX;
- moveMe->thisStepY = moveMe->walkToY;
- } else {
- // The section in which we need to be next...
- int newPoly = currentFloor->matrix[moveMe->inPoly][moveMe->walkToPoly];
- if (newPoly == -1)
- return false;
-
- // Grab the index of the second matching corner...
- int ID, ID2;
- if (!getMatchingCorners(currentFloor->polygon[moveMe->inPoly], currentFloor->polygon[newPoly], ID, ID2))
- return fatal("Not a valid floor plan!");
-
- // Remember that we're walking to the new polygon...
- moveMe->inPoly = newPoly;
-
- // Calculate the destination position on the coincidantal line...
- int x1 = moveMe->x, y1 = moveMe->y;
- int x2 = moveMe->walkToX, y2 = moveMe->walkToY;
- int x3 = currentFloor->vertex[ID].x, y3 = currentFloor->vertex[ID].y;
- int x4 = currentFloor->vertex[ID2].x, y4 = currentFloor->vertex[ID2].y;
-
- int xAB = x1 - x2;
- int yAB = y1 - y2;
- int xCD = x4 - x3;
- int yCD = y4 - y3;
-
- double m = (yAB * (x3 - x1) - xAB * (y3 - y1));
- m /= ((xAB * yCD) - (yAB * xCD));
-
- if (m > 0 && m < 1) {
- moveMe->thisStepX = x3 + m * xCD;
- moveMe->thisStepY = y3 + m * yCD;
- } else {
- int dx13 = x1 - x3, dx14 = x1 - x4, dx23 = x2 - x3, dx24 = x2 - x4;
- int dy13 = y1 - y3, dy14 = y1 - y4, dy23 = y2 - y3, dy24 = y2 - y4;
-
- dx13 *= dx13;
- dx14 *= dx14;
- dx23 *= dx23;
- dx24 *= dx24;
- dy13 *= dy13;
- dy14 *= dy14;
- dy23 *= dy23;
- dy24 *= dy24;
-
- if (sqrt((double)dx13 + dy13) + sqrt((double)dx23 + dy23) < sqrt((double)dx14 + dy14) + sqrt((double)dx24 + dy24)) {
- moveMe->thisStepX = x3;
- moveMe->thisStepY = y3;
- } else {
- moveMe->thisStepX = x4;
- moveMe->thisStepY = y4;
- }
- }
- }
-
- float yDiff = moveMe->thisStepY - moveMe->y;
- float xDiff = moveMe->x - moveMe->thisStepX;
- if (xDiff || yDiff) {
- moveMe->wantAngle = 180 + ANGLEFIX * atan2(xDiff, yDiff * 2);
- moveMe->spinning = true;
- }
-
- setFrames(*moveMe, ANI_WALK);
- return true;
-}
-
-bool walkMe(OnScreenPerson *thisPerson, bool move = true) {
+bool PeopleManager::walkMe(OnScreenPerson *thisPerson, bool move) {
float xDiff, yDiff, maxDiff, s;
for (;;) {
@@ -646,7 +573,7 @@ bool walkMe(OnScreenPerson *thisPerson, bool move = true) {
if (ABS(maxDiff) > s) {
if (thisPerson->spinning) {
spinStep(thisPerson);
- setFrames(*thisPerson, ANI_WALK);
+ thisPerson->setFrames(ANI_WALK);
}
s = maxDiff / s;
if (move)
@@ -662,20 +589,20 @@ bool walkMe(OnScreenPerson *thisPerson, bool move = true) {
}
break;
}
- if (!doBorderStuff(thisPerson))
+ if (!_vm->_floorMan->doBorderStuff(thisPerson))
break;
}
thisPerson->walking = false;
- setFrames(*thisPerson, ANI_STAND);
+ thisPerson->setFrames(ANI_STAND);
moveAndScale(*thisPerson, thisPerson->walkToX, thisPerson->walkToY);
return false;
}
-bool makeWalkingPerson(int x, int y, int objNum, LoadedFunction *func, int di) {
+bool PeopleManager::makeWalkingPerson(int x, int y, int objNum, LoadedFunction *func, int di) {
if (x == 0 && y == 0)
return false;
- if (currentFloor->numPolygons == 0)
+ if (_vm->_floorMan->isFloorNoPolygon())
return false;
OnScreenPerson *moveMe = findPerson(objNum);
if (!moveMe)
@@ -689,20 +616,20 @@ bool makeWalkingPerson(int x, int y, int objNum, LoadedFunction *func, int di) {
moveMe->walkToX = x;
moveMe->walkToY = y;
- moveMe->walkToPoly = inFloor(x, y);
+ moveMe->walkToPoly = _vm->_floorMan->inFloor(x, y);
if (moveMe->walkToPoly == -1) {
- if (!handleClosestPoint(moveMe->walkToX, moveMe->walkToY, moveMe->walkToPoly))
+ if (!_vm->_floorMan->handleClosestPoint(moveMe->walkToX, moveMe->walkToY, moveMe->walkToPoly))
return false;
}
- moveMe->inPoly = inFloor(moveMe->x, moveMe->y);
+ moveMe->inPoly = _vm->_floorMan->inFloor(moveMe->x, moveMe->y);
if (moveMe->inPoly == -1) {
int xxx = moveMe->x, yyy = moveMe->y;
- if (!handleClosestPoint(xxx, yyy, moveMe->inPoly))
+ if (!_vm->_floorMan->handleClosestPoint(xxx, yyy, moveMe->inPoly))
return false;
}
- doBorderStuff(moveMe);
+ _vm->_floorMan->doBorderStuff(moveMe);
if (walkMe(moveMe, false) || moveMe->spinning) {
moveMe->continueAfterWalking = func;
return true;
@@ -711,7 +638,7 @@ bool makeWalkingPerson(int x, int y, int objNum, LoadedFunction *func, int di) {
}
}
-bool stopPerson(int o) {
+bool PeopleManager::stopPerson(int o) {
OnScreenPerson *moveMe = findPerson(o);
if (moveMe)
if (moveMe->continueAfterWalking) {
@@ -719,13 +646,13 @@ bool stopPerson(int o) {
moveMe->continueAfterWalking = NULL;
moveMe->walking = false;
moveMe->spinning = false;
- setFrames(*moveMe, ANI_STAND);
+ moveMe->setFrames(ANI_STAND);
return true;
}
return false;
}
-bool forceWalkingPerson(int x, int y, int objNum, LoadedFunction *func, int di) {
+bool PeopleManager::forceWalkingPerson(int x, int y, int objNum, LoadedFunction *func, int di) {
if (x == 0 && y == 0)
return false;
OnScreenPerson *moveMe = findPerson(objNum);
@@ -746,7 +673,7 @@ bool forceWalkingPerson(int x, int y, int objNum, LoadedFunction *func, int di)
moveMe->inPoly = 0;
moveMe->walkToPoly = 0;
- doBorderStuff(moveMe);
+ _vm->_floorMan->doBorderStuff(moveMe);
if (walkMe(moveMe) || moveMe->spinning) {
moveMe->continueAfterWalking = func;
return true;
@@ -755,7 +682,7 @@ bool forceWalkingPerson(int x, int y, int objNum, LoadedFunction *func, int di)
}
}
-void jumpPerson(int x, int y, int objNum) {
+void PeopleManager::jumpPerson(int x, int y, int objNum) {
if (x == 0 && y == 0)
return;
OnScreenPerson *moveMe = findPerson(objNum);
@@ -769,7 +696,7 @@ void jumpPerson(int x, int y, int objNum) {
moveAndScale(*moveMe, x, y);
}
-bool floatCharacter(int f, int objNum) {
+bool PeopleManager::floatCharacter(int f, int objNum) {
OnScreenPerson *moveMe = findPerson(objNum);
if (!moveMe)
return false;
@@ -777,7 +704,7 @@ bool floatCharacter(int f, int objNum) {
return true;
}
-bool setCharacterWalkSpeed(int f, int objNum) {
+bool PeopleManager::setCharacterWalkSpeed(int f, int objNum) {
if (f <= 0)
return false;
OnScreenPerson *moveMe = findPerson(objNum);
@@ -787,31 +714,29 @@ bool setCharacterWalkSpeed(int f, int objNum) {
return true;
}
-void walkAllPeople() {
- OnScreenPerson *thisPerson = allPeople;
-
- while (thisPerson) {
+void PeopleManager::walkAllPeople() {
+ for (OnScreenPersonList::iterator it = _allPeople->begin(); it != _allPeople->end(); ++it) {
+ OnScreenPerson *thisPerson = (*it);
if (thisPerson->walking) {
walkMe(thisPerson);
} else if (thisPerson->spinning) {
spinStep(thisPerson);
- setFrames(*thisPerson, ANI_STAND);
+ thisPerson->setFrames(ANI_STAND);
}
if ((!thisPerson->walking) && (!thisPerson->spinning) && thisPerson->continueAfterWalking) {
restartFunction(thisPerson->continueAfterWalking);
thisPerson->continueAfterWalking = NULL;
}
- thisPerson = thisPerson->next;
}
}
-bool addPerson(int x, int y, int objNum, Persona *p) {
+bool PeopleManager::addPerson(int x, int y, int objNum, Persona *p) {
OnScreenPerson *newPerson = new OnScreenPerson;
if (!checkNew(newPerson))
return false;
- // EASY STUFF
- newPerson->thisType = g_sludge->_objMan->loadObjectType(objNum);
+ // Init newPerson
+ newPerson->thisType = _vm->_objMan->loadObjectType(objNum);
newPerson->scale = 1;
newPerson->extra = 0;
newPerson->continueAfterWalking = NULL;
@@ -839,7 +764,7 @@ bool addPerson(int x, int y, int objNum, Persona *p) {
newPerson->lastUsedAnim = 0;
newPerson->frameTick = 0;
- setFrames(*newPerson, ANI_STAND);
+ newPerson->setFrames(ANI_STAND);
// HEIGHT (BASED ON 1st FRAME OF 1st ANIMATION... INC. SPECIAL CASES)
int fNumSigned = p->animation[0]->frames[0].frameNum;
@@ -854,27 +779,23 @@ bool addPerson(int x, int y, int objNum, Persona *p) {
newPerson->height = p->animation[0]->theSprites->bank.sprites[fNum].yhot + 5;
}
- // NOW ADD IT IN THE RIGHT PLACE
- OnScreenPerson **changethat = &allPeople;
-
- while (((*changethat) != NULL) && ((*changethat)->y < y))
- changethat = &((*changethat)->next);
-
- newPerson->next = (*changethat);
- (*changethat) = newPerson;
+ // NOW INSERT IT IN THE RIGHT PLACE
+ bool inserted = false;
+ for (OnScreenPersonList::iterator it = _allPeople->begin(); it != _allPeople->end(); ++it) {
+ if ((*it)->y >= y) {
+ _allPeople->insert(it, newPerson);
+ inserted = true;
+ break;
+ }
+ }
+ if (!inserted) {
+ _allPeople->push_back(newPerson);
+ }
return (bool)(newPerson->thisType != NULL);
}
-int timeForAnim(PersonaAnimation *fram) {
- int total = 0;
- for (int a = 0; a < fram->numFrames; a++) {
- total += fram->frames[a].howMany;
- }
- return total;
-}
-
-void animatePerson(int obj, PersonaAnimation *fram) { // Set a new SINGLE animation
+void PeopleManager::animatePerson(int obj, PersonaAnimation *fram) { // Set a new SINGLE animation
OnScreenPerson *moveMe = findPerson(obj);
if (moveMe) {
if (moveMe->continueAfterWalking)
@@ -886,231 +807,127 @@ void animatePerson(int obj, PersonaAnimation *fram) { // Set a new SINGLE anima
}
}
-void animatePerson(int obj, Persona *per) { // Set a new costume
+void PeopleManager::animatePerson(int obj, Persona *per) { // Set a new costume
OnScreenPerson *moveMe = findPerson(obj);
if (moveMe) {
- // if (moveMe->continueAfterWalking) abortFunction (moveMe->continueAfterWalking);
- // moveMe->continueAfterWalking = NULL;
- // moveMe->walking = false;
moveMe->spinning = false;
moveMe->myPersona = per;
rethinkAngle(moveMe);
if (moveMe->walking) {
- setFrames(*moveMe, ANI_WALK);
+ moveMe->setFrames(ANI_WALK);
} else {
- setFrames(*moveMe, ANI_STAND);
+ moveMe->setFrames(ANI_STAND);
}
}
}
-void killAllPeople() {
- OnScreenPerson *killPeople;
- while (allPeople) {
- if (allPeople->continueAfterWalking)
- abortFunction(allPeople->continueAfterWalking);
- allPeople->continueAfterWalking = NULL;
- killPeople = allPeople;
- allPeople = allPeople->next;
- g_sludge->_objMan->removeObjectType(killPeople->thisType);
- delete killPeople;
+void PeopleManager::kill() {
+ for (OnScreenPersonList::iterator it = _allPeople->begin(); it != _allPeople->end(); ++it) {
+ if ((*it)->continueAfterWalking)
+ abortFunction((*it)->continueAfterWalking);
+ (*it)->continueAfterWalking = NULL;
+ _vm->_objMan->removeObjectType((*it)->thisType);
+ delete (*it);
+ (*it) = nullptr;
}
+ _allPeople->clear();
}
-void killMostPeople() {
- OnScreenPerson *killPeople;
- OnScreenPerson **lookyHere = &allPeople;
-
- while (*lookyHere) {
- if ((*lookyHere)->extra & EXTRA_NOREMOVE) {
- lookyHere = &(*lookyHere)->next;
- } else {
- killPeople = (*lookyHere);
-
- // Change last pointer to NEXT in the list instead
- (*lookyHere) = killPeople->next;
+void PeopleManager::killMostPeople() {
+ for (OnScreenPersonList::iterator it = _allPeople->begin(); it != _allPeople->end(); ++it) {
+ if (!((*it)->extra & EXTRA_NOREMOVE)) {
+ OnScreenPerson *killPeople = (*it);
+ _allPeople->reverse_erase(it);
// Gone from the list... now free some memory
if (killPeople->continueAfterWalking)
abortFunction(killPeople->continueAfterWalking);
killPeople->continueAfterWalking = NULL;
- g_sludge->_objMan->removeObjectType(killPeople->thisType);
+ _vm->_objMan->removeObjectType(killPeople->thisType);
delete killPeople;
}
}
}
-void removeOneCharacter(int i) {
- OnScreenPerson *p = findPerson(i);
-
- if (p) {
- if (overRegion == &personRegion && overRegion->thisType == p->thisType) {
- overRegion = NULL;
- }
-
- if (p->continueAfterWalking)
- abortFunction(p->continueAfterWalking);
- p->continueAfterWalking = NULL;
- OnScreenPerson **killPeople;
-
- for (killPeople = &allPeople; *killPeople != p; killPeople = &((*killPeople)->next)) {
- ;
+void PeopleManager::removeOneCharacter(int i) {
+ OnScreenPerson *removePerson = findPerson(i);
+ if (removePerson) {
+ ScreenRegion *overRegion = _vm->_regionMan->getOverRegion();
+ if (overRegion == _personRegion && overRegion->thisType == removePerson->thisType) {
+ overRegion = nullptr;
}
- *killPeople = p->next;
- g_sludge->_objMan->removeObjectType(p->thisType);
- delete p;
- }
-}
-
-bool saveAnim(PersonaAnimation *p, Common::WriteStream *stream) {
- stream->writeUint16BE(p->numFrames);
- if (p->numFrames) {
- stream->writeUint32LE(p->theSprites->ID);
+ if (removePerson->continueAfterWalking)
+ abortFunction(removePerson->continueAfterWalking);
+ removePerson->continueAfterWalking = NULL;
- for (int a = 0; a < p->numFrames; a++) {
- stream->writeUint32LE(p->frames[a].frameNum);
- stream->writeUint32LE(p->frames[a].howMany);
- stream->writeUint32LE(p->frames[a].noise);
- }
+ _allPeople->remove(removePerson);
+ _vm->_objMan->removeObjectType(removePerson->thisType);
+ delete removePerson;
+ removePerson = nullptr;
}
- return true;
}
-bool loadAnim(PersonaAnimation *p, Common::SeekableReadStream *stream) {
- p->numFrames = stream->readUint16BE();
-
- if (p->numFrames) {
- int a = stream->readUint32LE();
- p->frames = new AnimFrame [p->numFrames];
- if (!checkNew(p->frames))
- return false;
- p->theSprites = g_sludge->_gfxMan->loadBankForAnim(a);
-
- for (a = 0; a < p->numFrames; a++) {
- p->frames[a].frameNum = stream->readUint32LE();
- p->frames[a].howMany = stream->readUint32LE();
- if (ssgVersion >= VERSION(2, 0)) {
- p->frames[a].noise = stream->readUint32LE();
- } else {
- p->frames[a].noise = 0;
- }
- }
- } else {
- p->theSprites = NULL;
- p->frames = NULL;
- }
- return true;
-}
-
-bool saveCostume(Persona *cossy, Common::WriteStream *stream) {
- int a;
- stream->writeUint16BE(cossy->numDirections);
- for (a = 0; a < cossy->numDirections * 3; a++) {
- if (!saveAnim(cossy->animation[a], stream))
- return false;
- }
-// debugCostume ("Saved", cossy);
- return true;
-}
-
-bool loadCostume(Persona *cossy, Common::SeekableReadStream *stream) {
- int a;
- cossy->numDirections = stream->readUint16BE();
- cossy->animation = new PersonaAnimation *[cossy->numDirections * 3];
- if (!checkNew(cossy->animation))
- return false;
- for (a = 0; a < cossy->numDirections * 3; a++) {
- cossy->animation[a] = new PersonaAnimation ;
- if (!checkNew(cossy->animation[a]))
- return false;
-
- if (!loadAnim(cossy->animation[a], stream))
- return false;
- }
-// debugCostume ("Loaded", cossy);
- return true;
-}
-
-bool savePeople(Common::WriteStream *stream) {
- OnScreenPerson *me = allPeople;
- int countPeople = 0, a;
-
- stream->writeSint16LE(scaleHorizon);
- stream->writeSint16LE(scaleDivide);
-
- while (me) {
- countPeople++;
- me = me->next;
- }
-
+bool PeopleManager::savePeople(Common::WriteStream* stream) {
+ stream->writeSint16LE(_scaleHorizon);
+ stream->writeSint16LE(_scaleDivide);
+ int countPeople = _allPeople->size();
stream->writeUint16BE(countPeople);
-
- me = allPeople;
- for (a = 0; a < countPeople; a++) {
-
- stream->writeFloatLE(me->x);
- stream->writeFloatLE(me->y);
-
- saveCostume(me->myPersona, stream);
- saveAnim(me->myAnim, stream);
- stream->writeByte(me->myAnim == me->lastUsedAnim);
-
- stream->writeFloatLE(me->scale);
-
- stream->writeUint16BE(me->extra);
- stream->writeUint16BE(me->height);
- stream->writeUint16BE(me->walkToX);
- stream->writeUint16BE(me->walkToY);
- stream->writeUint16BE(me->thisStepX);
- stream->writeUint16BE(me->thisStepY);
- stream->writeUint16BE(me->frameNum);
- stream->writeUint16BE(me->frameTick);
- stream->writeUint16BE(me->walkSpeed);
- stream->writeUint16BE(me->spinSpeed);
- stream->writeSint16LE(me->floaty);
- stream->writeByte(me->show);
- stream->writeByte(me->walking);
- stream->writeByte(me->spinning);
- if (me->continueAfterWalking) {
+ for (OnScreenPersonList::iterator it = _allPeople->begin(); it != _allPeople->end(); ++it) {
+ stream->writeFloatLE((*it)->x);
+ stream->writeFloatLE((*it)->y);
+ (*it)->myPersona->save(stream);
+ (*it)->myAnim->save(stream);
+ stream->writeByte((*it)->myAnim == (*it)->lastUsedAnim);
+ stream->writeFloatLE((*it)->scale);
+ stream->writeUint16BE((*it)->extra);
+ stream->writeUint16BE((*it)->height);
+ stream->writeUint16BE((*it)->walkToX);
+ stream->writeUint16BE((*it)->walkToY);
+ stream->writeUint16BE((*it)->thisStepX);
+ stream->writeUint16BE((*it)->thisStepY);
+ stream->writeUint16BE((*it)->frameNum);
+ stream->writeUint16BE((*it)->frameTick);
+ stream->writeUint16BE((*it)->walkSpeed);
+ stream->writeUint16BE((*it)->spinSpeed);
+ stream->writeSint16LE((*it)->floaty);
+ stream->writeByte((*it)->show);
+ stream->writeByte((*it)->walking);
+ stream->writeByte((*it)->spinning);
+ if ((*it)->continueAfterWalking) {
stream->writeByte(1);
- saveFunction(me->continueAfterWalking, stream);
+ saveFunction((*it)->continueAfterWalking, stream);
} else {
stream->writeByte(0);
}
- stream->writeUint16BE(me->direction);
- stream->writeUint16BE(me->angle);
- stream->writeUint16BE(me->angleOffset);
- stream->writeUint16BE(me->wantAngle);
- stream->writeSint16LE(me->directionWhenDoneWalking);
- stream->writeSint16LE(me->inPoly);
- stream->writeSint16LE(me->walkToPoly);
-
- stream->writeByte(me->r);
- stream->writeByte(me->g);
- stream->writeByte(me->b);
- stream->writeByte(me->colourmix);
- stream->writeByte(me->transparency);
-
- g_sludge->_objMan->saveObjectRef(me->thisType, stream);
-
- me = me->next;
+ stream->writeUint16BE((*it)->direction);
+ stream->writeUint16BE((*it)->angle);
+ stream->writeUint16BE((*it)->angleOffset);
+ stream->writeUint16BE((*it)->wantAngle);
+ stream->writeSint16LE((*it)->directionWhenDoneWalking);
+ stream->writeSint16LE((*it)->inPoly);
+ stream->writeSint16LE((*it)->walkToPoly);
+ stream->writeByte((*it)->r);
+ stream->writeByte((*it)->g);
+ stream->writeByte((*it)->b);
+ stream->writeByte((*it)->colourmix);
+ stream->writeByte((*it)->transparency);
+ _vm->_objMan->saveObjectRef((*it)->thisType, stream);
}
return true;
}
-bool loadPeople(Common::SeekableReadStream *stream) {
- OnScreenPerson **pointy = &allPeople;
- OnScreenPerson *me;
+bool PeopleManager::loadPeople(Common::SeekableReadStream *stream) {
+ kill();
- scaleHorizon = stream->readSint16LE();
- scaleDivide = stream->readSint16LE();
+ _scaleHorizon = stream->readSint16LE();
+ _scaleDivide = stream->readSint16LE();
int countPeople = stream->readUint16BE();
int a;
- allPeople = NULL;
for (a = 0; a < countPeople; a++) {
- me = new OnScreenPerson;
+ OnScreenPerson *me = new OnScreenPerson;
if (!checkNew(me))
return false;
@@ -1118,15 +935,15 @@ bool loadPeople(Common::SeekableReadStream *stream) {
if (!checkNew(me->myPersona))
return false;
- me->myAnim = new PersonaAnimation ;
+ me->myAnim = new PersonaAnimation;
if (!checkNew(me->myAnim))
return false;
me->x = stream->readFloatLE();
me->y = stream->readFloatLE();
- loadCostume(me->myPersona, stream);
- loadAnim(me->myAnim, stream);
+ me->myPersona->load(stream);
+ me->myAnim->load(stream);
me->lastUsedAnim = stream->readByte() ? me->myAnim : NULL;
@@ -1173,7 +990,7 @@ bool loadPeople(Common::SeekableReadStream *stream) {
} else {
setMyDrawMode(me, stream->readUint16BE());
}
- me->thisType = g_sludge->_objMan->loadObjectRef(stream);
+ me->thisType = _vm->_objMan->loadObjectRef(stream);
// Anti-aliasing settings
if (ssgVersion >= VERSION(1, 6)) {
@@ -1184,13 +1001,22 @@ bool loadPeople(Common::SeekableReadStream *stream) {
stream->readFloatLE();
}
}
-
- me->next = NULL;
- *pointy = me;
- pointy = &(me->next);
+ _allPeople->push_back(me);
}
-// db ("End of loadPeople");
return true;
}
+void PeopleManager::freeze(FrozenStuffStruct *frozenStuff) {
+ frozenStuff->allPeople = _allPeople;
+ _allPeople = nullptr;
+ _allPeople = new OnScreenPersonList;
+}
+
+void PeopleManager::resotre(FrozenStuffStruct *frozenStuff) {
+ kill();
+ delete _allPeople;
+ _allPeople = nullptr;
+ _allPeople = frozenStuff->allPeople;
+}
+
} // End of namespace Sludge
diff --git a/engines/sludge/people.h b/engines/sludge/people.h
index 95b8e923b6..db22d19ad1 100644
--- a/engines/sludge/people.h
+++ b/engines/sludge/people.h
@@ -26,6 +26,12 @@
namespace Sludge {
+struct FrozenStuffStruct;
+struct LoadedSpriteBank;
+struct ScreenRegion;
+
+class SludgeEngine;
+
struct AnimFrame {
int frameNum, howMany;
int noise;
@@ -41,26 +47,41 @@ struct AnimFrame {
#define EXTRA_RECTANGULAR 64
struct PersonaAnimation {
- struct LoadedSpriteBank *theSprites;
- AnimFrame *frames;
+ LoadedSpriteBank *theSprites;
+ AnimFrame *frames;
int numFrames;
+
+ PersonaAnimation();
+ PersonaAnimation(int num, struct VariableStack *&stacky);
+ PersonaAnimation(PersonaAnimation *orig);
+ ~PersonaAnimation();
+
+ // Setter & getter
+ int getTotalTime();
+
+ // Save & load
+ bool save(Common::WriteStream *stream);
+ bool load(Common::SeekableReadStream *stream);
};
struct Persona {
- PersonaAnimation **animation;
+ PersonaAnimation **animation;
int numDirections;
+
+ // Save & load
+ bool save(Common::WriteStream *stream);
+ bool load(Common::SeekableReadStream *stream);
};
struct OnScreenPerson {
float x, y;
int height, floaty, walkSpeed;
float scale;
- OnScreenPerson *next;
int walkToX, walkToY, thisStepX, thisStepY, inPoly, walkToPoly;
bool walking, spinning;
struct LoadedFunction *continueAfterWalking;
- PersonaAnimation *myAnim;
- PersonaAnimation *lastUsedAnim;
+ PersonaAnimation *myAnim;
+ PersonaAnimation *lastUsedAnim;
Persona *myPersona;
int frameNum, frameTick, angle, wantAngle, angleOffset;
bool show;
@@ -68,64 +89,84 @@ struct OnScreenPerson {
struct ObjectType *thisType;
int extra, spinSpeed;
byte r, g, b, colourmix, transparency;
+
+ void makeTalker();
+ void makeSilent();
+ void setFrames(int a);
};
-// Initialisation and creation
-bool initPeople();
-bool addPerson(int x, int y, int objNum, Persona *p);
-
-// Draw to screen and to backdrop
-void drawPeople();
-void freezePeople(int, int);
-
-// Removalisationisms
-void killAllPeople();
-void killMostPeople();
-void removeOneCharacter(int i);
-
-// Things which affect or use all characters
-OnScreenPerson *findPerson(int v);
-void setScale(int16 h, int16 d);
-
-// Things which affect one character
-void makeTalker(OnScreenPerson &me);
-void makeSilent(OnScreenPerson &me);
-void setShown(bool h, int ob);
-void setDrawMode(int h, int ob);
-void setPersonTransparency(int ob, byte x);
-void setPersonColourise(int ob, byte r, byte g, byte b, byte colourmix);
-
-// Moving 'em
-void movePerson(int x, int y, int objNum);
-bool makeWalkingPerson(int x, int y, int objNum, struct LoadedFunction *func, int di);
-bool forceWalkingPerson(int x, int y, int objNum, struct LoadedFunction *func, int di);
-void jumpPerson(int x, int y, int objNum);
-void walkAllPeople();
-bool turnPersonToFace(int thisNum, int direc);
-bool stopPerson(int o);
-bool floatCharacter(int f, int objNum);
-bool setCharacterWalkSpeed(int f, int objNum);
-
-// Animating 'em
-void animatePerson(int obj, PersonaAnimation *);
-void animatePerson(int obj, Persona *per);
-PersonaAnimation *createPersonaAnim(int num, struct VariableStack *&stacky);
-inline void setBankFile(PersonaAnimation *newP, LoadedSpriteBank *sB) {
- newP->theSprites = sB;
-}
-bool setPersonExtra(int f, int newSetting);
-int timeForAnim(PersonaAnimation *fram);
-PersonaAnimation *copyAnim(PersonaAnimation *orig);
-PersonaAnimation *makeNullAnim();
-void deleteAnim(PersonaAnimation *orig);
-
-// Loading and saving
-bool saveAnim(PersonaAnimation *p, Common::WriteStream *stream);
-bool loadAnim(PersonaAnimation *p, Common::SeekableReadStream *stream);
-bool savePeople(Common::WriteStream *stream);
-bool loadPeople(Common::SeekableReadStream *stream);
-bool saveCostume(Persona *cossy, Common::WriteStream *stream);
-bool loadCostume(Persona *cossy, Common::SeekableReadStream *stream);
+typedef Common::List<OnScreenPerson *> OnScreenPersonList;
+
+class PeopleManager {
+public:
+ PeopleManager(SludgeEngine *vm);
+ ~PeopleManager();
+
+ // Initialisation and creation
+ bool init();
+ bool addPerson(int x, int y, int objNum, Persona *p);
+
+ // Draw to screen and to backdrop
+ void drawPeople();
+ void freezePeople(int, int);
+
+ // Removalisationisms
+ void kill();
+ void killMostPeople();
+ void removeOneCharacter(int i);
+
+ // Things which affect or use all characters
+ OnScreenPerson *findPerson(int v);
+ void setScale(int16 h, int16 d);
+
+ // Things which affect one character
+ void setShown(bool h, int ob);
+ void setDrawMode(int h, int ob);
+ void setPersonTransparency(int ob, byte x);
+ void setPersonColourise(int ob, byte r, byte g, byte b, byte colourmix);
+
+ // Moving 'em
+ void movePerson(int x, int y, int objNum);
+ bool makeWalkingPerson(int x, int y, int objNum, struct LoadedFunction *func, int di);
+ bool forceWalkingPerson(int x, int y, int objNum, struct LoadedFunction *func, int di);
+ void jumpPerson(int x, int y, int objNum);
+ void walkAllPeople();
+ bool turnPersonToFace(int thisNum, int direc);
+ bool stopPerson(int o);
+ bool floatCharacter(int f, int objNum);
+ bool setCharacterWalkSpeed(int f, int objNum);
+
+ // Animating 'em
+ void animatePerson(int obj, PersonaAnimation *);
+ void animatePerson(int obj, Persona *per);
+ bool setPersonExtra(int f, int newSetting);
+
+ // Loading and saving
+ bool savePeople(Common::WriteStream *stream);
+ bool loadPeople(Common::SeekableReadStream *stream);
+
+ // Freeze
+ void freeze(FrozenStuffStruct *frozenStuff);
+ void resotre(FrozenStuffStruct *frozenStuff);
+
+private:
+ ScreenRegion *_personRegion;
+ OnScreenPersonList *_allPeople;
+ int16 _scaleHorizon;
+ int16 _scaleDivide;
+
+ SludgeEngine *_vm;
+
+ void shufflePeople();
+
+ // OnScreenPerson manipulation
+ void turnMeAngle(OnScreenPerson *thisPerson, int direc);
+ void spinStep(OnScreenPerson *thisPerson);
+ void rethinkAngle(OnScreenPerson *thisPerson);
+ void moveAndScale(OnScreenPerson &me, float x, float y);
+ void setMyDrawMode(OnScreenPerson *moveMe, int h);
+ bool walkMe(OnScreenPerson *thisPerson, bool move = true);
+};
} // End of namespace Sludge
diff --git a/engines/sludge/region.cpp b/engines/sludge/region.cpp
index 7593fe4aee..4410951057 100644
--- a/engines/sludge/region.cpp
+++ b/engines/sludge/region.cpp
@@ -33,75 +33,65 @@
namespace Sludge {
-ScreenRegion *allScreenRegions = nullptr;
-ScreenRegion *overRegion = nullptr;
-ScreenRegion *lastRegion = nullptr;
-
-void showBoxes() {
- ScreenRegion*huntRegion = allScreenRegions;
-
- while (huntRegion) {
- g_sludge->_gfxMan->drawVerticalLine(huntRegion->x1, huntRegion->y1, huntRegion->y2);
- g_sludge->_gfxMan->drawVerticalLine(huntRegion->x2, huntRegion->y1, huntRegion->y2);
- g_sludge->_gfxMan->drawHorizontalLine(huntRegion->x1, huntRegion->y1, huntRegion->x2);
- g_sludge->_gfxMan->drawHorizontalLine(huntRegion->x1, huntRegion->y2, huntRegion->x2);
- huntRegion = huntRegion->next;
- }
+RegionManager::RegionManager(SludgeEngine *vm)
+{
+ _vm = vm;
+ _allScreenRegions = new ScreenRegionList;
+ _allScreenRegions->clear();
+ _lastRegion = nullptr;
+ _overRegion = nullptr;
+}
+
+RegionManager::~RegionManager() {
+ kill();
+
+ delete _allScreenRegions;
+ _allScreenRegions = nullptr;
}
-void removeScreenRegion(int objectNum) {
- ScreenRegion **huntRegion = &allScreenRegions;
- ScreenRegion *killMe;
+void RegionManager::showBoxes() {
+ for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
+ g_sludge->_gfxMan->drawVerticalLine((*it)->x1, (*it)->y1, (*it)->y2);
+ g_sludge->_gfxMan->drawVerticalLine((*it)->x2, (*it)->y1, (*it)->y2);
+ g_sludge->_gfxMan->drawHorizontalLine((*it)->x1, (*it)->y1, (*it)->x2);
+ g_sludge->_gfxMan->drawHorizontalLine((*it)->x1, (*it)->y2, (*it)->x2);
+ }
+}
- while (*huntRegion) {
- if ((*huntRegion)->thisType->objectNum == objectNum) {
- killMe = *huntRegion;
- *huntRegion = killMe->next;
+void RegionManager::removeScreenRegion(int objectNum) {
+ for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
+ if ((*it)->thisType->objectNum == objectNum) {
+ ScreenRegion *killMe = *it;
g_sludge->_objMan->removeObjectType(killMe->thisType);
- if (killMe == overRegion)
- overRegion = NULL;
+ if (killMe == _overRegion)
+ _overRegion = nullptr;
delete killMe;
- killMe = NULL;
- } else {
- huntRegion = &((*huntRegion)->next);
+ killMe = nullptr;
+ _allScreenRegions->reverse_erase(it);
}
}
}
-void saveRegions(Common::WriteStream *stream) {
- int numRegions = 0;
- ScreenRegion *thisRegion = allScreenRegions;
- while (thisRegion) {
- thisRegion = thisRegion->next;
- numRegions++;
- }
+void RegionManager::saveRegions(Common::WriteStream *stream) {
+ uint numRegions = _allScreenRegions->size();
stream->writeUint16BE(numRegions);
- thisRegion = allScreenRegions;
- while (thisRegion) {
- stream->writeUint16BE(thisRegion->x1);
- stream->writeUint16BE(thisRegion->y1);
- stream->writeUint16BE(thisRegion->x2);
- stream->writeUint16BE(thisRegion->y2);
- stream->writeUint16BE(thisRegion->sX);
- stream->writeUint16BE(thisRegion->sY);
- stream->writeUint16BE(thisRegion->di);
- g_sludge->_objMan->saveObjectRef(thisRegion->thisType, stream);
-
- thisRegion = thisRegion->next;
+ for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
+ stream->writeUint16BE((*it)->x1);
+ stream->writeUint16BE((*it)->y1);
+ stream->writeUint16BE((*it)->x2);
+ stream->writeUint16BE((*it)->y2);
+ stream->writeUint16BE((*it)->sX);
+ stream->writeUint16BE((*it)->sY);
+ stream->writeUint16BE((*it)->di);
+ g_sludge->_objMan->saveObjectRef((*it)->thisType, stream);
}
}
-void loadRegions(Common::SeekableReadStream *stream) {
+void RegionManager::loadRegions(Common::SeekableReadStream *stream) {
int numRegions = stream->readUint16BE();
-
- ScreenRegion *newRegion;
- ScreenRegion **pointy = &allScreenRegions;
-
while (numRegions--) {
- newRegion = new ScreenRegion;
- *pointy = newRegion;
- pointy = &(newRegion->next);
-
+ ScreenRegion *newRegion = new ScreenRegion;
+ _allScreenRegions->push_back(newRegion);
newRegion->x1 = stream->readUint16BE();
newRegion->y1 = stream->readUint16BE();
newRegion->x2 = stream->readUint16BE();
@@ -111,22 +101,20 @@ void loadRegions(Common::SeekableReadStream *stream) {
newRegion->di = stream->readUint16BE();
newRegion->thisType = g_sludge->_objMan->loadObjectRef(stream);
}
- *pointy = NULL;
}
-void killAllRegions() {
- ScreenRegion *killRegion;
- while (allScreenRegions) {
- killRegion = allScreenRegions;
- allScreenRegions = allScreenRegions->next;
+void RegionManager::kill() {
+ for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
+ ScreenRegion *killRegion = (*it);
g_sludge->_objMan->removeObjectType(killRegion->thisType);
delete killRegion;
}
- overRegion = nullptr;
- lastRegion = nullptr;
+ _allScreenRegions->clear();
+ _overRegion = nullptr;
+ _lastRegion = nullptr;
}
-bool addScreenRegion(int x1, int y1, int x2, int y2, int sX, int sY, int di,
+bool RegionManager::addScreenRegion(int x1, int y1, int x2, int y2, int sX, int sY, int di,
int objectNum) {
ScreenRegion *newRegion = new ScreenRegion;
if (!checkNew(newRegion))
@@ -139,40 +127,51 @@ bool addScreenRegion(int x1, int y1, int x2, int y2, int sX, int sY, int di,
newRegion->sX = sX;
newRegion->sY = sY;
newRegion->thisType = g_sludge->_objMan->loadObjectType(objectNum);
- newRegion->next = allScreenRegions;
- allScreenRegions = newRegion;
- return (bool) (newRegion->thisType != NULL);
+ _allScreenRegions->push_front(newRegion);
+ return (bool) (newRegion->thisType != nullptr);
}
-void getOverRegion() {
+void RegionManager::updateOverRegion() {
int cameraX = g_sludge->_gfxMan->getCamX();
int cameraY = g_sludge->_gfxMan->getCamY();
- ScreenRegion *thisRegion = allScreenRegions;
- while (thisRegion) {
- if ((g_sludge->_evtMan->mouseX() >= thisRegion->x1 - cameraX)
- && (g_sludge->_evtMan->mouseY() >= thisRegion->y1 - cameraY)
- && (g_sludge->_evtMan->mouseX() <= thisRegion->x2 - cameraX)
- && (g_sludge->_evtMan->mouseY() <= thisRegion->y2 - cameraY)) {
- overRegion = thisRegion;
+ for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
+ if ((g_sludge->_evtMan->mouseX() >= (*it)->x1 - cameraX)
+ && (g_sludge->_evtMan->mouseY() >= (*it)->y1 - cameraY)
+ && (g_sludge->_evtMan->mouseX() <= (*it)->x2 - cameraX)
+ && (g_sludge->_evtMan->mouseY() <= (*it)->y2 - cameraY)) {
+ _overRegion = (*it);
return;
}
- thisRegion = thisRegion->next;
}
- overRegion = NULL;
+ _overRegion = nullptr;
return;
}
-ScreenRegion *getRegionForObject(int obj) {
- ScreenRegion *thisRegion = allScreenRegions;
-
- while (thisRegion) {
- if (obj == thisRegion->thisType->objectNum) {
- return thisRegion;
+ScreenRegion *RegionManager::getRegionForObject(int obj) {
+ for (ScreenRegionList::iterator it = _allScreenRegions->begin(); it != _allScreenRegions->end(); ++it) {
+ if (obj == (*it)->thisType->objectNum) {
+ return (*it);
}
- thisRegion = thisRegion->next;
}
- return NULL;
+ return nullptr;
+}
+
+void RegionManager::freeze(FrozenStuffStruct *frozenStuff) {
+ frozenStuff->allScreenRegions = _allScreenRegions;
+ _allScreenRegions = new ScreenRegionList;
+ _overRegion = nullptr;
+}
+
+void RegionManager::resotre(FrozenStuffStruct *frozenStuff) {
+ // kill
+ kill();
+ delete _allScreenRegions;
+ _allScreenRegions = nullptr;
+
+ // restore
+ _allScreenRegions = frozenStuff->allScreenRegions;
+ _overRegion = nullptr;
}
} // End of namespace Sludge
diff --git a/engines/sludge/region.h b/engines/sludge/region.h
index 74294814f6..5f307cc9d0 100644
--- a/engines/sludge/region.h
+++ b/engines/sludge/region.h
@@ -23,24 +23,56 @@
#define SLUDGE_REGION_H
#include "sludge/objtypes.h"
+#include "sludge/freeze.h"
namespace Sludge {
struct ScreenRegion {
int x1, y1, x2, y2, sX, sY, di;
ObjectType *thisType;
- ScreenRegion *next;
};
+typedef Common::List<ScreenRegion *> ScreenRegionList;
-bool addScreenRegion(int x1, int y1, int x2, int y2, int, int, int, int objectNum);
-void getOverRegion();
-ScreenRegion *getRegionForObject(int obj);
-void removeScreenRegion(int objectNum);
-void loadRegions(Common::SeekableReadStream *stream);
-void saveRegions(Common::WriteStream *stream);
-void killAllRegions();
+class RegionManager {
+public:
+ RegionManager(SludgeEngine *vm);
+ ~RegionManager();
-void showBoxes();
+ // Kill
+ void kill();
+
+ // Add & remove region
+ bool addScreenRegion(int x1, int y1, int x2, int y2, int, int, int, int objectNum);
+ void removeScreenRegion(int objectNum);
+
+ // Save & load
+ void loadRegions(Common::SeekableReadStream *stream);
+ void saveRegions(Common::WriteStream *stream);
+
+ // Draw
+ void showBoxes();
+
+ // Setter & getter
+ ScreenRegion *getRegionForObject(int obj);
+ ScreenRegion *getOverRegion() const { return _overRegion; }
+ void setOverRegion(ScreenRegion *newRegion) { _overRegion = newRegion; }
+ void updateOverRegion();
+ bool isRegionChanged() const { return _lastRegion != _overRegion; }
+ void updateLastRegion() { _lastRegion = _overRegion; }
+ void resetOverRegion() { _overRegion = nullptr; }
+ void resetLastRegion() { _lastRegion = nullptr; }
+
+ // Freeze
+ void freeze(FrozenStuffStruct *frozenStuff);
+ void resotre(FrozenStuffStruct *frozenStuff);
+
+private:
+ SludgeEngine *_vm;
+
+ ScreenRegionList *_allScreenRegions;
+ ScreenRegion *_overRegion;
+ ScreenRegion *_lastRegion;
+};
} // End of namespace Sludge
diff --git a/engines/sludge/savedata.cpp b/engines/sludge/savedata.cpp
index 9e2c92395d..b103523f8c 100644
--- a/engines/sludge/savedata.cpp
+++ b/engines/sludge/savedata.cpp
@@ -20,44 +20,45 @@
*
*/
-#include "common/file.h"
+#include "common/savefile.h"
#include "sludge/allfiles.h"
#include "sludge/moreio.h"
#include "sludge/newfatal.h"
+#include "sludge/savedata.h"
#include "sludge/variable.h"
#define LOAD_ERROR "Can't load custom data...\n\n"
namespace Sludge {
-const char UTF8_CHECKER[] = {'U', 'N', '\xef', '\xbf', '\xbd', 'L', 'O', '\xef', '\xbf', '\xbd', 'C', 'K', 'E', 'D', '\0'};
-uint16 saveEncoding = false;
-char encode1 = 0;
-char encode2 = 0;
+const char CustomSaveHelper::UTF8_CHECKER[] = {'U', 'N', '\xef', '\xbf', '\xbd', 'L', 'O', '\xef', '\xbf', '\xbd', 'C', 'K', 'E', 'D', '\0'};
+uint16 CustomSaveHelper::_saveEncoding = false;
+char CustomSaveHelper::_encode1 = 0;
+char CustomSaveHelper::_encode2 = 0;
-void writeStringEncoded(const Common::String &s, Common::WriteStream *stream) {
- int len = s.size();
+void CustomSaveHelper::writeStringEncoded(const Common::String checker, Common::WriteStream *stream) {
+ int len = checker.size();
stream->writeUint16BE(len);
for (int a = 0; a < len; a++) {
- stream->writeByte(s[a] ^ encode1);
- encode1 += encode2;
+ stream->writeByte(checker[a] ^ _encode1);
+ _encode1 += _encode2;
}
}
-Common::String readStringEncoded(Common::File *fp) {
+Common::String CustomSaveHelper::readStringEncoded(Common::SeekableReadStream *fp) {
int len = fp->readUint16BE();
Common::String res = "";
for (int a = 0; a < len; a++) {
- res += (char)(fp->readByte() ^ encode1);
- encode1 += encode2;
+ res += (char)(fp->readByte() ^ _encode1);
+ _encode1 += _encode2;
}
return res;
}
-char *readTextPlain(Common::File *fp) {
+char *CustomSaveHelper::readTextPlain(Common::SeekableReadStream *fp) {
int32 startPos;
uint32 stringSize = 0;
@@ -94,86 +95,66 @@ char *readTextPlain(Common::File *fp) {
return reply;
}
-bool fileToStack(const Common::String &filename, StackHandler *sH) {
-
+bool CustomSaveHelper::fileToStack(const Common::String &filename, StackHandler *sH) {
Variable stringVar;
stringVar.varType = SVT_NULL;
- Common::String checker = saveEncoding ? "[Custom data (encoded)]\r\n" : "[Custom data (ASCII)]\n";
-
- Common::File fd;
-
- if (!fd.open(filename)) {
-#if 0
- char currentDir[1000];
- if (!getcwd(currentDir, 998)) {
- debugOut("Can't get current directory.\n");
- }
-
- if (chdir(gamePath)) {
- debugOut("Error: Failed changing to directory %s\n", gamePath);
- }
+ Common::String checker = _saveEncoding ? "[Custom data (encoded)]\r\n" : "[Custom data (ASCII)]\n";
- if (chdir(currentDir)) {
- debugOut("Error: Failed changing to directory %s\n", currentDir);
- }
+ Common::InSaveFile *fp = g_system->getSavefileManager()->openForLoading(filename);
- if (!fd.open(filename)) {
- return fatal("No such file", filename);
- }
-#endif
+ if (fp == NULL) {
return fatal("No such file", filename); //TODO: false value
}
- encode1 = (byte)saveEncoding & 255;
- encode2 = (byte)(saveEncoding >> 8);
+ _encode1 = (byte)_saveEncoding & 255;
+ _encode2 = (byte)(_saveEncoding >> 8);
for (uint i = 0; i < checker.size(); ++i) {
- if (fd.readByte() != checker[i]) {
- fd.close();
+ if (fp->readByte() != checker[i]) {
+ delete fp;
return fatal(LOAD_ERROR "This isn't a SLUDGE custom data file:", filename);
}
}
- if (saveEncoding) {
- checker = readStringEncoded(&fd);
+ if (_saveEncoding) {
+ checker = readStringEncoded(fp);
if (checker == UTF8_CHECKER) {
- fd.close();
- return fatal(
- LOAD_ERROR "The current file encoding setting does not match the encoding setting used when this file was created:", filename);
+ delete fp;
+ return fatal(LOAD_ERROR "The current file encoding setting does not match the encoding setting used when this file was created:", filename);
}
}
for (;;) {
- if (saveEncoding) {
- char i = fd.readByte() ^ encode1;
+ if (_saveEncoding) {
+ char i = fp->readByte() ^ _encode1;
- if (fd.eos())
+ if (fp->eos())
break;
switch (i) {
case 0: {
- Common::String g = readStringEncoded(&fd);
- makeTextVar(stringVar, g);
+ Common::String g = readStringEncoded(fp);
+ stringVar.makeTextVar(g);
}
break;
case 1:
- setVariable(stringVar, SVT_INT, fd.readUint32LE());
+ stringVar.setVariable(SVT_INT, fp->readUint32LE());
break;
case 2:
- setVariable(stringVar, SVT_INT, fd.readByte());
+ stringVar.setVariable(SVT_INT, fp->readByte());
break;
default:
fatal(LOAD_ERROR "Corrupt custom data file:", filename);
- fd.close();
+ delete fp;
return false;
}
} else {
- char *line = readTextPlain(&fd);
+ char *line = readTextPlain(fp);
if (!line)
break;
- makeTextVar(stringVar, line);
+ stringVar.makeTextVar(line);
}
if (sH->first == NULL) {
@@ -188,63 +169,66 @@ bool fileToStack(const Common::String &filename, StackHandler *sH) {
sH->last = sH->last->next;
}
}
- fd.close();
+
+ delete fp;
return true;
}
-bool stackToFile(const Common::String &filename, const Variable &from) {
-#if 0
- FILE *fp = fopen(filename, saveEncoding ? "wb" : "wt");
- if (!fp) return fatal("Can't create file", filename);
+bool CustomSaveHelper::stackToFile(const Common::String &filename, const Variable &from) {
+ Common::OutSaveFile *fp = g_system->getSavefileManager()->openForSaving(filename);
+ if (fp == NULL) {
+ return fatal("Can't create file", filename);
+ }
VariableStack *hereWeAre = from.varData.theStack -> first;
- encode1 = (byte)saveEncoding & 255;
- encode2 = (byte)(saveEncoding >> 8);
+ _encode1 = (byte)_saveEncoding & 255;
+ _encode2 = (byte)(_saveEncoding >> 8);
- if (saveEncoding) {
- fprintf(fp, "[Custom data (encoded)]\r\n");
+ if (_saveEncoding) {
+ fp->writeString("[Custom data (encoded)]\r\n");
writeStringEncoded(UTF8_CHECKER, fp);
} else {
- fprintf(fp, "[Custom data (ASCII)]\n");
+ fp->writeString("[Custom data (ASCII)]\n");
}
while (hereWeAre) {
- if (saveEncoding) {
+ if (_saveEncoding) {
switch (hereWeAre -> thisVar.varType) {
case SVT_STRING:
- fputc(encode1, fp);
- writeStringEncoded(hereWeAre -> thisVar.varData.theString, fp);
- break;
+ fp->writeByte(_encode1);
+ writeStringEncoded(hereWeAre -> thisVar.varData.theString, fp);
+ break;
case SVT_INT:
- // Small enough to be stored as a char
- if (hereWeAre -> thisVar.varData.intValue >= 0 && hereWeAre -> thisVar.varData.intValue < 256) {
- fputc(2 ^ encode1, fp);
- fputc(hereWeAre -> thisVar.varData.intValue, fp);
- } else {
- fputc(1 ^ encode1, fp);
- fp->writeUint32LE(hereWeAre -> thisVar.varData.intValue);
- }
- break;
+ // Small enough to be stored as a char
+ if (hereWeAre -> thisVar.varData.intValue >= 0 && hereWeAre -> thisVar.varData.intValue < 256) {
+ fp->writeByte(2 ^ _encode1);
+ fp->writeByte(hereWeAre -> thisVar.varData.intValue);
+ } else {
+ fp->writeByte(1 ^ _encode1);
+ fp->writeUint32LE(hereWeAre -> thisVar.varData.intValue);
+ }
+ break;
default:
- fatal("Can't create an encoded custom data file containing anything other than numbers and strings", filename);
- fclose(fp);
- return false;
+ fatal("Can't create an encoded custom data file containing anything other than numbers and strings", filename);
+ delete fp;
+ return false;
}
} else {
- char *makeSureItsText = getTextFromAnyVar(hereWeAre -> thisVar);
- if (makeSureItsText == NULL) break;
- fprintf(fp, "%s\n", makeSureItsText);
- delete makeSureItsText;
+ Common::String makeSureItsText = hereWeAre->thisVar.getTextFromAnyVar();
+ if (makeSureItsText.empty())
+ break;
+ fp->writeString((makeSureItsText + "\n").c_str());
}
hereWeAre = hereWeAre -> next;
}
- fclose(fp);
-#endif
+
+ delete fp;
+
return true;
}
diff --git a/engines/sludge/savedata.h b/engines/sludge/savedata.h
index 956df93f35..90b093f4ff 100644
--- a/engines/sludge/savedata.h
+++ b/engines/sludge/savedata.h
@@ -24,8 +24,26 @@
namespace Sludge {
-bool fileToStack(const Common::String &filename, StackHandler *sH);
-bool stackToFile(const Common::String &filename, const Variable &from);
+struct StackHandler;
+struct Variable;
+
+class CustomSaveHelper {
+public:
+ static bool fileToStack(const Common::String &filename, StackHandler *sH);
+ static bool stackToFile(const Common::String &filename, const Variable &from);
+
+ static uint16 _saveEncoding;
+
+private:
+ static const char UTF8_CHECKER[];
+ static char _encode1;
+ static char _encode2;
+
+ static void writeStringEncoded(const Common::String checker, Common::WriteStream *stream);
+ static Common::String readStringEncoded(Common::SeekableReadStream *fp);
+ static char *readTextPlain(Common::SeekableReadStream *fp);
+
+};
} // End of namespace Sludge
diff --git a/engines/sludge/sludge.cpp b/engines/sludge/sludge.cpp
index d14f92202f..821539d877 100644
--- a/engines/sludge/sludge.cpp
+++ b/engines/sludge/sludge.cpp
@@ -28,11 +28,15 @@
#include "sludge/cursors.h"
#include "sludge/event.h"
#include "sludge/fonttext.h"
+#include "sludge/floor.h"
#include "sludge/graphics.h"
+#include "sludge/main_loop.h"
+#include "sludge/newfatal.h"
+#include "sludge/people.h"
+#include "sludge/region.h"
#include "sludge/sludge.h"
#include "sludge/sound.h"
#include "sludge/speech.h"
-#include "sludge/main_loop.h"
namespace Sludge {
@@ -68,11 +72,10 @@ SludgeEngine::SludgeEngine(OSystem *syst, const SludgeGameDescription *gameDesc)
launchNext = "";
loadNow = "";
gamePath = "";
- bundleFolder = "";
- fatalMessage = "";
- fatalInfo = "Initialisation error! Something went wrong before we even got started!";
// Init managers
+ _fatalMan = new FatalMsgManager();
+ _peopleMan = new PeopleManager(this);
_resMan = new ResourceManager();
_languageMan = new LanguageManager();
_objMan = new ObjectManager(this);
@@ -82,6 +85,8 @@ SludgeEngine::SludgeEngine(OSystem *syst, const SludgeGameDescription *gameDesc)
_txtMan = new TextManager();
_cursorMan = new CursorManager(this);
_speechMan = new SpeechManager(this);
+ _regionMan = new RegionManager(this);
+ _floorMan = new FloorManager(this);
}
SludgeEngine::~SludgeEngine() {
@@ -122,6 +127,14 @@ SludgeEngine::~SludgeEngine() {
_resMan = nullptr;
delete _speechMan;
_speechMan = nullptr;
+ delete _regionMan;
+ _regionMan = nullptr;
+ delete _peopleMan;
+ _peopleMan = nullptr;
+ delete _floorMan;
+ _floorMan = nullptr;
+ delete _fatalMan;
+ _fatalMan = nullptr;
}
Common::Error SludgeEngine::run() {
diff --git a/engines/sludge/sludge.h b/engines/sludge/sludge.h
index 83c6359f52..692af64071 100644
--- a/engines/sludge/sludge.h
+++ b/engines/sludge/sludge.h
@@ -40,7 +40,11 @@ extern SludgeEngine *g_sludge;
class CursorManager;
class EventManager;
+class FatalMsgManager;
+class FloorManager;
class GraphicsManager;
+class PeopleManager;
+class RegionManager;
class SoundManager;
class SpeechManager;
class TextManager;
@@ -71,9 +75,6 @@ public:
Common::String launchNext;
Common::String loadNow;
Common::String gamePath;
- Common::String bundleFolder;
- Common::String fatalMessage;
- Common::String fatalInfo;
// timer
Timer _timer;
@@ -88,6 +89,10 @@ public:
TextManager *_txtMan;
CursorManager *_cursorMan;
SpeechManager *_speechMan;
+ RegionManager *_regionMan;
+ PeopleManager *_peopleMan;
+ FloorManager *_floorMan;
+ FatalMsgManager *_fatalMan;
SludgeEngine(OSystem *syst, const SludgeGameDescription *gameDesc);
virtual ~SludgeEngine();
diff --git a/engines/sludge/sludger.cpp b/engines/sludge/sludger.cpp
index 812f42fb5d..f9dedf22fc 100644
--- a/engines/sludge/sludger.cpp
+++ b/engines/sludge/sludger.cpp
@@ -32,69 +32,46 @@
#include "sludge/freeze.h"
#include "sludge/floor.h"
#include "sludge/fileset.h"
+#include "sludge/function.h"
#include "sludge/graphics.h"
#include "sludge/imgloader.h"
-#include "sludge/loadsave.h"
#include "sludge/language.h"
#include "sludge/moreio.h"
#include "sludge/newfatal.h"
#include "sludge/objtypes.h"
#include "sludge/people.h"
#include "sludge/region.h"
-#include "sludge/statusba.h"
-#include "sludge/sprites.h"
-#include "sludge/sprbanks.h"
-#include "sludge/sound.h"
+#include "sludge/savedata.h"
#include "sludge/sludge.h"
#include "sludge/sludger.h"
+#include "sludge/sound.h"
#include "sludge/speech.h"
-#include "sludge/transition.h"
+#include "sludge/sprites.h"
+#include "sludge/sprbanks.h"
+#include "sludge/statusba.h"
#include "sludge/variable.h"
#include "sludge/version.h"
#include "sludge/zbuffer.h"
namespace Sludge {
-extern int dialogValue;
+extern int numBIFNames;
+extern Common::String *allBIFNames;
+extern int numUserFunc;
+extern Common::String *allUserFunc;
-int numBIFNames = 0;
-Common::String *allBIFNames;
-int numUserFunc = 0;
-Common::String *allUserFunc = NULL;
-int numResourceNames = 0;
-Common::String *allResourceNames = NULL;
int selectedLanguage = 0;
int gameVersion;
FILETIME fileTime;
-bool captureAllKeys = false;
-
-byte brightnessLevel = 255;
-
-extern LoadedFunction *saverFunc;
-
-LoadedFunction *allRunningFunctions = NULL;
-VariableStack *noStack = NULL;
-Variable *globalVars;
int numGlobals = 0;
-extern SpritePalette pastePalette;
extern Variable *launchResult;
-extern int lastFramesPerSecond, thumbWidth, thumbHeight;
+extern Variable *globalVars;
+extern VariableStack *noStack;
extern bool allowAnyFilename;
-extern byte fadeMode;
-extern uint16 saveEncoding;
-
-const char *sludgeText[] = { "?????", "RETURN", "BRANCH", "BR_ZERO",
- "SET_GLOBAL", "SET_LOCAL", "LOAD_GLOBAL", "LOAD_LOCAL", "PLUS", "MINUS",
- "MULT", "DIVIDE", "AND", "OR", "EQUALS", "NOT_EQ", "MODULUS",
- "LOAD_VALUE", "LOAD_BUILT", "LOAD_FUNC", "CALLIT", "LOAD_STRING",
- "LOAD_FILE", "LOAD_OBJTYPE", "NOT", "LOAD_NULL", "STACK_PUSH",
- "LESSTHAN", "MORETHAN", "NEGATIVE", "U", "LESS_EQUAL", "MORE_EQUAL",
- "INC_LOCAL", "DEC_LOCAL", "INC_GLOBAL", "DEC_GLOBAL", "INDEXSET",
- "INDEXGET", "INC_INDEX", "DEC_INDEX", "QUICK_PUSH" };
Common::File *openAndVerify(const Common::String &filename, char extra1, char extra2,
const char *er, int &fileVersion) {
@@ -146,15 +123,15 @@ Common::File *openAndVerify(const Common::String &filename, char extra1, char ex
}
void initSludge() {
+ g_sludge->_timer.reset();
g_sludge->_languageMan->init();
g_sludge->_gfxMan->init();
g_sludge->_resMan->init();
- initPeople();
- initFloor();
+ g_sludge->_peopleMan->init();
+ g_sludge->_floorMan->init();
g_sludge->_objMan->init();
g_sludge->_speechMan->init();
initStatusBar();
- resetRandW();
g_sludge->_evtMan->init();
g_sludge->_txtMan->init();
g_sludge->_cursorMan->init();
@@ -164,27 +141,23 @@ void initSludge() {
g_sludge->_soundMan->initSoundStuff();
}
+ CustomSaveHelper::_saveEncoding = false;
+
// global variables
numGlobals = 0;
launchResult = nullptr;
- lastFramesPerSecond = -1;
- thumbWidth = thumbHeight = 0;
allowAnyFilename = true;
- captureAllKeys = false;
noStack = nullptr;
numBIFNames = numUserFunc = 0;
allUserFunc = allBIFNames = nullptr;
- brightnessLevel = 255;
- fadeMode = 2;
- saveEncoding = false;
}
void killSludge() {
killAllFunctions();
- killAllPeople();
- killAllRegions();
- setFloorNull();
+ g_sludge->_peopleMan->kill();
+ g_sludge->_regionMan->kill();
+ g_sludge->_floorMan->kill();
g_sludge->_speechMan->kill();
g_sludge->_languageMan->kill();
g_sludge->_gfxMan->kill();
@@ -196,7 +169,6 @@ void killSludge() {
g_sludge->_cursorMan->kill();
// global variables
- pastePalette.reset();
numBIFNames = numUserFunc = 0;
delete []allUserFunc;
delete []allBIFNames;
@@ -205,7 +177,6 @@ void killSludge() {
bool initSludge(const Common::String &filename) {
initSludge();
- int a = 0;
Common::File *fp = openAndVerify(filename, 'G', 'E', ERROR_BAD_HEADER, gameVersion);
if (!fp)
return false;
@@ -232,19 +203,9 @@ bool initSludge(const Common::String &filename) {
allUserFunc[fn].clear();
allUserFunc[fn] = readString(fp);
}
- if (gameVersion >= VERSION(1, 3)) {
- numResourceNames = fp->readUint16BE();
- debugC(2, kSludgeDebugDataLoad, "numResourceNames %i",
- numResourceNames);
- allResourceNames = new Common::String[numResourceNames];
- if (!checkNew(allResourceNames))
- return false;
- for (int fn = 0; fn < numResourceNames; fn++) {
- allResourceNames[fn].clear();
- allResourceNames[fn] = readString(fp);
- debugC(2, kSludgeDebugDataLoad, "Resource %i: %s", fn, allResourceNames[fn].c_str());
- }
+ if (gameVersion >= VERSION(1, 3)) {
+ g_sludge->_resMan->readResourceNames(fp);
}
}
@@ -256,7 +217,7 @@ bool initSludge(const Common::String &filename) {
int specialSettings = fp->readByte();
debugC(2, kSludgeDebugDataLoad, "specialSettings : %i", specialSettings);
- g_sludge->_timer.setDesiredfps(1000 / fp->readByte());
+ g_sludge->_timer.setDesiredFPS(1000 / fp->readByte());
readString(fp); // Unused - was used for registration purposes.
@@ -314,8 +275,6 @@ bool initSludge(const Common::String &filename) {
globalVars = new Variable[numGlobals];
if (!checkNew(globalVars))
return false;
- for (a = 0; a < numGlobals; a++)
- initVarNew(globalVars[a]);
// Get language selected by user
g_sludge->_resMan->setData(fp);
@@ -334,7 +293,7 @@ void displayBase() {
g_sludge->_gfxMan->clear(); // Clear screen
g_sludge->_gfxMan->drawBackDrop();// Draw Backdrop
g_sludge->_gfxMan->drawZBuffer(g_sludge->_gfxMan->getCamX(), g_sludge->_gfxMan->getCamY(), false);
- drawPeople();// Then add any moving characters...
+ g_sludge->_peopleMan->drawPeople();// Then add any moving characters...
g_sludge->_gfxMan->displaySpriteLayers();
}
@@ -344,712 +303,6 @@ void sludgeDisplay() {
drawStatusBar();
g_sludge->_cursorMan->displayCursor();
g_sludge->_gfxMan->display();
- if (brightnessLevel < 255) fixBrightness();// This is for transitionLevel special effects
-}
-
-void pauseFunction(LoadedFunction *fun) {
- LoadedFunction **huntAndDestroy = &allRunningFunctions;
- while (*huntAndDestroy) {
- if (fun == *huntAndDestroy) {
- (*huntAndDestroy) = (*huntAndDestroy)->next;
- fun->next = NULL;
- } else {
- huntAndDestroy = &(*huntAndDestroy)->next;
- }
- }
-}
-
-void restartFunction(LoadedFunction *fun) {
- fun->next = allRunningFunctions;
- allRunningFunctions = fun;
-}
-
-void killSpeechTimers() {
- LoadedFunction *thisFunction = allRunningFunctions;
-
- while (thisFunction) {
- if (thisFunction->freezerLevel == 0 && thisFunction->isSpeech
- && thisFunction->timeLeft) {
- thisFunction->timeLeft = 0;
- thisFunction->isSpeech = false;
- }
- thisFunction = thisFunction->next;
- }
-
- g_sludge->_speechMan->kill();
-}
-
-void completeTimers() {
- LoadedFunction *thisFunction = allRunningFunctions;
-
- while (thisFunction) {
- if (thisFunction->freezerLevel == 0)
- thisFunction->timeLeft = 0;
- thisFunction = thisFunction->next;
- }
-}
-
-void finishFunction(LoadedFunction *fun) {
- int a;
-
- pauseFunction(fun);
- if (fun->stack)
- fatal(ERROR_NON_EMPTY_STACK);
- delete[] fun->compiledLines;
- for (a = 0; a < fun->numLocals; a++)
- unlinkVar(fun->localVars[a]);
- delete[] fun->localVars;
- unlinkVar(fun->reg);
- delete fun;
- fun = NULL;
-}
-
-void abortFunction(LoadedFunction *fun) {
- int a;
-
- pauseFunction(fun);
- while (fun->stack)
- trimStack(fun->stack);
- delete []fun->compiledLines;
- for (a = 0; a < fun->numLocals; a++)
- unlinkVar(fun->localVars[a]);
- delete []fun->localVars;
- unlinkVar(fun->reg);
- if (fun->calledBy)
- abortFunction(fun->calledBy);
- delete fun;
- fun = NULL;
-}
-
-int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself) {
- int n = 0;
- killedMyself = false;
-
- LoadedFunction *fun = allRunningFunctions;
- while (fun) {
- if (fun->originalNumber == funcNum) {
- fun->cancelMe = true;
- n++;
- if (fun == myself)
- killedMyself = true;
- }
- fun = fun->next;
- }
- return n;
}
-void freezeSubs() {
- LoadedFunction *thisFunction = allRunningFunctions;
-
- while (thisFunction) {
- if (thisFunction->unfreezable) {
- //msgBox ("SLUDGE debugging bollocks!", "Trying to freeze an unfreezable function!");
- } else {
- thisFunction->freezerLevel++;
- }
- thisFunction = thisFunction->next;
- }
-}
-
-void unfreezeSubs() {
- LoadedFunction *thisFunction = allRunningFunctions;
-
- while (thisFunction) {
- if (thisFunction->freezerLevel)
- thisFunction->freezerLevel--;
- thisFunction = thisFunction->next;
- }
-}
-
-bool continueFunction(LoadedFunction *fun) {
- bool keepLooping = true;
- bool advanceNow;
- uint param;
- sludgeCommand com;
-
- if (fun->cancelMe) {
- abortFunction(fun);
- return true;
- }
-
- while (keepLooping) {
- advanceNow = true;
- debugC(1, kSludgeDebugStackMachine, "Executing command line %i : ", fun->runThisLine);
- param = fun->compiledLines[fun->runThisLine].param;
- com = fun->compiledLines[fun->runThisLine].theCommand;
-
- if (numBIFNames) {
- setFatalInfo((fun->originalNumber < numUserFunc) ? allUserFunc[fun->originalNumber] : "Unknown user function", (com < numSludgeCommands) ? sludgeText[com] : ERROR_UNKNOWN_MCODE);
- }
-
- switch (com) {
- case SLU_RETURN:
- if (fun->calledBy) {
- LoadedFunction *returnTo = fun->calledBy;
- if (fun->returnSomething)
- copyVariable(fun->reg, returnTo->reg);
- finishFunction(fun);
- fun = returnTo;
- restartFunction(fun);
- } else {
- finishFunction(fun);
- advanceNow = false; // So we don't do anything else with "fun"
- keepLooping = false; // So we drop out of the loop
- }
- break;
-
- case SLU_CALLIT:
- switch (fun->reg.varType) {
- case SVT_FUNC:
- pauseFunction(fun);
- if (numBIFNames)
- setFatalInfo(
- (fun->originalNumber < numUserFunc) ?
- allUserFunc[fun->originalNumber] :
- "Unknown user function",
- (fun->reg.varData.intValue < numUserFunc) ?
- allUserFunc[fun->reg.varData.intValue] :
- "Unknown user function");
-
- if (!startNewFunctionNum(fun->reg.varData.intValue, param, fun,
- fun->stack))
- return false;
- fun = allRunningFunctions;
- advanceNow = false; // So we don't do anything else with "fun"
- break;
-
- case SVT_BUILT: {
- debugC(1, kSludgeDebugStackMachine, "Built-in init value: %i",
- fun->reg.varData.intValue);
- BuiltReturn br = callBuiltIn(fun->reg.varData.intValue, param,
- fun);
-
- switch (br) {
- case BR_ERROR:
- return fatal(
- "Unknown error. This shouldn't happen. Please notify the SLUDGE developers.");
-
- case BR_PAUSE:
- pauseFunction(fun);
- // fall through
-
- case BR_KEEP_AND_PAUSE:
- keepLooping = false;
- break;
-
- case BR_ALREADY_GONE:
- keepLooping = false;
- advanceNow = false;
- break;
-
- case BR_CALLAFUNC: {
- int i = fun->reg.varData.intValue;
- setVariable(fun->reg, SVT_INT, 1);
- pauseFunction(fun);
- if (numBIFNames)
- setFatalInfo(
- (fun->originalNumber < numUserFunc) ?
- allUserFunc[fun->originalNumber] :
- "Unknown user function",
- (i < numUserFunc) ?
- allUserFunc[i] :
- "Unknown user function");
- if (!startNewFunctionNum(i, 0, fun, noStack, false))
- return false;
- fun = allRunningFunctions;
- advanceNow = false; // So we don't do anything else with "fun"
- }
- break;
-
- default:
- break;
- }
- }
- break;
-
- default:
- return fatal(ERROR_CALL_NONFUNCTION);
- }
- break;
-
- // These all grab things and shove 'em into the register
-
- case SLU_LOAD_NULL:
- setVariable(fun->reg, SVT_NULL, 0);
- break;
-
- case SLU_LOAD_FILE:
- setVariable(fun->reg, SVT_FILE, param);
- break;
-
- case SLU_LOAD_VALUE:
- setVariable(fun->reg, SVT_INT, param);
- break;
-
- case SLU_LOAD_LOCAL:
- if (!copyVariable(fun->localVars[param], fun->reg))
- return false;
- break;
-
- case SLU_AND:
- setVariable(fun->reg, SVT_INT,
- getBoolean(fun->reg) && getBoolean(fun->stack->thisVar));
- trimStack(fun->stack);
- break;
-
- case SLU_OR:
- setVariable(fun->reg, SVT_INT,
- getBoolean(fun->reg) || getBoolean(fun->stack->thisVar));
- trimStack(fun->stack);
- break;
-
- case SLU_LOAD_FUNC:
- setVariable(fun->reg, SVT_FUNC, param);
- break;
-
- case SLU_LOAD_BUILT:
- setVariable(fun->reg, SVT_BUILT, param);
- break;
-
- case SLU_LOAD_OBJTYPE:
- setVariable(fun->reg, SVT_OBJTYPE, param);
- break;
-
- case SLU_UNREG:
- if (dialogValue != 1)
- fatal(ERROR_HACKER);
- break;
-
- case SLU_LOAD_STRING:
- if (!loadStringToVar(fun->reg, param)) {
- return false;
- }
- break;
-
- case SLU_INDEXGET:
- case SLU_INCREMENT_INDEX:
- case SLU_DECREMENT_INDEX:
- switch (fun->stack->thisVar.varType) {
- case SVT_NULL:
- if (com == SLU_INDEXGET) {
- setVariable(fun->reg, SVT_NULL, 0);
- trimStack(fun->stack);
- } else {
- return fatal(ERROR_INCDEC_UNKNOWN);
- }
- break;
-
- case SVT_FASTARRAY:
- case SVT_STACK:
- if (fun->stack->thisVar.varData.theStack->first == NULL) {
- return fatal(ERROR_INDEX_EMPTY);
- } else {
- int ii;
- if (!getValueType(ii, SVT_INT, fun->reg))
- return false;
- Variable *grab =
- (fun->stack->thisVar.varType == SVT_FASTARRAY) ?
- fastArrayGetByIndex(
- fun->stack->thisVar.varData.fastArray,
- ii) :
- stackGetByIndex(
- fun->stack->thisVar.varData.theStack->first,
- ii);
-
- trimStack(fun->stack);
-
- if (!grab) {
- setVariable(fun->reg, SVT_NULL, 0);
- } else {
- int kk;
- switch (com) {
- case SLU_INCREMENT_INDEX:
- if (!getValueType(kk, SVT_INT, *grab))
- return false;
- setVariable(fun->reg, SVT_INT, kk);
- grab->varData.intValue = kk + 1;
- break;
-
- case SLU_DECREMENT_INDEX:
- if (!getValueType(kk, SVT_INT, *grab))
- return false;
- setVariable(fun->reg, SVT_INT, kk);
- grab->varData.intValue = kk - 1;
- break;
-
- default:
- if (!copyVariable(*grab, fun->reg))
- return false;
- }
- }
- }
- break;
-
- default:
- return fatal(ERROR_INDEX_NONSTACK);
- }
- break;
-
- case SLU_INDEXSET:
- switch (fun->stack->thisVar.varType) {
- case SVT_STACK:
- if (fun->stack->thisVar.varData.theStack->first == NULL) {
- return fatal(ERROR_INDEX_EMPTY);
- } else {
- int ii;
- if (!getValueType(ii, SVT_INT, fun->reg))
- return false;
- if (!stackSetByIndex(
- fun->stack->thisVar.varData.theStack->first, ii,
- fun->stack->next->thisVar)) {
- return false;
- }
- trimStack(fun->stack);
- trimStack(fun->stack);
- }
- break;
-
- case SVT_FASTARRAY: {
- int ii;
- if (!getValueType(ii, SVT_INT, fun->reg))
- return false;
- Variable *v = fastArrayGetByIndex(
- fun->stack->thisVar.varData.fastArray, ii);
- if (v == NULL)
- return fatal("Not within bounds of fast array.");
- if (!copyVariable(fun->stack->next->thisVar, *v))
- return false;
- trimStack(fun->stack);
- trimStack(fun->stack);
- }
- break;
-
- default:
- return fatal(ERROR_INDEX_NONSTACK);
- }
- break;
-
- // What can we do with the register? Well, we can copy it into a local
- // variable, a global or onto the stack...
-
- case SLU_INCREMENT_LOCAL: {
- int ii;
- if (!getValueType(ii, SVT_INT, fun->localVars[param]))
- return false;
- setVariable(fun->reg, SVT_INT, ii);
- setVariable(fun->localVars[param], SVT_INT, ii + 1);
- }
- break;
-
- case SLU_INCREMENT_GLOBAL: {
- int ii;
- if (!getValueType(ii, SVT_INT, globalVars[param]))
- return false;
- setVariable(fun->reg, SVT_INT, ii);
- setVariable(globalVars[param], SVT_INT, ii + 1);
- }
- break;
-
- case SLU_DECREMENT_LOCAL: {
- int ii;
- if (!getValueType(ii, SVT_INT, fun->localVars[param]))
- return false;
- setVariable(fun->reg, SVT_INT, ii);
- setVariable(fun->localVars[param], SVT_INT, ii - 1);
- }
- break;
-
- case SLU_DECREMENT_GLOBAL: {
- int ii;
- if (!getValueType(ii, SVT_INT, globalVars[param]))
- return false;
- setVariable(fun->reg, SVT_INT, ii);
- setVariable(globalVars[param], SVT_INT, ii - 1);
- }
- break;
-
- case SLU_SET_LOCAL:
- if (!copyVariable(fun->reg, fun->localVars[param]))
- return false;
- break;
-
- case SLU_SET_GLOBAL:
-// newDebug (" Copying TO global variable", param);
-// newDebug (" Global type at the moment", globalVars[param].varType);
- if (!copyVariable(fun->reg, globalVars[param]))
- return false;
-// newDebug (" New type", globalVars[param].varType);
- break;
-
- case SLU_LOAD_GLOBAL:
-// newDebug (" Copying FROM global variable", param);
-// newDebug (" Global type at the moment", globalVars[param].varType);
- if (!copyVariable(globalVars[param], fun->reg))
- return false;
- break;
-
- case SLU_STACK_PUSH:
- if (!addVarToStack(fun->reg, fun->stack))
- return false;
- break;
-
- case SLU_QUICK_PUSH:
- if (!addVarToStackQuick(fun->reg, fun->stack))
- return false;
- break;
-
- case SLU_NOT:
- setVariable(fun->reg, SVT_INT, !getBoolean(fun->reg));
- break;
-
- case SLU_BR_ZERO:
- if (!getBoolean(fun->reg)) {
- advanceNow = false;
- fun->runThisLine = param;
- }
- break;
-
- case SLU_BRANCH:
- advanceNow = false;
- fun->runThisLine = param;
- break;
-
- case SLU_NEGATIVE: {
- int i;
- if (!getValueType(i, SVT_INT, fun->reg))
- return false;
- setVariable(fun->reg, SVT_INT, -i);
- }
- break;
-
- // All these things rely on there being somet' on the stack
-
- case SLU_MULT:
- case SLU_PLUS:
- case SLU_MINUS:
- case SLU_MODULUS:
- case SLU_DIVIDE:
- case SLU_EQUALS:
- case SLU_NOT_EQ:
- case SLU_LESSTHAN:
- case SLU_MORETHAN:
- case SLU_LESS_EQUAL:
- case SLU_MORE_EQUAL:
- if (fun->stack) {
- int firstValue, secondValue;
-
- switch (com) {
- case SLU_PLUS:
- addVariablesInSecond(fun->stack->thisVar, fun->reg);
- trimStack(fun->stack);
- break;
-
- case SLU_EQUALS:
- compareVariablesInSecond(fun->stack->thisVar, fun->reg);
- trimStack(fun->stack);
- break;
-
- case SLU_NOT_EQ:
- compareVariablesInSecond(fun->stack->thisVar, fun->reg);
- trimStack(fun->stack);
- fun->reg.varData.intValue = !fun->reg.varData.intValue;
- break;
-
- default:
- if (!getValueType(firstValue, SVT_INT, fun->stack->thisVar))
- return false;
- if (!getValueType(secondValue, SVT_INT, fun->reg))
- return false;
- trimStack(fun->stack);
-
- switch (com) {
- case SLU_MULT:
- setVariable(fun->reg, SVT_INT,
- firstValue * secondValue);
- break;
-
- case SLU_MINUS:
- setVariable(fun->reg, SVT_INT,
- firstValue - secondValue);
- break;
-
- case SLU_MODULUS:
- setVariable(fun->reg, SVT_INT,
- firstValue % secondValue);
- break;
-
- case SLU_DIVIDE:
- setVariable(fun->reg, SVT_INT,
- firstValue / secondValue);
- break;
-
- case SLU_LESSTHAN:
- setVariable(fun->reg, SVT_INT,
- firstValue < secondValue);
- break;
-
- case SLU_MORETHAN:
- setVariable(fun->reg, SVT_INT,
- firstValue > secondValue);
- break;
-
- case SLU_LESS_EQUAL:
- setVariable(fun->reg, SVT_INT,
- firstValue <= secondValue);
- break;
-
- case SLU_MORE_EQUAL:
- setVariable(fun->reg, SVT_INT,
- firstValue >= secondValue);
- break;
-
- default:
- break;
- }
- }
- } else {
- return fatal(ERROR_NOSTACK);
- }
- break;
-
- default:
- return fatal(ERROR_UNKNOWN_CODE);
- }
-
- if (advanceNow)
- fun->runThisLine++;
-
- }
- return true;
-}
-
-bool runSludge() {
-
- LoadedFunction *thisFunction = allRunningFunctions;
- LoadedFunction *nextFunction;
-
- while (thisFunction) {
- nextFunction = thisFunction->next;
-
- if (!thisFunction->freezerLevel) {
- if (thisFunction->timeLeft) {
- if (thisFunction->timeLeft < 0) {
- if (!g_sludge->_soundMan->stillPlayingSound(
- g_sludge->_speechMan->getLastSpeechSound())) {
- thisFunction->timeLeft = 0;
- }
- } else if (!--(thisFunction->timeLeft)) {
- }
- } else {
- if (thisFunction->isSpeech) {
- thisFunction->isSpeech = false;
- g_sludge->_speechMan->kill();
- }
- if (!continueFunction(thisFunction))
- return false;
- }
- }
-
- thisFunction = nextFunction;
- }
-
- if (!g_sludge->loadNow.empty()) {
- if (g_sludge->loadNow[0] == ':') {
- saveGame(g_sludge->loadNow.c_str() + 1);
- setVariable(saverFunc->reg, SVT_INT, 1);
- } else {
- if (!loadGame(g_sludge->loadNow))
- return false;
- }
- g_sludge->loadNow.clear();
- }
-
- return true;
-}
-
-void killAllFunctions() {
- while (allRunningFunctions)
- finishFunction(allRunningFunctions);
-}
-
-bool loadFunctionCode(LoadedFunction *newFunc) {
- uint numLines, numLinesRead;
-
- if (!g_sludge->_resMan->openSubSlice(newFunc->originalNumber))
- return false;
-
- debugC(3, kSludgeDebugDataLoad, "Load function code");
-
- Common::SeekableReadStream *readStream = g_sludge->_resMan->getData();
- newFunc->unfreezable = readStream->readByte();
- numLines = readStream->readUint16BE();
- debugC(3, kSludgeDebugDataLoad, "numLines: %i", numLines);
- newFunc->numArgs = readStream->readUint16BE();
- debugC(3, kSludgeDebugDataLoad, "numArgs: %i", newFunc->numArgs);
- newFunc->numLocals = readStream->readUint16BE();
- debugC(3, kSludgeDebugDataLoad, "numLocals: %i", newFunc->numLocals);
- newFunc->compiledLines = new LineOfCode[numLines];
- if (!checkNew(newFunc->compiledLines))
- return false;
-
- for (numLinesRead = 0; numLinesRead < numLines; numLinesRead++) {
- newFunc->compiledLines[numLinesRead].theCommand = (sludgeCommand)readStream->readByte();
- newFunc->compiledLines[numLinesRead].param = readStream->readUint16BE();
- debugC(3, kSludgeDebugDataLoad, "command line %i: %i", numLinesRead,
- newFunc->compiledLines[numLinesRead].theCommand);
- }
- g_sludge->_resMan->finishAccess();
-
- // Now we need to reserve memory for the local variables
- newFunc->localVars = new Variable[newFunc->numLocals];
- if (!checkNew(newFunc->localVars))
- return false;
- for (int a = 0; a < newFunc->numLocals; a++) {
- initVarNew(newFunc->localVars[a]);
- }
-
- return true;
-}
-
-int startNewFunctionNum(uint funcNum, uint numParamsExpected,
- LoadedFunction *calledBy, VariableStack *&vStack, bool returnSommet) {
- LoadedFunction *newFunc = new LoadedFunction;
- checkNew(newFunc);
- newFunc->originalNumber = funcNum;
-
- loadFunctionCode(newFunc);
-
- if (newFunc->numArgs != (int) numParamsExpected)
- return fatal("Wrong number of parameters!");
- if (newFunc->numArgs > newFunc->numLocals)
- return fatal("More arguments than local Variable space!");
-
- // Now, lets copy the parameters from the calling function's stack...
-
- while (numParamsExpected) {
- numParamsExpected--;
- if (vStack == NULL)
- return fatal(
- "Corrupted file!The stack's empty and there were still parameters expected");
- copyVariable(vStack->thisVar, newFunc->localVars[numParamsExpected]);
- trimStack(vStack);
- }
-
- newFunc->cancelMe = false;
- newFunc->timeLeft = 0;
- newFunc->returnSomething = returnSommet;
- newFunc->calledBy = calledBy;
- newFunc->stack = NULL;
- newFunc->freezerLevel = 0;
- newFunc->runThisLine = 0;
- newFunc->isSpeech = 0;
- initVarNew(newFunc->reg);
-
- restartFunction(newFunc);
- return 1;
-}
-
-int lastFramesPerSecond = -1;
-int thisFramesPerSecond = -1;
-
} // End of namespace Sludge
diff --git a/engines/sludge/sludger.h b/engines/sludge/sludger.h
index 8f554f83cb..8efdfa62f2 100644
--- a/engines/sludge/sludger.h
+++ b/engines/sludge/sludger.h
@@ -22,12 +22,7 @@
#ifndef SLUDGER_H
#define SLUDGER_H
-#include "common/file.h"
-
#include "sludge/allfiles.h"
-#include "sludge/variable.h"
-#include "sludge/csludge.h"
-#include "sludge/language.h"
namespace Sludge {
@@ -36,52 +31,15 @@ typedef struct _FILETIME {
uint32 dwHighDateTime;
} FILETIME;
-struct Variable;
-struct VariableStack;
-
-struct LineOfCode {
- sludgeCommand theCommand;
- int32 param;
-};
-
-struct LoadedFunction {
- int originalNumber;
- LineOfCode *compiledLines;
- int numLocals, timeLeft, numArgs;
- Variable *localVars;
- VariableStack *stack;
- Variable reg;
- uint runThisLine;
- LoadedFunction *calledBy;
- LoadedFunction *next;
- bool returnSomething, isSpeech, unfreezable, cancelMe;
- byte freezerLevel;
-};
-
bool initSludge(const Common::String &);
-bool runSludge();
-
void initSludge();
void killSludge();
void displayBase();
void sludgeDisplay();
-int startNewFunctionNum(uint, uint, LoadedFunction *, VariableStack*&, bool = true);
-bool handleInput();
-void restartFunction(LoadedFunction *fun);
-bool loadFunctionCode(LoadedFunction *newFunc);
-void killAllFunctions();
-void finishFunction(LoadedFunction *fun);
-void abortFunction(LoadedFunction *fun);
Common::File *openAndVerify(const Common::String &filename, char extra1, char extra2, const char *er, int &fileVersion);
-void freezeSubs();
-void unfreezeSubs();
-void completeTimers();
-void killSpeechTimers();
-int cancelAFunction(int funcNum, LoadedFunction *myself, bool &killedMyself);
-
} // End of namespace Sludge
#endif
diff --git a/engines/sludge/sound.cpp b/engines/sludge/sound.cpp
index 306fd49b4e..25b239c191 100644
--- a/engines/sludge/sound.cpp
+++ b/engines/sludge/sound.cpp
@@ -402,7 +402,7 @@ bool SoundManager::getSoundCacheStack(StackHandler *sH) {
for (int a = 0; a < MAX_SAMPLES; a++) {
if (_soundCache[a].fileLoaded != -1) {
- setVariable(newFileHandle, SVT_FILE, _soundCache[a].fileLoaded);
+ newFileHandle.setVariable(SVT_FILE, _soundCache[a].fileLoaded);
if (!addVarToStackQuick(newFileHandle, sH->first))
return false;
if (sH->last == NULL)
diff --git a/engines/sludge/speech.cpp b/engines/sludge/speech.cpp
index 1d342a1b65..9c02eda5a6 100644
--- a/engines/sludge/speech.cpp
+++ b/engines/sludge/speech.cpp
@@ -45,7 +45,7 @@ void SpeechManager::init() {
_speech = new SpeechStruct;
if (checkNew(_speech)) {
_speech->currentTalker = NULL;
- _speech->allSpeech = NULL;
+ _speech->allSpeech.clear();
_speech->speechY = 0;
_speech->lastFile = -1;
}
@@ -61,20 +61,20 @@ void SpeechManager::kill() {
}
if (_speech->currentTalker) {
- makeSilent(*(_speech->currentTalker));
- _speech->currentTalker = NULL;
+ _speech->currentTalker->makeSilent();
+ _speech->currentTalker = nullptr;
}
- SpeechLine *killMe;
- while (_speech->allSpeech) {
- killMe = _speech->allSpeech;
- _speech->allSpeech = _speech->allSpeech->next;
+ for (SpeechLineList::iterator it = _speech->allSpeech.begin(); it != _speech->allSpeech.end(); ++it) {
+ SpeechLine *killMe = *it;
delete killMe;
+ killMe = nullptr;
}
+ _speech->allSpeech.clear();
}
void SpeechManager::setObjFontColour(ObjectType *t) {
- setFontColour(_speech->talkCol, t->r, t->g, t->b);
+ _speech->talkCol.setColor(t->r, t->g, t->b);
}
void SpeechManager::addSpeechLine(const Common::String &theLine, int x, int &offset) {
@@ -82,14 +82,16 @@ void SpeechManager::addSpeechLine(const Common::String &theLine, int x, int &off
int halfWidth = (g_sludge->_txtMan->stringWidth(theLine) >> 1) / cameraZoom;
int xx1 = x - (halfWidth);
int xx2 = x + (halfWidth);
+
+ // Create new speech line
SpeechLine *newLine = new SpeechLine;
checkNew(newLine);
-
- newLine->next = _speech->allSpeech;
newLine->textLine.clear();
newLine->textLine = theLine;
newLine->x = xx1;
- _speech->allSpeech = newLine;
+ _speech->allSpeech.push_front(newLine);
+
+ // Calculate offset
if ((xx1 < 5) && (offset < (5 - xx1))) {
offset = 5 - xx1;
} else if ((xx2 >= ((float) g_system->getWidth() / cameraZoom) - 5)
@@ -99,7 +101,7 @@ void SpeechManager::addSpeechLine(const Common::String &theLine, int x, int &off
}
int SpeechManager::isThereAnySpeechGoingOn() {
- return _speech->allSpeech ? _speech->lookWhosTalking : -1;
+ return _speech->allSpeech.empty() ? -1 : _speech->lookWhosTalking;
}
int SpeechManager::getLastSpeechSound() {
@@ -158,10 +160,8 @@ int SpeechManager::wrapSpeechXY(const Common::String &theText, int x, int y, int
+ (float) (g_system->getHeight() - fontHeight / 3) / cameraZoom;
if (offset) {
- SpeechLine *viewLine = _speech->allSpeech;
- while (viewLine) {
- viewLine->x += offset;
- viewLine = viewLine->next;
+ for (SpeechLineList::iterator it = _speech->allSpeech.begin(); it != _speech->allSpeech.end(); ++it) {
+ (*it)->x += offset;
}
}
return speechTime;
@@ -176,7 +176,7 @@ int SpeechManager::wrapSpeechPerson(const Common::String &theText, OnScreenPerso
- thePerson.thisType->speechGap,
thePerson.thisType->wrapSpeech, sampleFile);
if (animPerson) {
- makeTalker(thePerson);
+ thePerson.makeTalker();
_speech->currentTalker = &thePerson;
}
return i;
@@ -188,12 +188,12 @@ int SpeechManager::wrapSpeech(const Common::String &theText, int objT, int sampl
int cameraY = g_sludge->_gfxMan->getCamY();
_speech->lookWhosTalking = objT;
- OnScreenPerson *thisPerson = findPerson(objT);
+ OnScreenPerson *thisPerson = g_sludge->_peopleMan->findPerson(objT);
if (thisPerson) {
setObjFontColour(thisPerson->thisType);
i = wrapSpeechPerson(theText, *thisPerson, sampleFile, animPerson);
} else {
- ScreenRegion *thisRegion = getRegionForObject(objT);
+ ScreenRegion *thisRegion = g_sludge->_regionMan->getRegionForObject(objT);
if (thisRegion) {
setObjFontColour(thisRegion->thisType);
i = wrapSpeechXY(theText,
@@ -214,19 +214,14 @@ void SpeechManager::display() {
float cameraZoom = g_sludge->_gfxMan->getCamZoom();
int fontHeight = g_sludge->_txtMan->getFontHeight();
int viewY = _speech->speechY;
- SpeechLine *viewLine = _speech->allSpeech;
- while (viewLine) {
- g_sludge->_txtMan->pasteString(viewLine->textLine, viewLine->x, viewY, _speech->talkCol);
+ for (SpeechLineList::iterator it = _speech->allSpeech.begin(); it != _speech->allSpeech.end(); ++it) {
+ g_sludge->_txtMan->pasteString((*it)->textLine, (*it)->x, viewY, _speech->talkCol);
viewY -= fontHeight / cameraZoom;
- viewLine = viewLine->next;
}
}
void SpeechManager::save(Common::WriteStream *stream) {
stream->writeByte(_speechMode);
-
- SpeechLine *viewLine = _speech->allSpeech;
-
stream->writeByte(_speech->talkCol.originalRed);
stream->writeByte(_speech->talkCol.originalGreen);
stream->writeByte(_speech->talkCol.originalBlue);
@@ -246,11 +241,10 @@ void SpeechManager::save(Common::WriteStream *stream) {
}
// Write what's being said
- while (viewLine) {
+ for (SpeechLineList::iterator it = _speech->allSpeech.begin(); it != _speech->allSpeech.end(); ++it) {
stream->writeByte(1);
- writeString(viewLine->textLine, stream);
- stream->writeUint16BE(viewLine->x);
- viewLine = viewLine->next;
+ writeString((*it)->textLine, stream);
+ stream->writeUint16BE((*it)->x);
}
stream->writeByte(0);
}
@@ -264,8 +258,7 @@ bool SpeechManager::load(Common::SeekableReadStream *stream) {
byte r = stream->readByte();
byte g = stream->readByte();
byte b = stream->readByte();
- setFontColour(_speech->talkCol, r, g, b);
-
+ _speech->talkCol.setColor(r, g, b);
_speechSpeed = stream->readFloatLE();
// Read y co-ordinate
@@ -275,24 +268,20 @@ bool SpeechManager::load(Common::SeekableReadStream *stream) {
_speech->lookWhosTalking = stream->readUint16BE();
if (stream->readByte()) {
- _speech->currentTalker = findPerson(stream->readUint16BE());
+ _speech->currentTalker = g_sludge->_peopleMan->findPerson(stream->readUint16BE());
} else {
_speech->currentTalker = NULL;
}
// Read what's being said
- SpeechLine **viewLine = &_speech->allSpeech;
- SpeechLine *newOne;
_speech->lastFile = -1;
while (stream->readByte()) {
- newOne = new SpeechLine;
+ SpeechLine *newOne = new SpeechLine;
if (!checkNew(newOne))
return false;
newOne->textLine = readString(stream);
newOne->x = stream->readUint16BE();
- newOne->next = NULL;
- (*viewLine) = newOne;
- viewLine = &(newOne->next);
+ _speech->allSpeech.push_back(newOne);
}
return true;
}
diff --git a/engines/sludge/speech.h b/engines/sludge/speech.h
index 98b6035cb0..776a9f5dea 100644
--- a/engines/sludge/speech.h
+++ b/engines/sludge/speech.h
@@ -30,13 +30,14 @@ struct ObjectType;
struct SpeechLine {
Common::String textLine;
- SpeechLine *next;
int x;
};
+typedef Common::List<SpeechLine *> SpeechLineList;
+
struct SpeechStruct {
OnScreenPerson *currentTalker;
- SpeechLine *allSpeech;
+ SpeechLineList allSpeech;
int speechY, lastFile, lookWhosTalking;
SpritePalette talkCol;
};
@@ -60,6 +61,7 @@ public:
void setObjFontColour(ObjectType *t);
void setSpeechSpeed(float speed) { _speechSpeed = speed; }
float getSpeechSpeed() { return _speechSpeed; }
+ void setSpeechMode(int speechMode) { _speechMode = speechMode; }
// load & save
void save(Common::WriteStream *stream);
diff --git a/engines/sludge/sprites.h b/engines/sludge/sprites.h
index e138c6f14f..e18d16e5df 100644
--- a/engines/sludge/sprites.h
+++ b/engines/sludge/sprites.h
@@ -42,15 +42,8 @@ public:
byte originalRed, originalGreen, originalBlue, total;
SpritePalette() { init(); }
-
~SpritePalette() { kill(); }
- void reset() {
- kill();
- init();
- }
-
-private:
void init() {
pal = nullptr;
r = g = b = nullptr;
@@ -59,15 +52,29 @@ private:
}
void kill() {
- if (pal)
+ if (pal) {
delete[] pal;
- if (r)
+ pal = nullptr;
+ }
+ if (r) {
delete[] r;
- if (g)
+ r = nullptr;
+ }
+ if (g) {
delete[] g;
- if (b)
+ g = nullptr;
+ }
+ if (b) {
delete[] b;
+ b = nullptr;
+ }
}
+
+ void setColor(byte red, byte green, byte blue) {
+ originalRed = red;
+ originalGreen = green;
+ originalBlue = blue;
+ }
};
struct SpriteBank {
diff --git a/engines/sludge/statusba.cpp b/engines/sludge/statusba.cpp
index 1aa24971f1..fc0f065ea9 100644
--- a/engines/sludge/statusba.cpp
+++ b/engines/sludge/statusba.cpp
@@ -37,8 +37,8 @@ namespace Sludge {
SpritePalette verbLinePalette;
SpritePalette litVerbLinePalette;
-StatusStuff mainStatus;
-StatusStuff *nowStatus = & mainStatus;
+StatusStuff mainStatus;
+StatusStuff *nowStatus = & mainStatus;
void setLitStatus(int i) {
nowStatus->litStatus = i;
@@ -114,14 +114,14 @@ void drawStatusBar() {
}
void statusBarColour(byte r, byte g, byte b) {
- setFontColour(verbLinePalette, r, g, b);
+ verbLinePalette.setColor(r, g, b);
nowStatus->statusR = r;
nowStatus->statusG = g;
nowStatus->statusB = b;
}
void statusBarLitColour(byte r, byte g, byte b) {
- setFontColour(litVerbLinePalette, r, g, b);
+ litVerbLinePalette.setColor(r, g, b);
nowStatus->statusLR = r;
nowStatus->statusLG = g;
nowStatus->statusLB = b;
@@ -144,7 +144,7 @@ StatusStuff *copyStatusBarStuff(StatusStuff *here) {
here->litStatus = -1;
here->firstStatusBar = NULL;
- StatusStuff *old = nowStatus;
+ StatusStuff *old = nowStatus;
nowStatus = here;
return old;
@@ -152,8 +152,8 @@ StatusStuff *copyStatusBarStuff(StatusStuff *here) {
void restoreBarStuff(StatusStuff *here) {
delete nowStatus;
- setFontColour(verbLinePalette, here->statusR, here->statusG, here->statusB);
- setFontColour(litVerbLinePalette, here->statusLR, here->statusLG, here->statusLB);
+ verbLinePalette.setColor((byte)here->statusR, (byte)here->statusG, (byte)here->statusB);
+ litVerbLinePalette.setColor((byte)here->statusLR, (byte)here->statusLG, (byte)here->statusLB);
nowStatus = here;
}
@@ -215,8 +215,8 @@ bool loadStatusBars(Common::SeekableReadStream *stream) {
nowStatus->statusLG = stream->readByte();
nowStatus->statusLB = stream->readByte();
- setFontColour(verbLinePalette, nowStatus->statusR, nowStatus->statusG, nowStatus->statusB);
- setFontColour(litVerbLinePalette, nowStatus->statusLR, nowStatus->statusLG, nowStatus->statusLB);
+ verbLinePalette.setColor((byte)nowStatus->statusR, (byte)nowStatus->statusG, (byte)nowStatus->statusB);
+ litVerbLinePalette.setColor((byte)nowStatus->statusLR, (byte)nowStatus->statusLG, (byte)nowStatus->statusLB);
// Read what's being said
StatusBar **viewLine = & (nowStatus->firstStatusBar);
StatusBar *newOne;
diff --git a/engines/sludge/thumbnail.cpp b/engines/sludge/thumbnail.cpp
index 2c7e007f71..dcbcd91db3 100644
--- a/engines/sludge/thumbnail.cpp
+++ b/engines/sludge/thumbnail.cpp
@@ -35,14 +35,23 @@
namespace Sludge {
-int thumbWidth = 0, thumbHeight = 0;
+bool GraphicsManager::setThumbnailSize(int thumbWidth, int thumbHeight)
+{
+ if (checkSizeValide(thumbWidth, thumbHeight))
+ {
+ _thumbWidth = thumbWidth;
+ _thumbHeight = thumbHeight;
+ return true;
+ }
+ return false;
+}
bool GraphicsManager::saveThumbnail(Common::WriteStream *stream) {
- stream->writeUint32LE(thumbWidth);
- stream->writeUint32LE(thumbHeight);
+ stream->writeUint32LE(_thumbWidth);
+ stream->writeUint32LE(_thumbHeight);
- if (thumbWidth && thumbHeight) {
+ if (_thumbWidth && _thumbHeight) {
if (!freeze())
return false;
@@ -117,12 +126,12 @@ void GraphicsManager::showThumbnail(const Common::String &filename, int atX, int
}
bool GraphicsManager::skipThumbnail(Common::SeekableReadStream *stream) {
- thumbWidth = stream->readUint32LE();
- thumbHeight = stream->readUint32LE();
+ _thumbWidth = stream->readUint32LE();
+ _thumbHeight = stream->readUint32LE();
// Load image
Graphics::Surface tmp;
- if (thumbWidth & thumbHeight) {
+ if (_thumbWidth & _thumbHeight) {
if (!ImgLoader::loadPNGImage(stream, &tmp))
return false;
else
diff --git a/engines/sludge/timing.cpp b/engines/sludge/timing.cpp
index 2e3865498a..c291f57a6b 100644
--- a/engines/sludge/timing.cpp
+++ b/engines/sludge/timing.cpp
@@ -25,31 +25,63 @@
namespace Sludge {
+Timer::Timer(){
+ reset();
+}
+
+void Timer::reset(void) {
+ _desiredFPS = 300;
+ _startTime = 0;
+ _endTime = 0;
+ _desiredFrameTime = 0;
+ _addNextTime = 0;
+
+ // FPS stats
+ _lastFPS = -1;
+ _thisFPS = -1;
+ _lastSeconds = 0;
+}
+
void Timer::init(void) {
- _desired_frame_time = 1000 / _desiredfps;
- _starttime = g_system->getMillis();
+ _desiredFrameTime = 1000 / _desiredFPS;
+ _startTime = g_system->getMillis();
}
void Timer::initSpecial(int t) {
- _desired_frame_time = 1000 / t;
- _starttime = g_system->getMillis();
+ _desiredFrameTime = 1000 / t;
+ _startTime = g_system->getMillis();
+}
+
+void Timer::updateFpsStats() {
+ uint32 currentSeconds = g_system->getMillis() / 1000;
+ if (_lastSeconds != currentSeconds) {
+ _lastSeconds = currentSeconds;
+ _lastFPS = _thisFPS;
+ _thisFPS = 1;
+ } else {
+ ++_thisFPS;
+ }
}
void Timer::waitFrame(void) {
- static uint32 addNextTime = 0;
uint32 timetaken;
for (;;) {
- _endtime = g_system->getMillis();
- timetaken = addNextTime + _endtime - _starttime;
- if (timetaken >= _desired_frame_time) break;
+ _endTime = g_system->getMillis();
+ timetaken = _addNextTime + _endTime - _startTime;
+ if (timetaken >= _desiredFrameTime)
+ break;
g_system->delayMillis(1);
}
- addNextTime = timetaken - _desired_frame_time;
- if (addNextTime > _desired_frame_time) addNextTime = _desired_frame_time;
+ _addNextTime = timetaken - _desiredFrameTime;
+ if (_addNextTime > _desiredFrameTime)
+ _addNextTime = _desiredFrameTime;
+
+ _startTime = _endTime;
- _starttime = _endtime;
+ // Stats
+ updateFpsStats();
}
} // End of namespace Sludge
diff --git a/engines/sludge/timing.h b/engines/sludge/timing.h
index 0d7ffece8d..e04ddf4732 100644
--- a/engines/sludge/timing.h
+++ b/engines/sludge/timing.h
@@ -25,18 +25,28 @@
namespace Sludge {
class Timer {
-private:
- int _desiredfps; // desired frames per second
- uint32 _starttime, _endtime;
- uint32 _desired_frame_time;
-
public:
- void setDesiredfps(int t) { _desiredfps = t; }
+ Timer();
+
+ void setDesiredFPS(int t) { _desiredFPS = t; }
+ void reset(void);
void init(void);
void initSpecial(int t);
void waitFrame(void);
- Timer():_desiredfps(300), _starttime(0), _endtime(0), _desired_frame_time(0){}
+ int getLastFps() const { return _lastFPS; }
+
+private:
+ int _desiredFPS; // desired frames per second
+ uint32 _startTime, _endTime;
+ uint32 _desiredFrameTime;
+ uint32 _addNextTime;
+
+ // FPS stats
+ void updateFpsStats();
+ int _lastFPS;
+ int _thisFPS;
+ uint32 _lastSeconds;
};
} // End of namespace Sludge
diff --git a/engines/sludge/transition.cpp b/engines/sludge/transition.cpp
index 3a768cb5f4..35f650e8e4 100644
--- a/engines/sludge/transition.cpp
+++ b/engines/sludge/transition.cpp
@@ -22,15 +22,22 @@
#include "sludge/allfiles.h"
#include "sludge/backdrop.h"
+#include "sludge/graphics.h"
#include "sludge/newfatal.h"
namespace Sludge {
-extern byte brightnessLevel;
-
extern float snapTexW, snapTexH;
-byte fadeMode = 2;
+void GraphicsManager::setBrightnessLevel(int brightnessLevel)
+{
+ if (brightnessLevel < 0)
+ _brightnessLevel = 0;
+ else if (brightnessLevel > 255)
+ _brightnessLevel = 255;
+ else
+ _brightnessLevel = brightnessLevel;
+}
//----------------------------------------------------
// PROPER BRIGHTNESS FADING
@@ -142,7 +149,7 @@ void transitionSnapshotBox() {
uint32 randbuffer[KK][2]; // history buffer
int p1, p2;
-void resetRandW() {
+void GraphicsManager::resetRandW() {
int32 seed = 12345;
for (int i = 0; i < KK; i++) {
@@ -373,8 +380,8 @@ void transitionBlinds() {
//----------------------------------------------------
-void fixBrightness() {
- switch (fadeMode) {
+void GraphicsManager::fixBrightness() {
+ switch (_fadeMode) {
case 0:
transitionFader();
break;
diff --git a/engines/sludge/variable.cpp b/engines/sludge/variable.cpp
index 9cbb9f49f8..44381aa97f 100644
--- a/engines/sludge/variable.cpp
+++ b/engines/sludge/variable.cpp
@@ -38,34 +38,37 @@ const char *typeName[] = { "undefined", "number", "user function", "string",
"built-in function", "file", "stack", "object type", "animation",
"costume" };
-void unlinkVar(Variable &thisVar) {
- switch (thisVar.varType) {
+void Variable::unlinkVar() {
+ switch (varType) {
case SVT_STRING:
- delete []thisVar.varData.theString;
- thisVar.varData.theString = NULL;
+ delete []varData.theString;
+ varData.theString = NULL;
break;
case SVT_STACK:
- thisVar.varData.theStack->timesUsed--;
- if (thisVar.varData.theStack->timesUsed <= 0) {
- while (thisVar.varData.theStack->first)
- trimStack(thisVar.varData.theStack->first);
- delete thisVar.varData.theStack;
- thisVar.varData.theStack = NULL;
+ varData.theStack->timesUsed--;
+ if (varData.theStack->timesUsed <= 0) {
+ while (varData.theStack->first)
+ trimStack(varData.theStack->first);
+ delete varData.theStack;
+ varData.theStack = NULL;
}
break;
case SVT_FASTARRAY:
- thisVar.varData.fastArray->timesUsed--;
- if (thisVar.varData.theStack->timesUsed <= 0) {
- delete thisVar.varData.fastArray->fastVariables;
- delete[] thisVar.varData.fastArray;
- thisVar.varData.fastArray = NULL;
+ varData.fastArray->timesUsed--;
+ if (varData.theStack->timesUsed <= 0) {
+ delete varData.fastArray->fastVariables;
+ delete[] varData.fastArray;
+ varData.fastArray = NULL;
}
break;
case SVT_ANIM:
- deleteAnim(thisVar.varData.animHandler);
+ if (varData.animHandler) {
+ delete varData.animHandler;
+ varData.animHandler = nullptr;
+ }
break;
default:
@@ -73,39 +76,39 @@ void unlinkVar(Variable &thisVar) {
}
}
-void setVariable(Variable &thisVar, VariableType vT, int value) {
- unlinkVar(thisVar);
- thisVar.varType = vT;
- thisVar.varData.intValue = value;
+void Variable::setVariable(VariableType vT, int value) {
+ unlinkVar();
+ varType = vT;
+ varData.intValue = value;
}
-void newAnimationVariable(Variable &thisVar, PersonaAnimation *i) {
- unlinkVar(thisVar);
- thisVar.varType = SVT_ANIM;
- thisVar.varData.animHandler = i;
+void Variable::makeAnimationVariable(PersonaAnimation *i) {
+ unlinkVar();
+ varType = SVT_ANIM;
+ varData.animHandler = i;
}
-PersonaAnimation *getAnimationFromVar(Variable &thisVar) {
- if (thisVar.varType == SVT_ANIM)
- return copyAnim(thisVar.varData.animHandler);
+PersonaAnimation *Variable::getAnimationFromVar() {
+ if (varType == SVT_ANIM)
+ return new PersonaAnimation(varData.animHandler);
- if (thisVar.varType == SVT_INT && thisVar.varData.intValue == 0)
- return makeNullAnim();
+ if (varType == SVT_INT && varData.intValue == 0)
+ return new PersonaAnimation();
- fatal("Expecting an animation variable; found Variable of type", typeName[thisVar.varType]);
+ fatal("Expecting an animation variable; found Variable of type", typeName[varType]);
return NULL;
}
-void newCostumeVariable(Variable &thisVar, Persona *i) {
- unlinkVar(thisVar);
- thisVar.varType = SVT_COSTUME;
- thisVar.varData.costumeHandler = i;
+void Variable::makeCostumeVariable(Persona *i) {
+ unlinkVar();
+ varType = SVT_COSTUME;
+ varData.costumeHandler = i;
}
-Persona *getCostumeFromVar(Variable &thisVar) {
+Persona *Variable::getCostumeFromVar() {
Persona *p = NULL;
- switch (thisVar.varType) {
+ switch (varType) {
case SVT_ANIM:
p = new Persona;
if (!checkNew(p))
@@ -116,24 +119,24 @@ Persona *getCostumeFromVar(Variable &thisVar) {
return NULL;
for (int iii = 0; iii < 3; iii++)
- p->animation[iii] = copyAnim(thisVar.varData.animHandler);
+ p->animation[iii] = new PersonaAnimation(varData.animHandler);
break;
case SVT_COSTUME:
- return thisVar.varData.costumeHandler;
+ return varData.costumeHandler;
break;
default:
- fatal("Expecting an animation variable; found Variable of type", typeName[thisVar.varType]);
+ fatal("Expecting an animation variable; found Variable of type", typeName[varType]);
}
return p;
}
-int stackSize(const StackHandler *me) {
+int StackHandler::getStackSize() const {
int r = 0;
- VariableStack *a = me->first;
+ VariableStack *a = first;
while (a) {
r++;
a = a->next;
@@ -141,8 +144,7 @@ int stackSize(const StackHandler *me) {
return r;
}
-bool getSavedGamesStack(StackHandler *sH, const Common::String &ext) {
-
+bool StackHandler::getSavedGamesStack(const Common::String &ext) {
// Make pattern
uint len = ext.size();
Common::String pattern = "*";
@@ -157,30 +159,30 @@ bool getSavedGamesStack(StackHandler *sH, const Common::String &ext) {
Common::StringArray::iterator it;
for (it = sa.begin(); it != sa.end(); ++it) {
(*it).erase((*it).size() - len, len);
- makeTextVar(newName, (*it));
- if (!addVarToStack(newName, sH->first))
+ newName.makeTextVar((*it));
+ if (!addVarToStack(newName, first))
return false;
- if (sH->last == NULL)
- sH->last = sH->first;
+ if (last == NULL)
+ last = first;
}
return true;
}
-bool copyStack(const Variable &from, Variable &to) {
- to.varType = SVT_STACK;
- to.varData.theStack = new StackHandler;
- if (!checkNew(to.varData.theStack))
+bool Variable::copyStack(const Variable &from) {
+ varType = SVT_STACK;
+ varData.theStack = new StackHandler;
+ if (!checkNew(varData.theStack))
return false;
- to.varData.theStack->first = NULL;
- to.varData.theStack->last = NULL;
- to.varData.theStack->timesUsed = 1;
+ varData.theStack->first = NULL;
+ varData.theStack->last = NULL;
+ varData.theStack->timesUsed = 1;
VariableStack *a = from.varData.theStack->first;
while (a) {
- addVarToStack(a->thisVar, to.varData.theStack->first);
- if (to.varData.theStack->last == NULL) {
- to.varData.theStack->last = to.varData.theStack->first;
+ addVarToStack(a->thisVar, varData.theStack->first);
+ if (varData.theStack->last == NULL) {
+ varData.theStack->last = varData.theStack->first;
}
a = a->next;
}
@@ -188,89 +190,78 @@ bool copyStack(const Variable &from, Variable &to) {
return true;
}
-void addVariablesInSecond(Variable &var1, Variable &var2) {
- if (var1.varType == SVT_INT && var2.varType == SVT_INT) {
- var2.varData.intValue += var1.varData.intValue;
+void Variable::addVariablesInSecond(const Variable &other) {
+ if (other.varType == SVT_INT && varType == SVT_INT) {
+ varData.intValue += other.varData.intValue;
} else {
- Common::String string1 = getTextFromAnyVar(var1);
- Common::String string2 = getTextFromAnyVar(var2);
+ Common::String string1 = other.getTextFromAnyVar();
+ Common::String string2 = getTextFromAnyVar();
- unlinkVar(var2);
- var2.varData.theString = createCString(string1 + string2);
- var2.varType = SVT_STRING;
+ unlinkVar();
+ varData.theString = createCString(string1 + string2);
+ varType = SVT_STRING;
}
}
-int compareVars(const Variable &var1, const Variable &var2) {
+int Variable::compareVars(const Variable &other) const {
int re = 0;
- if (var1.varType == var2.varType) {
- switch (var1.varType) {
+ if (other.varType == varType) {
+ switch (other.varType) {
case SVT_NULL:
re = 1;
break;
case SVT_COSTUME:
- re = (var1.varData.costumeHandler == var2.varData.costumeHandler);
+ re = (other.varData.costumeHandler == varData.costumeHandler);
break;
case SVT_ANIM:
- re = (var1.varData.animHandler == var2.varData.animHandler);
+ re = (other.varData.animHandler == varData.animHandler);
break;
case SVT_STRING:
- re = (strcmp(var1.varData.theString, var2.varData.theString) == 0);
+ re = (strcmp(other.varData.theString, varData.theString) == 0);
break;
case SVT_STACK:
- re = (var1.varData.theStack == var2.varData.theStack);
+ re = (other.varData.theStack == varData.theStack);
break;
default:
- re = (var1.varData.intValue == var2.varData.intValue);
+ re = (other.varData.intValue == varData.intValue);
}
}
return re;
}
-void compareVariablesInSecond(const Variable &var1, Variable &var2) {
- setVariable(var2, SVT_INT, compareVars(var1, var2));
-}
-
-char *createCString(const Common::String &s) {
- uint n = s.size() + 1;
- char *res = new char[n];
- if (!checkNew(res)) {
- fatal("createCString : Unable to copy String");
- return NULL;
- }
- memcpy(res, s.c_str(), n);
- return res;
+void Variable::compareVariablesInSecond(const Variable &other) {
+ setVariable(SVT_INT, compareVars(other));
}
-void makeTextVar(Variable &thisVar, const Common::String &txt) {
- unlinkVar(thisVar);
- thisVar.varType = SVT_STRING;
- thisVar.varData.theString = createCString(txt);
+void Variable::makeTextVar(const Common::String &txt) {
+ unlinkVar();
+ varType = SVT_STRING;
+ varData.theString = createCString(txt);
}
-bool loadStringToVar(Variable &thisVar, int value) {
- makeTextVar(thisVar, g_sludge->_resMan->getNumberedString(value));
- return (bool)(thisVar.varData.theString != NULL);
+bool Variable::loadStringToVar(int value) {
+ makeTextVar(g_sludge->_resMan->getNumberedString(value));
+ return (bool)(varData.theString != NULL);
}
-Common::String getTextFromAnyVar(const Variable &from) {
- switch (from.varType) {
+Common::String Variable::getTextFromAnyVar() const {
+ switch (varType) {
case SVT_STRING:
- return from.varData.theString;
+ return varData.theString;
case SVT_FASTARRAY: {
Common::String builder = "FAST:";
Common::String builder2 = "";
Common::String grabText = "";
- for (int i = 0; i < from.varData.fastArray->size; i++) {
+ for (int i = 0; i < varData.fastArray->size; i++) {
builder2 = builder + " ";
- grabText = getTextFromAnyVar(from.varData.fastArray->fastVariables[i]);
+ grabText = varData.fastArray->fastVariables[i].getTextFromAnyVar();
builder.clear();
builder = builder2 + grabText;
}
@@ -282,11 +273,11 @@ Common::String getTextFromAnyVar(const Variable &from) {
Common::String builder2 = "";
Common::String grabText = "";
- VariableStack *stacky = from.varData.theStack->first;
+ VariableStack *stacky = varData.theStack->first;
while (stacky) {
builder2 = builder + " ";
- grabText = getTextFromAnyVar(stacky->thisVar);
+ grabText = stacky->thisVar.getTextFromAnyVar();
builder.clear();
builder = builder2 + grabText;
stacky = stacky->next;
@@ -295,16 +286,16 @@ Common::String getTextFromAnyVar(const Variable &from) {
}
case SVT_INT: {
- Common::String buff = Common::String::format("%i", from.varData.intValue);
+ Common::String buff = Common::String::format("%i", varData.intValue);
return buff;
}
case SVT_FILE: {
- return resourceNameFromNum(from.varData.intValue);
+ return g_sludge->_resMan->resourceNameFromNum(varData.intValue);
}
case SVT_OBJTYPE: {
- ObjectType *thisType = g_sludge->_objMan->findObjectType(from.varData.intValue);
+ ObjectType *thisType = g_sludge->_objMan->findObjectType(varData.intValue);
if (thisType)
return thisType->screenName;
break;
@@ -314,25 +305,25 @@ Common::String getTextFromAnyVar(const Variable &from) {
break;
}
- return typeName[from.varType];
+ return typeName[varType];
}
-bool getBoolean(const Variable &from) {
- switch (from.varType) {
+bool Variable::getBoolean() const {
+ switch (varType) {
case SVT_NULL:
return false;
case SVT_INT:
- return (bool)(from.varData.intValue != 0);
+ return (bool)(varData.intValue != 0);
case SVT_STACK:
- return (bool)(from.varData.theStack->first != NULL);
+ return (bool)(varData.theStack->first != NULL);
case SVT_STRING:
- return (bool)(from.varData.theString[0] != 0);
+ return (bool)(varData.theString[0] != 0);
case SVT_FASTARRAY:
- return (bool)(from.varData.fastArray->size != 0);
+ return (bool)(varData.fastArray->size != 0);
default:
break;
@@ -340,37 +331,37 @@ bool getBoolean(const Variable &from) {
return true;
}
-bool copyMain(const Variable &from, Variable &to) {
- to.varType = from.varType;
- switch (to.varType) {
+bool Variable::copyMain(const Variable &from) {
+ varType = from.varType;
+ switch (varType) {
case SVT_INT:
case SVT_FUNC:
case SVT_BUILT:
case SVT_FILE:
case SVT_OBJTYPE:
- to.varData.intValue = from.varData.intValue;
+ varData.intValue = from.varData.intValue;
return true;
case SVT_FASTARRAY:
- to.varData.fastArray = from.varData.fastArray;
- to.varData.fastArray->timesUsed++;
+ varData.fastArray = from.varData.fastArray;
+ varData.fastArray->timesUsed++;
return true;
case SVT_STRING:
- to.varData.theString = createCString(from.varData.theString);
- return to.varData.theString ? true : false;
+ varData.theString = createCString(from.varData.theString);
+ return varData.theString ? true : false;
case SVT_STACK:
- to.varData.theStack = from.varData.theStack;
- to.varData.theStack->timesUsed++;
+ varData.theStack = from.varData.theStack;
+ varData.theStack->timesUsed++;
return true;
case SVT_COSTUME:
- to.varData.costumeHandler = from.varData.costumeHandler;
+ varData.costumeHandler = from.varData.costumeHandler;
return true;
case SVT_ANIM:
- to.varData.animHandler = copyAnim(from.varData.animHandler);
+ varData.animHandler = new PersonaAnimation(from.varData.animHandler);
return true;
case SVT_NULL:
@@ -383,39 +374,36 @@ bool copyMain(const Variable &from, Variable &to) {
return false;
}
-bool copyVariable(const Variable &from, Variable &to) {
- unlinkVar(to);
- return copyMain(from, to);
+bool Variable::copyFrom(const Variable &from) {
+ unlinkVar();
+ return copyMain(from);
}
-Variable *fastArrayGetByIndex(FastArrayHandler *vS, uint theIndex) {
- if ((int)theIndex >= vS->size)
+Variable *FastArrayHandler::fastArrayGetByIndex(uint theIndex) {
+ if ((int)theIndex >= size)
return NULL;
- return &vS->fastVariables[theIndex];
+ return &fastVariables[theIndex];
}
-bool makeFastArraySize(Variable &to, int size) {
+bool Variable::makeFastArraySize(int size) {
if (size < 0)
return fatal("Can't create a fast array with a negative number of elements!");
- unlinkVar(to);
- to.varType = SVT_FASTARRAY;
- to.varData.fastArray = new FastArrayHandler;
- if (!checkNew(to.varData.fastArray))
+ unlinkVar();
+ varType = SVT_FASTARRAY;
+ varData.fastArray = new FastArrayHandler;
+ if (!checkNew(varData.fastArray))
return false;
- to.varData.fastArray->fastVariables = new Variable[size];
- if (!checkNew(to.varData.fastArray->fastVariables))
+ varData.fastArray->fastVariables = new Variable[size];
+ if (!checkNew(varData.fastArray->fastVariables))
return false;
- for (int i = 0; i < size; i++) {
- initVarNew(to.varData.fastArray->fastVariables[i]);
- }
- to.varData.fastArray->size = size;
- to.varData.fastArray->timesUsed = 1;
+ varData.fastArray->size = size;
+ varData.fastArray->timesUsed = 1;
return true;
}
-bool makeFastArrayFromStack(Variable &to, const StackHandler *stacky) {
- int size = stackSize(stacky);
- if (!makeFastArraySize(to, size))
+bool Variable::makeFastArrayFromStack(const StackHandler *stacky) {
+ int size = stacky->getStackSize();
+ if (!makeFastArraySize(size))
return false;
// Now let's fill up the new array
@@ -423,7 +411,7 @@ bool makeFastArrayFromStack(Variable &to, const StackHandler *stacky) {
VariableStack *allV = stacky->first;
size = 0;
while (allV) {
- copyMain(allV->thisVar, to.varData.fastArray->fastVariables[size]);
+ varData.fastArray->fastVariables[size].copyMain(allV->thisVar);
size++;
allV = allV->next;
}
@@ -435,7 +423,7 @@ bool addVarToStack(const Variable &va, VariableStack *&thisStack) {
if (!checkNew(newStack))
return false;
- if (!copyMain(va, newStack->thisVar))
+ if (!newStack->thisVar.copyMain(va))
return false;
newStack->next = thisStack;
thisStack = newStack;
@@ -459,16 +447,18 @@ bool addVarToStackQuick(Variable &va, VariableStack *&thisStack) {
return true;
}
-bool stackSetByIndex(VariableStack *vS, uint theIndex, const Variable &va) {
+bool VariableStack::stackSetByIndex(uint theIndex, const Variable &va) {
+ VariableStack *vS = this;
while (theIndex--) {
vS = vS->next;
if (!vS)
return fatal("Index past end of stack.");
}
- return copyVariable(va, vS->thisVar);
+ return vS->thisVar.copyFrom(va);
}
-Variable *stackGetByIndex(VariableStack *vS, uint theIndex) {
+Variable *VariableStack::stackGetByIndex(uint theIndex) {
+ VariableStack *vS = this;
while (theIndex--) {
vS = vS->next;
if (!vS) {
@@ -484,10 +474,10 @@ int deleteVarFromStack(const Variable &va, VariableStack *&thisStack, bool allOf
int reply = 0;
while (*huntVar) {
- if (compareVars((*huntVar)->thisVar, va)) {
+ if (va.compareVars((*huntVar)->thisVar)) {
killMe = *huntVar;
*huntVar = killMe->next;
- unlinkVar(killMe->thisVar);
+ killMe->thisVar.unlinkVar();
delete killMe;
if (!allOfEm)
return 1;
@@ -501,28 +491,25 @@ int deleteVarFromStack(const Variable &va, VariableStack *&thisStack, bool allOf
}
// Would be a LOT better just to keep this up to date in the above function... ah well
-VariableStack *stackFindLast(VariableStack *hunt) {
- if (hunt == NULL)
- return NULL;
-
+VariableStack *VariableStack::stackFindLast() {
+ VariableStack *hunt = this;
while (hunt->next)
hunt = hunt->next;
return hunt;
}
-bool getValueType(int &toHere, VariableType vT, const Variable &v) {
- //if (! v) return false;
- if (v.varType != vT) {
+bool Variable::getValueType(int &toHere, VariableType vT) const {
+ if (varType != vT) {
Common::String e1 = "Can only perform specified operation on a value which is of type ";
e1 += typeName[vT];
Common::String e2 = "... value supplied was of type ";
- e2 += typeName[v.varType];
+ e2 += typeName[varType];
fatal(e1, e2);
return false;
}
- toHere = v.varData.intValue;
+ toHere = varData.intValue;
return true;
}
@@ -533,8 +520,212 @@ void trimStack(VariableStack *&stack) {
//debugC(2, kSludgeDebugStackMachine, "Variable %s was removed from stack", getTextFromAnyVar(killMe->thisVar));
// When calling this, we've ALWAYS checked that stack != NULL
- unlinkVar(killMe->thisVar);
+ killMe->thisVar.unlinkVar();
delete killMe;
}
+//----------------------------------------------------------------------
+// Globals (so we know what's saved already and what's a reference
+//----------------------------------------------------------------------
+
+struct stackLibrary {
+ StackHandler *stack;
+ stackLibrary *next;
+};
+
+int stackLibTotal = 0;
+stackLibrary *stackLib = NULL;
+
+//----------------------------------------------------------------------
+// For saving and loading stacks...
+//----------------------------------------------------------------------
+void saveStack(VariableStack *vs, Common::WriteStream *stream) {
+ int elements = 0;
+ int a;
+
+ VariableStack *search = vs;
+ while (search) {
+ elements++;
+ search = search->next;
+ }
+
+ stream->writeUint16BE(elements);
+ search = vs;
+ for (a = 0; a < elements; a++) {
+ search->thisVar.save(stream);
+ search = search->next;
+ }
+}
+
+VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last) {
+ int elements = stream->readUint16BE();
+ int a;
+ VariableStack *first = NULL;
+ VariableStack **changeMe = &first;
+
+ for (a = 0; a < elements; a++) {
+ VariableStack *nS = new VariableStack;
+ if (!checkNew(nS))
+ return NULL;
+ nS->thisVar.load(stream);
+ if (last && a == elements - 1) {
+ *last = nS;
+ }
+ nS->next = NULL;
+ (*changeMe) = nS;
+ changeMe = &(nS->next);
+ }
+
+ return first;
+}
+
+bool saveStackRef(StackHandler *vs, Common::WriteStream *stream) {
+ stackLibrary *s = stackLib;
+ int a = 0;
+ while (s) {
+ if (s->stack == vs) {
+ stream->writeByte(1);
+ stream->writeUint16BE(stackLibTotal - a);
+ return true;
+ }
+ s = s->next;
+ a++;
+ }
+ stream->writeByte(0);
+ saveStack(vs->first, stream);
+ s = new stackLibrary;
+ stackLibTotal++;
+ if (!checkNew(s))
+ return false;
+ s->next = stackLib;
+ s->stack = vs;
+ stackLib = s;
+ return true;
+}
+
+void clearStackLib() {
+ stackLibrary *k;
+ while (stackLib) {
+ k = stackLib;
+ stackLib = stackLib->next;
+ delete k;
+ }
+ stackLibTotal = 0;
+}
+
+StackHandler *getStackFromLibrary(int n) {
+ n = stackLibTotal - n;
+ while (n) {
+ stackLib = stackLib->next;
+ n--;
+ }
+ return stackLib->stack;
+}
+
+StackHandler *loadStackRef(Common::SeekableReadStream *stream) {
+ StackHandler *nsh;
+
+ if (stream->readByte()) { // It's one we've loaded already...
+ nsh = getStackFromLibrary(stream->readUint16BE());
+ nsh->timesUsed++;
+ } else {
+ // Load the new stack
+
+ nsh = new StackHandler;
+ if (!checkNew(nsh))
+ return NULL;
+ nsh->last = NULL;
+ nsh->first = loadStack(stream, &nsh->last);
+ nsh->timesUsed = 1;
+
+ // Add it to the library of loaded stacks
+
+ stackLibrary *s = new stackLibrary;
+ if (!checkNew(s))
+ return NULL;
+ s->stack = nsh;
+ s->next = stackLib;
+ stackLib = s;
+ stackLibTotal++;
+ }
+ return nsh;
+}
+
+//----------------------------------------------------------------------
+// For saving and loading variables...
+//----------------------------------------------------------------------
+bool Variable::save(Common::WriteStream *stream) {
+ stream->writeByte(varType);
+ switch (varType) {
+ case SVT_INT:
+ case SVT_FUNC:
+ case SVT_BUILT:
+ case SVT_FILE:
+ case SVT_OBJTYPE:
+ stream->writeUint32LE(varData.intValue);
+ return true;
+
+ case SVT_STRING:
+ writeString(varData.theString, stream);
+ return true;
+
+ case SVT_STACK:
+ return saveStackRef(varData.theStack, stream);
+
+ case SVT_COSTUME:
+ varData.costumeHandler->save(stream);
+ return false;
+
+ case SVT_ANIM:
+ varData.animHandler->save(stream);
+ return false;
+
+ case SVT_NULL:
+ return false;
+
+ default:
+ fatal("Can't save variables of this type:", (varType < SVT_NUM_TYPES) ? typeName[varType] : "bad ID");
+ }
+ return true;
+}
+
+bool Variable::load(Common::SeekableReadStream *stream) {
+ varType = (VariableType)stream->readByte();
+ switch (varType) {
+ case SVT_INT:
+ case SVT_FUNC:
+ case SVT_BUILT:
+ case SVT_FILE:
+ case SVT_OBJTYPE:
+ varData.intValue = stream->readUint32LE();
+ return true;
+
+ case SVT_STRING:
+ varData.theString = createCString(readString(stream));
+ return true;
+
+ case SVT_STACK:
+ varData.theStack = loadStackRef(stream);
+ return true;
+
+ case SVT_COSTUME:
+ varData.costumeHandler = new Persona;
+ if (!checkNew(varData.costumeHandler))
+ return false;
+ varData.costumeHandler->load(stream);
+ return true;
+
+ case SVT_ANIM:
+ varData.animHandler = new PersonaAnimation;
+ if (!checkNew(varData.animHandler))
+ return false;
+ varData.animHandler->load(stream);
+ return true;
+
+ default:
+ break;
+ }
+ return true;
+}
+
} // End of namespace Sludge
diff --git a/engines/sludge/variable.h b/engines/sludge/variable.h
index 005eb1cd05..1ae2acacc7 100644
--- a/engines/sludge/variable.h
+++ b/engines/sludge/variable.h
@@ -24,6 +24,8 @@
namespace Sludge {
+struct Persona;
+struct PersonaAnimation;
struct Variable;
struct VariableStack;
@@ -46,76 +48,103 @@ struct FastArrayHandler {
struct Variable *fastVariables;
int size;
int timesUsed;
+
+ Variable *fastArrayGetByIndex(uint theIndex);
};
struct StackHandler {
struct VariableStack *first;
struct VariableStack *last;
int timesUsed;
+
+ int getStackSize() const;
+ bool getSavedGamesStack(const Common::String &ext);
};
union VariableData {
signed int intValue;
const char *theString;
StackHandler *theStack;
- struct PersonaAnimation *animHandler;
- struct Persona *costumeHandler;
+ PersonaAnimation *animHandler;
+ Persona *costumeHandler;
FastArrayHandler *fastArray;
};
struct Variable {
VariableType varType;
VariableData varData;
-};
-struct VariableStack {
- Variable thisVar;
- VariableStack *next;
-};
+ Variable() {
+ varType = SVT_NULL;
+ varData.intValue = 0;
+ }
+
+ void unlinkVar();
+ void setVariable(VariableType vT, int value);
+
+ // Copy from another variable
+ bool copyFrom(const Variable &from);
+ bool copyMain(const Variable &from); // without variable unlink
+
+ // Load & save
+ bool save(Common::WriteStream *stream);
+ bool load(Common::SeekableReadStream *stream);
-// Initialisation
+ // Text variable
+ void makeTextVar(const Common::String &txt);
+ bool loadStringToVar(int value);
-#define initVarNew(thisVar) thisVar.varType = SVT_NULL
+ // Animation variable
+ void makeAnimationVariable(PersonaAnimation *i);
+ struct PersonaAnimation *getAnimationFromVar();
-// Setting variables
+ // Custome variable
+ void makeCostumeVariable(Persona *i);
+ struct Persona *getCostumeFromVar();
-void setVariable(Variable &thisVar, VariableType vT, int value);
-bool copyVariable(const Variable &from, Variable &to);
-bool loadStringToVar(Variable &thisVar, int value);
-void newAnimationVariable(Variable &thisVar, struct PersonaAnimation *i);
-void newCostumeVariable(Variable &thisVar, struct Persona *i);
-void makeTextVar(Variable &thisVar, const Common::String &txt);
-void addVariablesInSecond(Variable &var1, Variable &var2);
-void compareVariablesInSecond(const Variable &var1, Variable &var2);
-char *createCString(const Common::String &s);
+ // Fast array variable
+ bool makeFastArrayFromStack(const StackHandler *stacky);
+ bool makeFastArraySize(int size);
-// Misc.
+ // Stack variable
+ bool copyStack(const Variable &from);
-void unlinkVar(Variable &thisVar);
-Common::String getNumberedString(int value);
-Common::String getTextFromAnyVar(const Variable &from);
-struct Persona *getCostumeFromVar(Variable &thisVar);
-struct PersonaAnimation *getAnimationFromVar(Variable &thisVar);
-bool getBoolean(const Variable &from);
-bool getValueType(int &toHere, VariableType vT, const Variable &v);
+ // Add variables
+ void addVariablesInSecond(const Variable &other);
+ void compareVariablesInSecond(const Variable &other);
+ int compareVars(const Variable &other) const;
+
+ // General getters
+ Common::String getTextFromAnyVar() const;
+ bool getBoolean() const;
+ bool getValueType(int &toHere, VariableType vT) const;
+};
+
+struct VariableStack {
+ Variable thisVar;
+ VariableStack *next;
+
+ // Variable getter & setter
+ bool stackSetByIndex(uint, const Variable &);
+ Variable *stackGetByIndex(uint);
+
+ // Find last
+ VariableStack *stackFindLast();
+};
// Stacky stuff
bool addVarToStack(const Variable &va, VariableStack *&thisStack);
bool addVarToStackQuick(Variable &va, VariableStack *&thisStack);
void trimStack(VariableStack *&stack);
-int deleteVarFromStack(const Variable &va, VariableStack *&thisStack,
- bool allOfEm = false);
-VariableStack *stackFindLast(VariableStack *hunt);
-bool copyStack(const Variable &from, Variable &to);
-int stackSize(const StackHandler *me);
-bool stackSetByIndex(VariableStack *, uint, const Variable &);
-Variable *stackGetByIndex(VariableStack *, uint);
-bool getSavedGamesStack(StackHandler *sH, const Common::String &ext);
-
-bool makeFastArrayFromStack(Variable &to, const StackHandler *stacky);
-bool makeFastArraySize(Variable &to, int size);
-Variable *fastArrayGetByIndex(FastArrayHandler *vS, uint theIndex);
+int deleteVarFromStack(const Variable &va, VariableStack *&thisStack, bool allOfEm = false);
+
+// load & save
+void saveStack(VariableStack *vs, Common::WriteStream *stream);
+VariableStack *loadStack(Common::SeekableReadStream *stream, VariableStack **last);
+bool saveStackRef(StackHandler *vs, Common::WriteStream *stream);
+StackHandler *loadStackRef(Common::SeekableReadStream *stream);
+void clearStackLib();
} // End of namespace Sludge
diff --git a/engines/supernova/detection.cpp b/engines/supernova/detection.cpp
index 8e9db14db4..b172b7fa49 100644
--- a/engines/supernova/detection.cpp
+++ b/engines/supernova/detection.cpp
@@ -32,7 +32,7 @@
static const PlainGameDescriptor supernovaGames[] = {
{"msn1", "Mission Supernova 1"},
{"msn2", "Mission Supernova 2"},
- {NULL, NULL}
+ {nullptr, nullptr}
};
namespace Supernova {
@@ -40,7 +40,7 @@ static const ADGameDescription gameDescriptions[] = {
// Mission Supernova 1
{
"msn1",
- NULL,
+ nullptr,
AD_ENTRY1s("msn_data.000", "f64f16782a86211efa919fbae41e7568", 24163),
Common::DE_DEU,
Common::kPlatformDOS,
@@ -49,7 +49,7 @@ static const ADGameDescription gameDescriptions[] = {
},
{
"msn1",
- NULL,
+ nullptr,
AD_ENTRY1s("msn_data.000", "f64f16782a86211efa919fbae41e7568", 24163),
Common::EN_ANY,
Common::kPlatformDOS,
@@ -60,13 +60,22 @@ static const ADGameDescription gameDescriptions[] = {
// Mission Supernova 2
{
"msn2",
- NULL,
+ nullptr,
AD_ENTRY1s("ms2_data.000", "e595610cba4a6d24a763e428d05cc83f", 24805),
Common::DE_DEU,
Common::kPlatformDOS,
ADGF_UNSTABLE,
GUIO1(GUIO_NONE)
},
+ {
+ "msn2",
+ nullptr,
+ AD_ENTRY1s("ms2_data.000", "e595610cba4a6d24a763e428d05cc83f", 24805),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NONE)
+ },
AD_TABLE_END_MARKER
};
@@ -122,7 +131,7 @@ bool SupernovaMetaEngine::createInstance(OSystem *syst, Engine **engine, const A
*engine = new Supernova::SupernovaEngine(syst);
}
- return desc != NULL;
+ return desc != nullptr;
}
SaveStateList SupernovaMetaEngine::listSaves(const char *target) const {
@@ -200,7 +209,11 @@ SaveStateDescriptor SupernovaMetaEngine::querySaveMetaInfos(const char *target,
desc.setPlayTime(playTime * 1000);
if (Graphics::checkThumbnailHeader(*savefile)) {
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*savefile);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*savefile, thumbnail)) {
+ delete savefile;
+ return SaveStateDescriptor();
+ }
desc.setThumbnail(thumbnail);
}
diff --git a/engines/supernova/graphics.cpp b/engines/supernova/graphics.cpp
index 3a29bacacc..9a05a424ca 100644
--- a/engines/supernova/graphics.cpp
+++ b/engines/supernova/graphics.cpp
@@ -28,13 +28,14 @@
#include "graphics/palette.h"
#include "graphics/surface.h"
-#include "graphics.h"
-#include "msn_def.h"
-#include "supernova.h"
+#include "supernova/graphics.h"
+#include "supernova/msn_def.h"
+#include "supernova/screen.h"
+#include "supernova/supernova.h"
namespace Supernova {
-MSNImageDecoder::MSNImageDecoder() {
+MSNImage::MSNImage() {
_palette = nullptr;
_encodedImage = nullptr;
_filenumber = -1;
@@ -43,11 +44,11 @@ MSNImageDecoder::MSNImageDecoder() {
_numClickFields = 0;
}
-MSNImageDecoder::~MSNImageDecoder() {
+MSNImage::~MSNImage() {
destroy();
}
-bool MSNImageDecoder::init(int filenumber) {
+bool MSNImage::init(int filenumber) {
Common::File file;
if (!file.open(Common::String::format("msn_data.%03d", filenumber))) {
warning("Image data file msn_data.%03d could not be read!", filenumber);
@@ -60,7 +61,7 @@ bool MSNImageDecoder::init(int filenumber) {
return true;
}
-bool MSNImageDecoder::loadFromEngineDataFile() {
+bool MSNImage::loadFromEngineDataFile() {
Common::String name;
if (_filenumber == 1)
name = "IMG1";
@@ -102,7 +103,7 @@ bool MSNImageDecoder::loadFromEngineDataFile() {
return false;
}
-bool MSNImageDecoder::loadStream(Common::SeekableReadStream &stream) {
+bool MSNImage::loadStream(Common::SeekableReadStream &stream) {
destroy();
uint size = 0;
@@ -199,7 +200,7 @@ bool MSNImageDecoder::loadStream(Common::SeekableReadStream &stream) {
return true;
}
-bool MSNImageDecoder::loadSections() {
+bool MSNImage::loadSections() {
bool isNewspaper = _filenumber == 1 || _filenumber == 2;
int imageWidth = isNewspaper ? 640 : 320;
int imageHeight = isNewspaper ? 480 : 200;
@@ -238,14 +239,14 @@ bool MSNImageDecoder::loadSections() {
return true;
}
-void MSNImageDecoder::destroy() {
+void MSNImage::destroy() {
if (_palette) {
delete[] _palette;
- _palette = NULL;
+ _palette = nullptr;
}
if (_encodedImage) {
delete[] _encodedImage;
- _encodedImage = NULL;
+ _encodedImage = nullptr;
}
for (Common::Array<Graphics::Surface *>::iterator it = _sectionSurfaces.begin();
it != _sectionSurfaces.end(); ++it) {
diff --git a/engines/supernova/graphics.h b/engines/supernova/graphics.h
index 2a820c9432..058da45ba8 100644
--- a/engines/supernova/graphics.h
+++ b/engines/supernova/graphics.h
@@ -36,10 +36,10 @@ struct Surface;
namespace Supernova {
-class MSNImageDecoder : public Image::ImageDecoder {
+class MSNImage : public Image::ImageDecoder {
public:
- MSNImageDecoder();
- virtual ~MSNImageDecoder();
+ MSNImage();
+ virtual ~MSNImage();
virtual void destroy();
virtual bool loadStream(Common::SeekableReadStream &stream);
diff --git a/engines/supernova/imageid.h b/engines/supernova/imageid.h
new file mode 100644
index 0000000000..7cfa08370e
--- /dev/null
+++ b/engines/supernova/imageid.h
@@ -0,0 +1,654 @@
+/* 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 SUPERNOVA_IMAGEID_H
+#define SUPERNOVA_IMAGEID_H
+
+namespace Supernova {
+
+enum ImageId {
+ // file 0
+ kAxacussanShipBackground,
+ kAxacussanShipCenterMouthOpen,
+ kAxacussanShipRightMouthOpen,
+ // file 1
+ kNewspaper1,
+ // file 2
+ kNewspaper2,
+ // file 3
+ kElevatorBackground,
+ kElevatorGreenButton,
+ kElevatorRedButton,
+ kElevatorDoorAnimation1,
+ kElevatorDoorAnimation2,
+ kElevatorDoorAnimation3,
+ kElevatorDoorAnimation4,
+ kElevatorDoorAnimation5,
+ kElevatorDummy1,
+ kElevatorDummy2,
+ kElevatorDummy3,
+ kElevatorDummy4,
+ // file 4
+ kShipSpaceBackground,
+ kShipSpaceRope,
+ kShipSpaceDummy1,
+ kShipSpaceDummy2,
+ // file 5
+ kBusStationBackground,
+ kBusStationArrived,
+ kBusStationPlantAnimation1,
+ kBusStationPlantAnimation2,
+ kBusStationPlantAnimation3,
+ kBusStationPlantAnimation4,
+ kBusStationPlantAnimation5,
+ kBusStationPlantAnimation6,
+ kBusStationPlantAnimation7,
+ kBusStationDoorOpened,
+ // file 6
+ kOfficesBackground,
+ kOfficesDoorOpenTopLeft,
+ kOfficesDoorOpenBottomLeft,
+ kOfficesDoorOpenTopRight,
+ kOfficesDoorOpenBottomRight,
+ kOfficesAlienCorridorAnimation1,
+ kOfficesAlienCorridorAnimation2,
+ kOfficesAlienCorridorAnimation3,
+ kOfficesAlienCorridorAnimation4,
+ kOfficesAlienCorridorAnimation5,
+ kOfficesAlienCorridorAnimation6,
+ kOfficesAlienTopOfficeAnimation1,
+ kOfficesAlienTopOfficeAnimation2,
+ kOfficesAlienTopOfficeAnimation3,
+ kOfficesAlienTopOfficeAnimation4,
+ kOfficesAlienTopOfficeAnimation5,
+ kOfficesAlienBottomOfficeAnimation1,
+ kOfficesAlienBottomOfficeAnimation2,
+ kOfficesAlienBottomOfficeAnimation3,
+ kOfficesAlienBottomOfficeAnimation4,
+ kOfficesAlienBottomOfficeAnimation5,
+ kOfficesAlienBottom,
+ // file 7
+ kOfficeLeftBackground,
+ kOfficeLeftDecoration,
+ kOfficeLeftMemo,
+ kOfficeLeftGraffiti,
+ kOfficeLeftTerminalSmashed,
+ kOfficeLeftDrawerMoney,
+ kOfficeLeftSafeOpen,
+ kOfficeLeftSafeClosed,
+ kOfficeLeftSafeMoney,
+ kOfficeLeftDoorOpen,
+ kOfficeLeftAlienShootAnimation1,
+ kOfficeLeftAlienShootAnimation2,
+ kOfficeLeftAlienShootAnimation3,
+ kOfficeLeftAlienShootAnimation4,
+ kOfficeLeftAlienShootAnimation5,
+ kOfficeLeftAlienShootAnimation6,
+ kOfficeLeftTerminalText,
+ kOfficeLeftDoorClosed,
+ kOfficeLeftDummy1,
+ kOfficeLeftDummy2,
+ kOfficeLeftDummy3,
+ kOfficeLeftDummy4,
+ kOfficeLeftDummy5,
+ // file 8
+ kOfficeRightBackground,
+ kOfficeRightDecorationPictures,
+ kOfficeRightDecorationPlants,
+ kOfficeRightDoorOpen,
+ kOfficeRightTerminalSmashed,
+ kOfficeRightAlienShootAnimation1,
+ kOfficeRightAlienShootAnimation2,
+ kOfficeRightAlienShootAnimation3,
+ kOfficeRightAlienTalking,
+ kOfficeRightDummy1,
+ kOfficeRightDummy2,
+ kOfficeRightDummy3,
+ kOfficeRightDummy4,
+ // file 9
+ kShipCockpitBackground,
+ kShipCockpitPilotAnimation1,
+ kShipCockpitPilotAnimation2,
+ kShipCockpitPilotAnimation3,
+ kShipCockpitPilotAnimation4,
+ kShipCockpitPilotAnimation5,
+ kShipCockpitPilotAnimation6,
+ kShipCockpitPilotAnimation7,
+ kShipCockpitPilotAnimation8,
+ kShipCockpitPilotAnimation9,
+ kShipCockpitPilotAnimation10,
+ kShipCockpitPilotAnimation11,
+ kShipCockpitPilotAnimation12,
+ kShipCockpitPilotAnimation13,
+ kShipCockpitPilotAnimation14,
+ kShipCockpitPilotAnimation15,
+ kShipCockpitPilotAnimation16,
+ kShipCockpitPilotAnimation17,
+ kShipCockpitPilotAnimation18,
+ kShipCockpitPilotAnimation19,
+ kShipCockpitPilotAnimation20,
+ kShipCockpitDisplayStatusAnimation1,
+ kShipCockpitDisplayStatusAnimation2,
+ kShipCockpitWindowRocks,
+ // file 10
+ kRestaurantEntranceBackground,
+ kRestaurantEntrancePorterAnimation1,
+ kRestaurantEntrancePorterAnimation2,
+ kRestaurantEntrancePorterAnimation3,
+ kRestaurantEntrancePorterAnimation4,
+ kRestaurantEntranceBathroomDoorAnimation1,
+ kRestaurantEntranceBathroomDoorAnimation2,
+ kRestaurantEntranceBathroomDoorAnimation3,
+ kRestaurantEntranceBathroomDoorAnimation4,
+ kRestaurantEntranceBathroomDoorAnimation5,
+ kRestaurantEntranceGreenCandy,
+ kRestaurantEntranceBlueCandy,
+ kRestaurantEntrancePinkCandy,
+ kRestaurantEntranceWhiteCandy,
+ kRestaurantEntranceBlackCandy,
+ kRestaurantEntraceDummy1,
+ kRestaurantEntraceDummy2,
+ // file 11
+ kDeathScreen,
+ // file 12
+ kRocksBackground,
+ kRocksRockAnimation1,
+ kRocksRockAnimation2,
+ kRocksRockAnimation3,
+ // file 13
+ kBluePlanetBackground,
+ kBluePlanetShipAnimation1,
+ kBluePlanetShipAnimation2,
+ kBluePlanetShipAnimation3,
+ kBluePlanetShipAnimation4,
+ kBluePlanetShipAnimation5,
+ kBluePlanetShipAnimation6,
+ kBluePlanetShipAnimation7,
+ kBluePlanetShipAnimation8,
+ kBluePlanetShipAnimation9,
+ kBluePlanetShipAnimation10,
+ kBluePlanetShipAnimation11,
+ kBluePlanetShipAnimation12,
+ kBluePlanetShipAnimation13,
+ // file 14
+ kRogerCrashBackground,
+ kRogerCrashAnimation1,
+ kRogerCrashAnimation2,
+ kRogerCrashAnimation3,
+ kRogerCrashAnimation4,
+ kRogerCrashAnimation5,
+ kRogerCrashAnimation6,
+ kRogerCrashAnimation7,
+ kRogerCrashAnimation8,
+ kRogerCrashAnimation9,
+ kRogerCrashAnimation10,
+ kRogerCrashAnimation11,
+ kRogerCrashAnimation12,
+ kRogerCrashAnimation13,
+ kRogerCrashAnimation14,
+ kRogerCrashAnimation15,
+ kRogerCrashAnimation16,
+ kRogerCrashAnimation17,
+ kRogerCrashAnimation18,
+ kRogerCrashAnimation19,
+ // file 15
+ kShipCorridorBackground,
+ kShipCorridorCockpitDoorOpen,
+ kShipCorridorSleepCabinDoorAnimation1,
+ kShipCorridorSleepCabinDoorAnimation2,
+ kShipCorridorSleepCabinDoorAnimation3,
+ kShipCorridorDummy1,
+ // file 16
+ kAxacussCorridorTileWalled,
+ kAxacussCorridorToLeft,
+ kAxacussCorridorToRight,
+ kAxacussCorridorToTop,
+ kAxacussCorridorToBottom,
+ kAxacussCorridorTile,
+ kAxacussCorridorDoorClosed,
+ kAxacussCorridorDoorOpen,
+ kAxacussCorridorDesk,
+ kAxacussCorridorLaptop,
+ kAxacussCorridorStuff10,
+ kAxacussCorridorStuff11,
+ kAxacussCorridorStuff12,
+ kAxacussCorridorStuff13,
+ kAxacussCorridorStuff14,
+ kAxacussCorridorStuff15,
+ kAxacussCorridorStuff16,
+ kAxacussCorridorStuff17,
+ kAxacussCorridorStuff18,
+ kAxacussCorridorStuff19,
+ kAxacussCorridorStuff21,
+ kAxacussCorridorStuff22,
+ kAxacussCorridorStuff23,
+ kAxacussCorridorStuff24,
+ kAxacussCorridorStuff25,
+ kAxacussCorridorStuff26,
+ kAxacussCorridorStuff27,
+ kAxacussCorridorStuff28,
+ kAxacussCorridorAlarmStatus,
+ kAxacussCorridorAlienRight,
+ kAxacussCorridorAlienLeft,
+ kAxacussCorridorAlienBottom,
+ kAxacussCorridorAlienTop,
+ kAxacussCorridorDummy1,
+ // file 17
+ kShipCorridorCabinBackground,
+ kShipCorridorCabinL1Open,
+ kShipCorridorCabinL2Open,
+ kShipCorridorCabinL3Open,
+ kShipCorridorCabinR1Open,
+ kShipCorridorCabinR2Open,
+ kShipCorridorCabinR3Open,
+ kShipCorridorCabinAirlockDoorAnimation1,
+ kShipCorridorCabinAirlockDoorAnimation2,
+ kShipCorridorCabinAirlockDoorAnimation3,
+ kShipCorridorCabinDummy1,
+ kShipCorridorCabinDummy2,
+ kShipCorridorCabinDummy3,
+ kShipCorridorCabinDummy4,
+ kShipCorridorCabinDummy5,
+ kShipCorridorCabinDummy6,
+ // file 18
+ kShipGeneratorBackground,
+ kShipGeneratorHatchOpen,
+ kShipGeneratorJunctionBoxOpen,
+ kShipGeneratorJunctionBoxOffline,
+ kShipGeneratorJunctionBoxDisplay,
+ kShipGeneratorKeycard,
+ kShipGeneratorSpoolFloating,
+ kShipGeneratorSpoolOnGround,
+ kShipGeneratorCableUnplugged,
+ kShipGeneratorCablePluggedIn,
+ kShipGeneratorHatchRocks,
+ kShipGeneratorRopeRocks,
+ kShipGeneratorRopeSpace,
+ kShipGeneratorRopeFloor,
+ kShipGeneratorDummy1,
+ kShipGeneratorDummy2,
+ kShipGeneratorDummy3,
+ kShipGeneratorDummy4,
+ kShipGeneratorDummy5,
+ kShipGeneratorDummy6,
+ kShipGeneratorDummy7,
+ kShipGeneratorDummy8,
+ // file 19
+ kRogerShipBackground,
+ kRogerShipButtonPressed1,
+ kRogerShipButtonPressed2,
+ kRogerShipButtonPressed3,
+ kRogerShipButtonPressed4,
+ kRogerShipCardInSlot,
+ kRogerShipCompartmentOpen,
+ kRogerShipUnknown7,
+ kRogerShipDisplayLeftOn,
+ kRogerShipGreenDisplayAnimation1,
+ kRogerShipGreenDisplayAnimation2,
+ kRogerShipGreenDisplayAnimation3,
+ kRogerShipGreenDisplayAnimation4,
+ kRogerShipGreenDisplayAnimation5,
+ kRogerShipGreenDisplayAnimation6,
+ kRogerShipGreenDisplayAnimation7,
+ kRogerShipBlueDisplayAnimation1,
+ kRogerShipBlueDisplayAnimation2,
+ kRogerShipBlueDisplayAnimation3,
+ kRogerShipBlueDisplayAnimation4,
+ kRogerShipBlueDisplayAnimation5,
+ kRogerShipBlueDisplayAnimation6,
+ kRogerShipBlueDisplayAnimation7,
+ kRogerShipUnknown23,
+ kRogerShipDisplaySinewaveAnimation1,
+ kRogerShipDisplaySinewaveAnimation2,
+ kRogerShipDisplaySinewaveAnimation3,
+ kRogerShipDisplaySinewaveAnimation4,
+ kRogerShipDisplaySinewaveAnimation5,
+ kRogerShipDisplaySinewaveAnimation6,
+ kRogerShipDisplaySinewaveAnimation7,
+ kRogerShipDisplaySinewaveAnimation8,
+ kRogerShipDisplaySinewaveAnimation9,
+ kRogerShipDisplaySinewaveAnimation10,
+ kRogerShipDisplaySinewaveAnimation11,
+ kRogerShipDisplaySinewaveAnimation12,
+ kRogerShipDisplaySinewaveAnimation13,
+ kRogerShipDisplaySinewaveAnimation14,
+ kRogerShipCompartmentContent,
+ kRogerShipDummy1,
+ kRogerShipDummy2,
+ // file 20
+ kHelpScreen,
+ // file 21
+ kShipCabinLeftBackground,
+ kShipCabinLeftPaintingSunset,
+ kShipCabinLeftPaintingLandscape,
+ kShipCabinLeftPaintingAbstract,
+ kShipCabinLeftTableStuff1,
+ kShipCabinLeftCeilingPencil,
+ kShipCabinLeft3Decoration,
+ kShipCabinLeftSocketPluggedIn,
+ kShipCabinLeftVinyl,
+ kShipCabinLeftTurntable,
+ kShipCabinLeftSocketUnplugged,
+ kShipCabinLeftTurntableCableCut,
+ kShipCabinLeftTurntableCable,
+ kShipCabinLeftTurntableAnimation1,
+ kShipCabinLeftTurntableAnimation2,
+ kShipCabinLeftTurntableAnimation3,
+ kShipCabinLeftTableStuff2,
+ kShipCabinLeftLockerOpen,
+ kShipCabinLeftLockerBooksOpen,
+ kShipCabinLeftLockerSpoolOpen,
+ kShipCabinLeftLockerPistolRemoved,
+ kShipCabinLeftLockerSpoolRemoved,
+ kShipCabinLeftBedSafeOpen,
+ kShipCabinLeftBedSafeEmpty,
+ kShipCabinLeftDoorClosed,
+ kShipCabinLeftTurntableCableSparks,
+ kShipCabinLeftTurntableCableCutEnd,
+ kShipCabinLeftDummy1,
+ kShipCabinLeftDummy2,
+ kShipCabinLeftDummy3,
+ kShipCabinLeftDummy4,
+ kShipCabinLeftDummy5,
+ kShipCabinLeftDummy6,
+ kShipCabinLeftDummy7,
+ kShipCabinLeftDummy8,
+ kShipCabinLeftDummy9,
+ kShipCabinLeftDummy10,
+ kShipCabinLeftDummy11,
+ kShipCabinLeftDummy12,
+ // file 22
+ kShipCabinRightBackground,
+ kShipCabinRightPosterSnowman,
+ kShipCabinRightTableStuff,
+ kShipCabinRightCeilingChess,
+ kShipCabinRightTennisRacket,
+ kShipCabinRightTennisBallsFloating,
+ kShipCabinRightTennisBallsOnGround,
+ kShipCabinRightTableChess,
+ kShipCabinRight2Bed,
+ kShipCabinRightLockerBooksOpen,
+ kShipCabinRightLockerRopeOpen,
+ kShipCabinRightLockerOpen,
+ kShipCabinRightLockerRopeRemoved,
+ kShipCabinRightBedSafeOpen,
+ kShipCabinRightBedSafeEmpty,
+ kShipCabinRightDoorClosed,
+ kShipCabinRightLockerDiscmanRemoved,
+ kShipCabinRightDummy1,
+ kShipCabinRightDummy2,
+ // file 23
+ kShipBathroomBackground,
+ // file 24
+ kShipHoldBackgroundFloating,
+ kShipHoldBackgroundOnGround,
+ kShipHoldLandingModuleDoorOpen,
+ kShipHoldGeneratorHatchOpen,
+ kShipHoldLandingModuleSpool,
+ kShipHoldCableToGeneratorUnplugged,
+ kShipHoldCableToGeneratorPluggedIn,
+ kShipHoldDummy1,
+ kShipHoldDummy2,
+ // file 25
+ kShipLandingModuleBackground,
+ kShipLandingModuleDoorClosed,
+ kShipLandingModuleDisplayLeftOn,
+ kShipLandingModuleCablePluggedIn,
+ kShipLandingModuleCableSpoolConnected,
+ kShipLandingModuleCableToHold,
+ kShipLandingModuleDisplayRightOn,
+ kShipLandingModuleDisplayTop1On,
+ kShipLandingModuleDisplayTop2On,
+ kShipLandingModuleDisplayTop3On,
+ kShipLandingModuleCableWithTerminalStrip,
+ kShipLandingModuleDummy1,
+ kShipLandingModuleDummy2,
+ kShipLandingModuleDummy3,
+ kShipLandingModuleDummy4,
+ kShipLandingModuleDummy5,
+ kShipLandingModuleDummy6,
+ kShipLandingModuleDummy7,
+ kShipLandingModuleDummy8,
+ // file 26
+ kArsanoStar,
+ // file 27
+ kSaveLoadScreen,
+ // file 28
+ kRestaurantBackground,
+ kRestaurantAnimation1,
+ kRestaurantAnimation2,
+ kRestaurantAnimation3,
+ kRestaurantAnimation4,
+ kRestaurantAnimation5,
+ kRestaurantAnimation6,
+ kRestaurantAnimation7,
+ kRestaurantAnimation8,
+ kRestaurantAnimation9,
+ kRestaurantAnimation10,
+ kRestaurantAnimation11,
+ kRestaurantAnimation12,
+ kRestaurantAnimation13,
+ kRestaurantAnimation14,
+ kRestaurantAnimation15,
+ kRestaurantAnimation16,
+ kRestaurantAnimation17,
+ kRestaurantAnimation18,
+ kRestaurantAnimation19,
+ kRestaurantAnimation20,
+ kRestaurantAnimation21,
+ kRestaurantAnimation22,
+ // file 29
+ kRestaurantRogerBackground,
+ kRestaurantRogerEyes1Closed,
+ kRestaurantRogerMouthOpen,
+ kRestaurantRogerPlayingChess,
+ kRestaurantRogerWalletRemoved,
+ kRestaurantRogerHandAnimation1,
+ kRestaurantRogerHandAnimation2,
+ kRestaurantRogerHandAnimation3,
+ kRestaurantRogerHandAnimation4,
+ kRestaurantRogerHandAnimation5,
+ kRestaurantRogerEyes2Closed,
+ kRestaurantRogerChessBoard,
+ kRestaurantRogerEyes2Open,
+ kRestaurantRogerDummy1,
+ // file 30
+ kRogerOutsideBackground,
+ kRogerOutsideMouthOpen,
+ // file 31
+ kIntroScreenBackground,
+ kIntroScreenShipAnimation1,
+ kIntroScreenShipAnimation2,
+ kIntroScreenShipAnimation3,
+ kIntroScreenShipAnimation4,
+ kIntroScreenShipAnimation5,
+ kIntroScreenShipAnimation6,
+ // file 32
+ kBusStationSignBackground,
+ kBusStationSignPrice,
+ kBusStationSignPleaseWait,
+ kBusStationSignPleasantFlight,
+ // file 33
+ kShipSleepCabinBackground,
+ kShipSleepCabinTerminalWarning,
+ kShipSleepCabinTerminal1,
+ kShipSleepCabinTerminal2,
+ kShipSleepCabinStatusLight,
+ kShipSleepCabinTerminal3,
+ // file 34
+ kShipAirlockBackground,
+ kShipAirlockDoorLeftAnimation1,
+ kShipAirlockDoorLeftAnimation2,
+ kShipAirlockDoorLeftAnimation3,
+ kShipAirlockDoorRightAnimation1,
+ kShipAirlockDoorRightAnimation2,
+ kShipAirlockDoorRightAnimation3,
+ kShipAirlockHelmetRemoved,
+ kShipAirlockSpacesuitRemoved,
+ kShipAirlockSupplyRemoved,
+ kShipAirlockDoorLeftButton,
+ kShipAirlockDoorRightButton,
+ kShipAirlockManometerAnimation1,
+ kShipAirlockManometerAnimation2,
+ kShipAirlockManometerAnimation3,
+ kShipAirlockManometerAnimation4,
+ kShipAirlockManometerAnimation5,
+ kShipAirlockManometerAnimation6,
+ // file 35
+ kAxacussSpaceBackground,
+ kAxacussSpaceShipAnimation1,
+ kAxacussSpaceShipAnimation2,
+ kAxacussSpaceShipAnimation3,
+ kAxacussSpaceShipAnimation4,
+ kAxacussSpaceShipAnimation5,
+ kAxacussSpaceShipAnimation6,
+ kAxacussSpaceShipAnimation7,
+ kAxacussSpaceBusAnimation1,
+ kAxacussSpaceBusAnimation2,
+ kAxacussSpaceBusAnimation3,
+ kAxacussSpaceBusAnimation4,
+ kAxacussSpaceBusAnimation5,
+ kAxacussSpaceBusAnimation6,
+ kAxacussSpaceBusAnimation7,
+ kAxacussSpaceBusAnimation8,
+ kAxacussSpaceBusAnimation9,
+ kAxacussSpaceBusAnimation10,
+ kAxacussSpaceBusAnimation11,
+ kAxacussSpaceBusAnimation12,
+ kAxacussSpaceBusAnimation13,
+ kAxacussSpaceBusAnimation14,
+ // file 36
+ kAxacussanCapsuleBackground,
+ kAxacussanCapsuleRobotAnimation1,
+ kAxacussanCapsuleRobotAnimation2,
+ kAxacussanCapsuleRobotAnimation3,
+ kAxacussanCapsuleRobotAnimation4,
+ kAxacussanCapsuleDummy1,
+ // file 37
+ kArsanoMeetupBackground,
+ kArsanoMeetupRestaurantLightAnimation1,
+ kArsanoMeetupRestaurantLightAnimation2,
+ kArsanoMeetupRestaurantLightAnimation3,
+ kArsanoMeetupRestaurantLightAnimation4,
+ kArsanoMeetupRestaurantLightAnimation5,
+ kArsanoMeetupRestaurantDoorAnimation1,
+ kArsanoMeetupRestaurantDoorAnimation2,
+ kArsanoMeetupRestaurantDoorSignAnimation1,
+ kArsanoMeetupRestaurantDoorSignAnimation2,
+ kArsanoMeetupRestaurantDoorSignAnimation3,
+ kArsanoMeetupRestaurantDoorSignAnimation4,
+ kArsanoMeetupRestaurantDoorSignAnimation5,
+ kArsanoMeetupRestaurantSignAnimation1,
+ kArsanoMeetupRestaurantSignAnimation2,
+ kArsanoMeetupRestaurantSignAnimation3,
+ kArsanoMeetupRestaurantSignAnimation4,
+ kArsanoMeetupRestaurantSignAnimation5,
+ kArsanoMeetupRestaurantSignAnimation6,
+ kArsanoMeetupRestaurantSignAnimation7,
+ kArsanoMeetupRestaurantSignAnimation8,
+ kArsanoMeetupRestaurantSignAnimation9,
+ kArsanoMeetupRestaurantSignAnimation10,
+ kArsanoMeetupRestaurantSignAnimation11,
+ kArsanoMeetupRestaurantSignAnimation12,
+ kArsanoMeetupRestaurantSignAnimation13,
+ kArsanoMeetupRestaurantSignAnimation14,
+ // file 38
+ kArsanoAfterNovaBackground,
+ kArsanoAfterNovaRogerShipAnimation1,
+ kArsanoAfterNovaRogerShipAnimation2,
+ kArsanoAfterNovaRogerShipAnimation3,
+ kArsanoAfterNovaRogerShipAnimation4,
+ kArsanoAfterNovaRogerShipAnimation5,
+ kArsanoAfterNovaRogerShipAnimation6,
+ kArsanoAfterNovaRogerShipAnimation7,
+ kArsanoAfterNovaRogerShipAnimation8,
+ kArsanoAfterNovaRogerShipAnimation9,
+ kArsanoAfterNovaRogerShipAnimation10,
+ kArsanoAfterNovaRogerShipAnimation11,
+ kArsanoAfterNovaRoger,
+ // file 39
+ kArsanoDesolate,
+ // file 40
+ kIntersectionBackground,
+ kIntersectionGuardRemoved,
+ kIntersectionGuardMouthOpen,
+ kIntersectionGuardShootAnimation1,
+ kIntersectionGuardShootAnimation2,
+ kIntersectionGuardMouthClosed,
+ kIntersectionDoorOpen,
+ kIntersectoinKeycard,
+ // file 41
+ kInformationDeskBackground,
+ kInformationDeskAlienMouthOpen,
+ kInformationDeskAlienHandMoved,
+ kInformationDeskAlienShoot,
+ // file 42
+ kArtGalleryBackground,
+ kArtGalleryAlienShootAnimation1,
+ kArtGalleryAlienShootAnimation2,
+ kArtGalleryAlienShootAnimation3,
+ kArtGalleryThrowingBlockAnimation1,
+ kArtGalleryThrowingBlockAnimation2,
+ kArtGalleryThrowingBlockAnimation3,
+ kArtGalleryThrowingBlockAnimation4,
+ kArtGalleryThrowingBlockAnimation5,
+ kArtGalleryThrowingBlockAnimation6,
+ kArtGalleryThrowingBlockAnimation7,
+ kArtGalleryDummy1,
+ // file 43
+ kCellBackground,
+ kCellCablePluggedIn,
+ kCellCableUnplugged,
+ kCellCableCutUnplugged,
+ kCellCableCutPluggedIn,
+ kCellCableCutTableUnplugged,
+ kCellCableCutTablePluggedIn,
+ kCellTableTablet,
+ kCellRobotComesAnimation1,
+ kCellRobotComesAnimation2,
+ kCellRobotComesAnimation3,
+ kCellRobotComesAnimation4,
+ kCellRobotComesAnimation5,
+ kCellRobotComesAnimation6,
+ kCellRobotComesAnimation7,
+ kCellRobotComesAnimation8,
+ kCellRobotComesAnimation9,
+ kCellRobotComesAnimation10,
+ kCellRobotComesAnimation11,
+ kCellRobotLeavesAnimation1,
+ kCellRobotLeavesAnimation2,
+ kCellRobotLeavesAnimation3,
+ kCellRobotLeavesAnimation4,
+ kCellRobotLeavesAnimation5,
+ kCellRobotLeavesAnimation6,
+ kCellRobotLeavesAnimation7,
+ kCellRobotLeavesAnimation8,
+ kCellRobotLeavesAnimation9,
+ kCellRobotSparks,
+ kCellRobotBroken,
+ kCellDoorClosed,
+ kCellDummy1
+};
+
+}
+
+#endif
diff --git a/engines/supernova/module.mk b/engines/supernova/module.mk
index 9baf196c7c..722a230cde 100644
--- a/engines/supernova/module.mk
+++ b/engines/supernova/module.mk
@@ -4,9 +4,12 @@ MODULE_OBJS := \
console.o \
detection.o \
graphics.o \
- supernova.o \
+ resman.o \
rooms.o \
- state.o
+ screen.o \
+ sound.o \
+ state.o \
+ supernova.o
MODULE_DIRS += \
engines/supernova
diff --git a/engines/supernova/msn_def.h b/engines/supernova/msn_def.h
index c18baa068c..6ce16b8283 100644
--- a/engines/supernova/msn_def.h
+++ b/engines/supernova/msn_def.h
@@ -25,10 +25,6 @@
namespace Supernova {
-const int kScreenWidth = 320;
-const int kScreenHeight = 200;
-const int kFontWidth = 5;
-const int kFontHeight = 8;
const int kTextSpeed[] = {19, 14, 10, 7, 4};
const int kMsecPerTick = 55;
@@ -50,266 +46,6 @@ enum MessagePosition {
kMessageTop
};
-enum AudioIndex {
- kAudioFoundLocation, // 44|0
- kAudioCrash, // 45|0
- kAudioVoiceHalt, // 46|0
- kAudioGunShot, // 46|2510
- kAudioSmash, // 46|4020
- kAudioVoiceSupernova, // 47|0
- kAudioVoiceYeah, // 47|24010
- kAudioRobotShock, // 48|0
- kAudioRobotBreaks, // 48|2510
- kAudioShock, // 48|10520
- kAudioTurntable, // 48|13530
- kAudioSiren, // 50|0
- kAudioSnoring, // 50|12786
- kAudioRocks, // 51|0
- kAudioDeath, // 53|0
- kAudioAlarm, // 54|0
- kAudioSuccess, // 54|8010
- kAudioSlideDoor, // 54|24020
- kAudioDoorOpen, // 54|30030
- kAudioDoorClose, // 54|31040
- kAudioNumSamples
-};
-
-enum MusicIndex {
- kMusicIntro = 52,
- kMusicOutro = 49
-};
-
-struct AudioInfo {
- int _filenumber;
- int _offsetStart;
- int _offsetEnd;
-};
-
-const int kColorBlack = 0;
-const int kColorWhite25 = 1;
-const int kColorWhite35 = 2;
-const int kColorWhite44 = 3;
-const int kColorWhite99 = 4;
-const int kColorDarkGreen = 5;
-const int kColorGreen = 6;
-const int kColorDarkRed = 7;
-const int kColorRed = 8;
-const int kColorDarkBlue = 9;
-const int kColorBlue = 10;
-const int kColorWhite63 = 11;
-const int kColorLightBlue = 12;
-const int kColorLightGreen = 13;
-const int kColorLightYellow = 14;
-const int kColorLightRed = 15;
-const int kColorCursorTransparent = kColorWhite25;
-
-const byte mouseNormal[64] = {
- 0xff,0x3f,0xff,0x1f,0xff,0x0f,0xff,0x07,
- 0xff,0x03,0xff,0x01,0xff,0x00,0x7f,0x00,
- 0x3f,0x00,0x1f,0x00,0x0f,0x00,0x0f,0x00,
- 0xff,0x00,0x7f,0x18,0x7f,0x38,0x7f,0xfc,
-
- 0x00,0x00,0x00,0x40,0x00,0x60,0x00,0x70,
- 0x00,0x78,0x00,0x7c,0x00,0x7e,0x00,0x7f,
- 0x80,0x7f,0xc0,0x7f,0xe0,0x7f,0x00,0x7e,
- 0x00,0x66,0x00,0x43,0x00,0x03,0x00,0x00
-};
-
-const byte mouseWait[64] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,
- 0x01,0x80,0x01,0x80,0x11,0x88,0x31,0x8c,
- 0x31,0x8c,0x11,0x88,0x01,0x80,0x01,0x80,
- 0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0xfe,0x7f,0xf4,0x2f,0xf4,0x2f,
- 0x14,0x28,0x24,0x24,0x44,0x22,0x84,0x21,
- 0x84,0x21,0xc4,0x23,0xe4,0x27,0x74,0x2e,
- 0x34,0x2c,0x14,0x28,0xfe,0x7f,0x00,0x00
-};
-
-const byte font[][5] = {
- {0x00,0x00,0x00,0xff,0x00},
- {0x5f,0xff,0x00,0x00,0x00},
- {0x03,0x00,0x03,0xff,0x00},
- {0x14,0x7f,0x14,0x7f,0x14},
- {0x24,0x2a,0x7f,0x2a,0x12},
- {0x61,0x10,0x08,0x04,0x43},
- {0x38,0x4e,0x59,0x26,0x50},
- {0x03,0xff,0x00,0x00,0x00},
- {0x3e,0x41,0xff,0x00,0x00},
- {0x41,0x3e,0xff,0x00,0x00},
- {0x10,0x54,0x38,0x54,0x10},
- {0x10,0x10,0x7c,0x10,0x10},
- {0x80,0x40,0xff,0x00,0x00},
- {0x10,0x10,0x10,0x10,0x10},
- {0x40,0xff,0x00,0x00,0x00},
- {0x60,0x10,0x08,0x04,0x03},
-
- {0x3e,0x41,0x41,0x41,0x3e}, /* digits */
- {0x04,0x02,0x7f,0xff,0x00},
- {0x42,0x61,0x51,0x49,0x46},
- {0x22,0x41,0x49,0x49,0x36},
- {0x18,0x14,0x12,0x7f,0x10},
- {0x27,0x45,0x45,0x45,0x39},
- {0x3e,0x49,0x49,0x49,0x32},
- {0x01,0x61,0x19,0x07,0x01},
- {0x36,0x49,0x49,0x49,0x36},
- {0x26,0x49,0x49,0x49,0x3e},
-
- {0x44,0xff,0x00,0x00,0x00},
- {0x80,0x44,0xff,0x00,0x00},
- {0x10,0x28,0x44,0xff,0x00},
- {0x28,0x28,0x28,0x28,0x28},
- {0x44,0x28,0x10,0xff,0x00},
- {0x02,0x01,0x51,0x09,0x06},
- {0x3e,0x41,0x5d,0x5d,0x1e},
-
- {0x7c,0x12,0x11,0x12,0x7c}, /* uppercase letters*/
- {0x7f,0x49,0x49,0x49,0x36},
- {0x3e,0x41,0x41,0x41,0x22},
- {0x7f,0x41,0x41,0x22,0x1c},
- {0x7f,0x49,0x49,0x49,0xff},
- {0x7f,0x09,0x09,0x09,0xff},
- {0x3e,0x41,0x41,0x49,0x3a},
- {0x7f,0x08,0x08,0x08,0x7f},
- {0x41,0x7f,0x41,0xff,0x00},
- {0x20,0x40,0x40,0x3f,0xff},
- {0x7f,0x08,0x14,0x22,0x41},
- {0x7f,0x40,0x40,0x40,0xff},
- {0x7f,0x02,0x04,0x02,0x7f},
- {0x7f,0x02,0x0c,0x10,0x7f},
- {0x3e,0x41,0x41,0x41,0x3e},
- {0x7f,0x09,0x09,0x09,0x06},
- {0x3e,0x41,0x51,0x21,0x5e},
- {0x7f,0x09,0x19,0x29,0x46},
- {0x26,0x49,0x49,0x49,0x32},
- {0x01,0x01,0x7f,0x01,0x01},
- {0x3f,0x40,0x40,0x40,0x3f},
- {0x07,0x18,0x60,0x18,0x07},
- {0x1f,0x60,0x18,0x60,0x1f},
- {0x63,0x14,0x08,0x14,0x63},
- {0x03,0x04,0x78,0x04,0x03},
- {0x61,0x51,0x49,0x45,0x43},
-
- {0x7f,0x41,0x41,0xff,0x00},
- {0x03,0x04,0x08,0x10,0x60},
- {0x41,0x41,0x7f,0xff,0x00},
- {0x02,0x01,0x02,0xff,0x00},
- {0x80,0x80,0x80,0x80,0x80},
- {0x01,0x02,0xff,0x00,0x00},
-
- {0x38,0x44,0x44,0x44,0x7c}, /* lowercase letters */
- {0x7f,0x44,0x44,0x44,0x38},
- {0x38,0x44,0x44,0x44,0x44},
- {0x38,0x44,0x44,0x44,0x7f},
- {0x38,0x54,0x54,0x54,0x58},
- {0x04,0x7e,0x05,0x01,0xff},
- {0x98,0xa4,0xa4,0xa4,0x7c},
- {0x7f,0x04,0x04,0x04,0x78},
- {0x7d,0xff,0x00,0x00,0x00},
- {0x80,0x80,0x7d,0xff,0x00},
- {0x7f,0x10,0x28,0x44,0xff},
- {0x7f,0xff,0x00,0x00,0x00},
- {0x7c,0x04,0x7c,0x04,0x78},
- {0x7c,0x04,0x04,0x04,0x78},
- {0x38,0x44,0x44,0x44,0x38},
- {0xfc,0x24,0x24,0x24,0x18},
- {0x18,0x24,0x24,0x24,0xfc},
- {0x7c,0x08,0x04,0x04,0xff},
- {0x48,0x54,0x54,0x54,0x24},
- {0x04,0x3e,0x44,0x40,0xff},
- {0x7c,0x40,0x40,0x40,0x3c},
- {0x0c,0x30,0x40,0x30,0x0c},
- {0x3c,0x40,0x3c,0x40,0x3c},
- {0x44,0x28,0x10,0x28,0x44},
- {0x9c,0xa0,0xa0,0xa0,0x7c},
- {0x44,0x64,0x54,0x4c,0x44},
-
- {0x08,0x36,0x41,0xff,0x00},
- {0x77,0xff,0x00,0x00,0x00},
- {0x41,0x36,0x08,0xff,0x00},
- {0x02,0x01,0x02,0x01,0xff},
- {0xff,0x00,0x00,0x00,0x00},
-
- {0xfe,0x49,0x49,0x4e,0x30}, /* sharp S */
-
- {0x7c,0x41,0x40,0x41,0x3c}, /* umlauts */
-
- {0x04,0x06,0x7f,0x06,0x04}, /* arrows */
- {0x20,0x60,0xfe,0x60,0x20},
-
- {0x38,0x45,0x44,0x45,0x7c}, /* umlauts */
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0x79,0x14,0x12,0x14,0x79},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0x38,0x45,0x44,0x45,0x38},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0xff,0x00,0x00,0x00,0x00},
- {0x3d,0x42,0x42,0x42,0x3d},
- {0x3d,0x40,0x40,0x40,0x3d},
-};
-
-// Default palette
-const byte initVGAPalette[768] = {
- 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x58, 0x58, 0x58, 0x70, 0x70, 0x70, 0xfc, 0xfc, 0xfc, 0x00, 0xd0, 0x00,
- 0x00, 0xfc, 0x00, 0xd8, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xb0, 0xa0, 0xa0, 0xa0,
- 0x50, 0xc8, 0xfc, 0x28, 0xfc, 0x28, 0xf0, 0xf0, 0x00, 0xfc, 0x28, 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14,
- 0x20, 0x20, 0x20, 0x2c, 0x2c, 0x2c, 0x38, 0x38, 0x38, 0x44, 0x44, 0x44, 0x50, 0x50, 0x50, 0x60, 0x60, 0x60,
- 0x70, 0x70, 0x70, 0x80, 0x80, 0x80, 0x90, 0x90, 0x90, 0xa0, 0xa0, 0xa0, 0xb4, 0xb4, 0xb4, 0xc8, 0xc8, 0xc8,
- 0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc,
- 0xfc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00,
- 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00,
- 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc,
- 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc,
- 0xfc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c,
- 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c,
- 0x7c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc,
- 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc,
- 0xfc, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4,
- 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4,
- 0xb4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc,
- 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70,
- 0x70, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00,
- 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00,
- 0x00, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70,
- 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70,
- 0x70, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38,
- 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38,
- 0x38, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70,
- 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70,
- 0x70, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50,
- 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50,
- 0x50, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70,
- 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40,
- 0x40, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00,
- 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00,
- 0x00, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40,
- 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40,
- 0x40, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20,
- 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20,
- 0x20, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40,
- 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40,
- 0x40, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c,
- 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c,
- 0x2c, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40,
- 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
enum ObjectType {
NULLTYPE = 0,
TAKE = 1,
@@ -341,7 +77,7 @@ enum Action {
ACTION_GIVE
};
-enum RoomID {
+enum RoomId {
INTRO,CORRIDOR,HALL,SLEEP,COCKPIT,AIRLOCK,
HOLD,LANDINGMODULE,GENERATOR,OUTSIDE,
CABIN_R1,CABIN_R2,CABIN_R3,CABIN_L1,CABIN_L2,CABIN_L3,BATHROOM,
@@ -353,7 +89,7 @@ enum RoomID {
ELEVATOR,STATION,SIGN,OUTRO,NUMROOMS,NULLROOM
};
-enum ObjectID {
+enum ObjectId {
INVALIDOBJECT = -1,
NULLOBJECT = 0,
KEYCARD,KNIFE,WATCH,
@@ -397,7 +133,7 @@ enum ObjectID {
JUNGLE,STATION_SLOT,STATION_SIGN
};
-enum StringID {
+enum StringId {
kNoString = -1,
// 0
kStringCommandGo = 0, kStringCommandLook, kStringCommandTake, kStringCommandOpen, kStringCommandClose,
@@ -568,8 +304,6 @@ ObjectType &operator&=(ObjectType &a, ObjectType b);
ObjectType &operator^=(ObjectType &a, ObjectType b);
struct Object {
- static const Object nullObject;
-
Object()
: _name(kNoString)
, _description(kStringDefaultDescription)
@@ -582,8 +316,8 @@ struct Object {
, _exitRoom(NULLROOM)
, _direction(0)
{}
- Object(byte roomId, StringID name, StringID description, ObjectID id, ObjectType type,
- byte click, byte click2, byte section = 0, RoomID exitRoom = NULLROOM, byte direction = 0)
+ Object(byte roomId, StringId name, StringId description, ObjectId id, ObjectType type,
+ byte click, byte click2, byte section = 0, RoomId exitRoom = NULLROOM, byte direction = 0)
: _name(name)
, _description(description)
, _id(id)
@@ -596,12 +330,6 @@ struct Object {
, _direction(direction)
{}
- static void setObjectNull(Object *&obj) {
- obj = const_cast<Object *>(&nullObject);
- }
- static bool isNullObject(Object *obj) {
- return obj == &nullObject;
- }
void resetProperty(ObjectType type = NULLTYPE) {
_type = type;
}
@@ -618,7 +346,7 @@ struct Object {
return _type & type;
}
- static bool combine(Object &obj1, Object &obj2, ObjectID id1, ObjectID id2) {
+ static bool combine(Object &obj1, Object &obj2, ObjectId id1, ObjectId id2) {
if (obj1.hasProperty(COMBINABLE))
return (((obj1._id == id1) && (obj2._id == id2)) ||
((obj1._id == id2) && (obj2._id == id1)));
@@ -627,14 +355,14 @@ struct Object {
}
byte _roomId;
- StringID _name;
- StringID _description;
- ObjectID _id;
+ StringId _name;
+ StringId _description;
+ ObjectId _id;
ObjectTypes _type;
byte _click;
byte _click2;
byte _section;
- RoomID _exitRoom;
+ RoomId _exitRoom;
byte _direction;
};
diff --git a/engines/supernova/resman.cpp b/engines/supernova/resman.cpp
new file mode 100644
index 0000000000..1c178846ed
--- /dev/null
+++ b/engines/supernova/resman.cpp
@@ -0,0 +1,395 @@
+/* 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 "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+#include "audio/mixer.h"
+#include "audio/mods/protracker.h"
+#include "common/memstream.h"
+#include "common/system.h"
+#include "graphics/cursorman.h"
+#include "graphics/palette.h"
+
+#include "supernova/graphics.h"
+#include "supernova/resman.h"
+#include "supernova/screen.h"
+#include "supernova/supernova.h"
+
+namespace Supernova {
+
+struct AudioInfo {
+ int _filenumber;
+ int _offsetStart;
+ int _offsetEnd;
+};
+
+static Common::MemoryReadStream *convertToMod(const char *filename, int version = 1);
+
+static const AudioInfo audioInfo[kAudioNumSamples] = {
+ {44, 0, -1},
+ {45, 0, -1},
+ {46, 0, 2510},
+ {46, 2510, 4020},
+ {46, 4020, -1},
+ {47, 0, 24010},
+ {47, 24010, -1},
+ {48, 0, 2510},
+ {48, 2510, 10520},
+ {48, 10520, 13530},
+ {48, 13530, -1},
+ {50, 0, 12786},
+ {50, 12786, -1},
+ {51, 0, -1},
+ {53, 0, -1},
+ {54, 0, 8010},
+ {54, 8010, 24020},
+ {54, 24020, 30030},
+ {54, 30030, 31040},
+ {54, 31040, -1}
+};
+
+static const byte mouseNormal[64] = {
+ 0xff,0x3f,0xff,0x1f,0xff,0x0f,0xff,0x07,
+ 0xff,0x03,0xff,0x01,0xff,0x00,0x7f,0x00,
+ 0x3f,0x00,0x1f,0x00,0x0f,0x00,0x0f,0x00,
+ 0xff,0x00,0x7f,0x18,0x7f,0x38,0x7f,0xfc,
+
+ 0x00,0x00,0x00,0x40,0x00,0x60,0x00,0x70,
+ 0x00,0x78,0x00,0x7c,0x00,0x7e,0x00,0x7f,
+ 0x80,0x7f,0xc0,0x7f,0xe0,0x7f,0x00,0x7e,
+ 0x00,0x66,0x00,0x43,0x00,0x03,0x00,0x00
+};
+
+static const byte mouseWait[64] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,
+ 0x01,0x80,0x01,0x80,0x11,0x88,0x31,0x8c,
+ 0x31,0x8c,0x11,0x88,0x01,0x80,0x01,0x80,
+ 0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0xfe,0x7f,0xf4,0x2f,0xf4,0x2f,
+ 0x14,0x28,0x24,0x24,0x44,0x22,0x84,0x21,
+ 0x84,0x21,0xc4,0x23,0xe4,0x27,0x74,0x2e,
+ 0x34,0x2c,0x14,0x28,0xfe,0x7f,0x00,0x00
+};
+
+
+ResourceManager::ResourceManager()
+ : _audioRate(11931) {
+ initSoundFiles();
+ initGraphics();
+}
+
+void ResourceManager::initSoundFiles() {
+ // Sound
+ // Note:
+ // - samples start with a header of 6 bytes: 01 SS SS 00 AD 00
+ // where SS SS (LE uint16) is the size of the sound sample + 2
+ // - samples end with a footer of 4 bytes: 00 00
+ // Skip those in the buffer
+ Common::File file;
+
+ for (int i = 0; i < kAudioNumSamples; ++i) {
+ if (!file.open(Common::String::format("msn_data.%03d", audioInfo[i]._filenumber))) {
+ error("File %s could not be read!", file.getName());
+ }
+
+ int length = 0;
+ byte *buffer = nullptr;
+
+ if (audioInfo[i]._offsetEnd == -1) {
+ file.seek(0, SEEK_END);
+ length = file.pos() - audioInfo[i]._offsetStart - 10;
+ } else {
+ length = audioInfo[i]._offsetEnd - audioInfo[i]._offsetStart - 10;
+ }
+ buffer = new byte[length];
+ file.seek(audioInfo[i]._offsetStart + 6);
+ file.read(buffer, length);
+ file.close();
+
+ byte streamFlag = Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN;
+ _soundSamples[i].reset(Audio::makeRawStream(buffer, length, _audioRate,
+ streamFlag, DisposeAfterUse::YES));
+ }
+
+ _musicIntroBuffer.reset(convertToMod("msn_data.052"));
+ _musicOutroBuffer.reset(convertToMod("msn_data.049"));
+}
+
+void ResourceManager::initGraphics() {
+ Screen::initPalette();
+ initCursorGraphics();
+ initImages();
+}
+
+void ResourceManager::initCursorGraphics() {
+ const uint16 *bufferNormal = reinterpret_cast<const uint16 *>(mouseNormal);
+ const uint16 *bufferWait = reinterpret_cast<const uint16 *>(mouseWait);
+ for (uint i = 0; i < sizeof(mouseNormal) / 4; ++i) {
+ for (uint bit = 0; bit < 16; ++bit) {
+ uint mask = 0x8000 >> bit;
+ uint bitIndex = i * 16 + bit;
+
+ _cursorNormal[bitIndex] = (READ_LE_UINT16(bufferNormal + i) & mask) ?
+ kColorCursorTransparent : kColorBlack;
+ if (READ_LE_UINT16(bufferNormal + i + 16) & mask)
+ _cursorNormal[bitIndex] = kColorLightRed;
+
+ _cursorWait[bitIndex] = (READ_LE_UINT16(bufferWait + i) & mask) ?
+ kColorCursorTransparent : kColorBlack;
+ if (READ_LE_UINT16(bufferWait + i + 16) & mask)
+ _cursorWait[bitIndex] = kColorLightRed;
+ }
+ }
+}
+
+void ResourceManager::initImages() {
+ for (int i = 0; i < kNumImageFiles; ++i) {
+ if (!_images[i].init(i))
+ error("Failed reading image file msn_data.%03d", i);
+ }
+}
+
+Audio::SeekableAudioStream *ResourceManager::getSoundStream(AudioId index) {
+ Audio::SeekableAudioStream *stream = _soundSamples[index].get();
+ stream->rewind();
+
+ return stream;
+}
+
+Audio::AudioStream *ResourceManager::getSoundStream(MusicId index) {
+ switch (index) {
+ case kMusicIntro:
+ _musicIntro.reset(Audio::makeProtrackerStream(_musicIntroBuffer.get()));
+ return _musicIntro.get();
+ case kMusicOutro:
+ _musicOutro.reset(Audio::makeProtrackerStream(_musicOutroBuffer.get()));
+ return _musicOutro.get();
+ default:
+ error("Invalid music constant in playAudio()");
+ }
+}
+
+const MSNImage *ResourceManager::getImage(int filenumber) const {
+ assert(filenumber < kNumImageFiles);
+
+ return &_images[filenumber];
+}
+
+const byte *ResourceManager::getImage(CursorId id) const {
+ switch (id) {
+ case kCursorNormal:
+ return _cursorNormal;
+ case kCursorWait:
+ return _cursorWait;
+ default:
+ return nullptr;
+ }
+}
+
+static Common::MemoryReadStream *convertToMod(const char *filename, int version) {
+ // MSN format
+ struct {
+ uint16 seg;
+ uint16 start;
+ uint16 end;
+ uint16 loopStart;
+ uint16 loopEnd;
+ char volume;
+ char dummy[5];
+ } instr2[22];
+ int nbInstr2; // 22 for version1, 15 for version 2
+ int16 songLength;
+ char arrangement[128];
+ int16 patternNumber;
+ int32 note2[28][64][4];
+
+ nbInstr2 = ((version == 1) ? 22 : 15);
+
+ Common::File msnFile;
+ msnFile.open(filename);
+ if (!msnFile.isOpen()) {
+ warning("Data file '%s' not found", msnFile.getName());
+ return nullptr;
+ }
+
+ for (int i = 0 ; i < nbInstr2 ; ++i) {
+ instr2[i].seg = msnFile.readUint16LE();
+ instr2[i].start = msnFile.readUint16LE();
+ instr2[i].end = msnFile.readUint16LE();
+ instr2[i].loopStart = msnFile.readUint16LE();
+ instr2[i].loopEnd = msnFile.readUint16LE();
+ instr2[i].volume = msnFile.readByte();
+ msnFile.read(instr2[i].dummy, 5);
+ }
+ songLength = msnFile.readSint16LE();
+ msnFile.read(arrangement, 128);
+ patternNumber = msnFile.readSint16LE();
+ for (int p = 0 ; p < patternNumber ; ++p) {
+ for (int n = 0 ; n < 64 ; ++n) {
+ for (int k = 0 ; k < 4 ; ++k) {
+ note2[p][n][k] = msnFile.readSint32LE();
+ }
+ }
+ }
+
+ /* MOD format */
+ struct {
+ char iname[22];
+ uint16 length;
+ char finetune;
+ char volume;
+ uint16 loopStart;
+ uint16 loopLength;
+ } instr[31];
+ int32 note[28][64][4];
+
+ // We can't recover some MOD effects since several of them are mapped to 0.
+ // Assume the MSN effect of value 0 is Arpeggio (MOD effect of value 0).
+ const char invConvEff[8] = {0, 1, 2, 3, 10, 12, 13 ,15};
+
+ // Reminder from convertToMsn
+ // 31 30 29 28 27 26 25 24 - 23 22 21 20 19 18 17 16 - 15 14 13 12 11 10 09 08 - 07 06 05 04 03 02 01 00
+ // h h h h g g g g f f f f e e e e d d d d c c c c b b b b a a a a
+ //
+ // MSN:
+ // hhhh (4 bits) Cleared to 0
+ // dddd c (5 bits) Sample index | after mapping through convInstr
+ // ccc (3 bits) Effect type | after mapping through convEff
+ // bbbb aaaa (8 bits) Effect value | unmodified
+ // gggg ffff eeee (12 bits) Sample period | unmodified
+ //
+ // MS2:
+ // hhhh (4 bits) Cleared to 0
+ // dddd (4 bits) Sample index | after mapping through convInstr
+ // cccc (4 bits) Effect type | unmodified
+ // bbbb aaaa (8 bits) Effect value | unmodified
+ // gggg ffff eeee (12 bits) Sample period | transformed (0xE000 / p) - 256
+ //
+ // MOD:
+ // hhhh dddd (8 bits) Sample index
+ // cccc (4 bits) Effect type for this channel/division
+ // bbbb aaaa (8 bits) Effect value
+ // gggg ffff eeee (12 bits) Sample period
+
+ // Can we recover the instruments mapping? I don't think so as part of the original instrument index is cleared.
+ // And it doesn't really matter as long as we are consistent.
+ // However we need to make sure 31 (or 15 in MS2) is mapped to 0 in MOD.
+ // We just add 1 to all other values, and this means a 1 <-> 1 mapping for the instruments
+ for (int p = 0; p < patternNumber; ++p) {
+ for (int n = 0; n < 64; ++n) {
+ for (int k = 0; k < 4; ++k) {
+ int32* l = &(note[p][n][k]);
+ *l = note2[p][n][k];
+ int32 i = 0;
+ if (nbInstr2 == 22) { // version 1
+ i = ((*l & 0xF800) >> 11);
+ int32 e = ((*l & 0x0700) >> 8);
+ int32 e1 = invConvEff[e];
+ *l &= 0x0FFF00FF;
+ *l |= (e1 << 8);
+ } else { // version 2
+ int32 h = (*l >> 16);
+ i = ((*l & 0xF000) >> 12);
+ *l &= 0x00000FFF;
+ if (h)
+ h = 0xE000 / (h + 256);
+ *l |= (h << 16);
+ if (i == 15)
+ i = 31;
+ }
+
+ // Add back index in note
+ if (i != 31) {
+ ++i;
+ *l |= ((i & 0x0F) << 12);
+ *l |= ((i & 0xF0) << 24);
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < 31; ++i) {
+ // iname is not stored in the mod file. Just set it to 'instrument#'
+ // finetune is not stored either. Assume 0.
+ memset(instr[i].iname, 0, 22);
+ sprintf(instr[i].iname, "instrument%d", i+1);
+ instr[i].length = 0;
+ instr[i].finetune = 0;
+ instr[i].volume = 0;
+ instr[i].loopStart = 0;
+ instr[i].loopLength = 0;
+
+ if (i < nbInstr2) {
+ instr[i].length = ((instr2[i].end - instr2[i].start) >> 1);
+ instr[i].loopStart = ((instr2[i].loopStart - instr2[i].start) >> 1);
+ instr[i].loopLength = (( instr2[i].loopEnd - instr2[i].loopStart) >> 1);
+ instr[i].volume = instr2[i].volume;
+ }
+ }
+
+ // The ciaaSpeed is kind of useless and not present in the MSN file.
+ // Traditionally 0x78 in SoundTracker. Was used in NoiseTracker as a restart point.
+ // ProTracker uses 0x7F. FastTracker uses it as a restart point, whereas ScreamTracker 3 uses 0x7F like ProTracker.
+ // You can use this to roughly detect which tracker made a MOD, and detection gets more accurate for more obscure MOD types.
+ char ciaaSpeed = 0x7F;
+
+ // The mark cannot be recovered either. Since we have 4 channels and 31 instrument it can be either ID='M.K.' or ID='4CHN'.
+ // Assume 'M.K.'
+ const char mark[4] = { 'M', '.', 'K', '.' };
+
+ Common::MemoryWriteStreamDynamic buffer(DisposeAfterUse::NO);
+
+ buffer.write(msnFile.getName(), 19);
+ buffer.writeByte(0);
+
+ for (int i = 0 ; i < 31 ; ++i) {
+ buffer.write(instr[i].iname, 22);
+ buffer.writeUint16BE(instr[i].length);
+ buffer.writeByte(instr[i].finetune);
+ buffer.writeByte(instr[i].volume);
+ buffer.writeUint16BE(instr[i].loopStart);
+ buffer.writeUint16BE(instr[i].loopLength);
+ }
+ buffer.writeByte((char)songLength);
+ buffer.writeByte(ciaaSpeed);
+ buffer.write(arrangement, 128);
+ buffer.write(mark, 4);
+
+ for (int p = 0 ; p < patternNumber ; ++p) {
+ for (int n = 0 ; n < 64 ; ++n) {
+ for (int k = 0 ; k < 4 ; ++k) {
+// buffer.writeUint32BE(*((uint32*)(note[p][n]+k)));
+ buffer.writeSint32BE(note[p][n][k]);
+ }
+ }
+ }
+
+ uint nb;
+ char buf[4096];
+ while ((nb = msnFile.read(buf, 4096)) > 0)
+ buffer.write(buf, nb);
+
+ return new Common::MemoryReadStream(buffer.getData(), buffer.size(), DisposeAfterUse::YES);
+}
+
+}
diff --git a/engines/supernova/resman.h b/engines/supernova/resman.h
new file mode 100644
index 0000000000..080ecc5da4
--- /dev/null
+++ b/engines/supernova/resman.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.
+*
+*/
+
+#ifndef SUPERNOVA_RESOURCES_H
+#define SUPERNOVA_RESOURCES_H
+
+#include "audio/audiostream.h"
+#include "common/ptr.h"
+
+#include "supernova/graphics.h"
+#include "supernova/sound.h"
+
+
+namespace Common {
+class MemoryReadStream;
+}
+
+namespace Supernova {
+
+class ResourceManager {
+public:
+ enum CursorId {
+ kCursorNormal,
+ kCursorWait
+ };
+
+public:
+ static const int kNumImageFiles = 44;
+
+public:
+ ResourceManager();
+
+ Audio::SeekableAudioStream *getSoundStream(AudioId index);
+ Audio::AudioStream *getSoundStream(MusicId index);
+ const MSNImage *getImage(int filenumber) const;
+ const byte *getImage(CursorId id) const;
+
+private:
+ void initSoundFiles();
+ void initGraphics();
+ void initCursorGraphics();
+ void initImages();
+
+private:
+ Common::ScopedPtr<Audio::SeekableAudioStream> _soundSamples[kAudioNumSamples];
+ Common::ScopedPtr<Common::MemoryReadStream> _musicIntroBuffer;
+ Common::ScopedPtr<Common::MemoryReadStream> _musicOutroBuffer;
+ Common::ScopedPtr<Audio::AudioStream> _musicIntro;
+ Common::ScopedPtr<Audio::AudioStream> _musicOutro;
+ int _audioRate;
+ MSNImage _images[kNumImageFiles];
+ byte _cursorNormal[256];
+ byte _cursorWait[256];
+};
+
+}
+
+#endif
diff --git a/engines/supernova/rooms.cpp b/engines/supernova/rooms.cpp
index faa6129723..9360d58aa1 100644
--- a/engines/supernova/rooms.cpp
+++ b/engines/supernova/rooms.cpp
@@ -24,6 +24,7 @@
#include "graphics/palette.h"
#include "graphics/cursorman.h"
+#include "supernova/screen.h"
#include "supernova/supernova.h"
#include "supernova/state.h"
@@ -79,15 +80,15 @@ bool Room::deserialize(Common::ReadStream *in, int version) {
int numObjects = in->readSint32LE();
for (int i = 0; i < numObjects; ++i) {
- _objectState[i]._name = static_cast<StringID>(in->readSint32LE());
- _objectState[i]._description = static_cast<StringID>(in->readSint32LE());
+ _objectState[i]._name = static_cast<StringId>(in->readSint32LE());
+ _objectState[i]._description = static_cast<StringId>(in->readSint32LE());
_objectState[i]._roomId = in->readByte();
- _objectState[i]._id = static_cast<ObjectID>(in->readSint32LE());
+ _objectState[i]._id = static_cast<ObjectId>(in->readSint32LE());
_objectState[i]._type = static_cast<ObjectType>(in->readSint32LE());
_objectState[i]._click = in->readByte();
_objectState[i]._click2 = in->readByte();
_objectState[i]._section = in->readByte();
- _objectState[i]._exitRoom = static_cast<RoomID>(in->readSint32LE());
+ _objectState[i]._exitRoom = static_cast<RoomId>(in->readSint32LE());
_objectState[i]._direction = in->readByte();
}
@@ -147,102 +148,11 @@ void Intro::onEntrance() {
leaveCutscene();
}
-class Marquee {
-public:
- enum MarqueeIndex {
- kMarqueeIntro,
- kMarqueeOutro
- };
-
- Marquee(SupernovaEngine *vm, MarqueeIndex id, const char *text)
- : _text(text)
- , _textBegin(text)
- , _delay(0)
- , _color(kColorLightBlue)
- , _loop(false)
- , _vm(vm)
- {
- if (id == kMarqueeIntro) {
- _y = 191;
- _loop = true;
- } else if (id == kMarqueeOutro) {
- _y = 1;
- }
- _textWidth = _vm->textWidth(_text);
- _x = kScreenWidth / 2 - _textWidth / 2;
- _vm->_textCursorX = _x;
- _vm->_textCursorY = _y;
- _vm->_textColor = _color;
- }
-
- void renderCharacter();
-
-private:
- void clearText();
-
- SupernovaEngine *_vm;
- MarqueeIndex _id;
- const char *const _textBegin;
- const char *_text;
- bool _loop;
- int _delay;
- int _color;
- int _x;
- int _y;
- int _textWidth;
-};
-
-void Marquee::clearText() {
- _vm->renderBox(_x, _y - 1, _textWidth + 1, 9, kColorBlack);
-}
-
-void Marquee::renderCharacter() {
- if (_delay != 0) {
- _delay--;
- return;
- }
-
- switch (*_text) {
- case '\233':
- if (_loop) {
- _loop = false;
- _text = _textBegin;
- clearText();
- _textWidth = _vm->textWidth(_text);
- _x = kScreenWidth / 2 - _textWidth / 2;
- _vm->_textCursorX = _x;
- }
- break;
- case '\0':
- clearText();
- _text++;
- _textWidth = _vm->textWidth(_text);
- _x = kScreenWidth / 2 - _textWidth / 2;
- _vm->_textCursorX = _x;
- _color = kColorLightBlue;
- _vm->_textColor = _color;
- break;
- case '^':
- _color = kColorLightYellow;
- _vm->_textColor = _color;
- _text++;
- break;
- case '#':
- _delay = 50;
- _text++;
- break;
- default:
- _vm->renderText((uint16)*_text++);
- _delay = 1;
- break;
- }
-}
-
void Intro::titleScreen() {
// Newspaper
CursorMan.showMouse(false);
- _vm->_brightness = 0;
- _vm->_menuBrightness = 0;
+ _vm->_screen->setViewportBrightness(0);
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
_vm->setCurrentImage(1);
_vm->renderImage(0);
@@ -254,25 +164,25 @@ void Intro::titleScreen() {
_vm->setCurrentImage(31);
_vm->renderImage(0);
_vm->paletteFadeIn();
- _gm->wait2(1);
+ _gm->wait(1);
_vm->playSound(kAudioVoiceSupernova);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
titleFadeIn();
_vm->renderText(kStringTitleVersion, 295, 190, kColorWhite44);
const Common::String& title1 = _vm->getGameString(kStringTitle1);
const Common::String& title2 = _vm->getGameString(kStringTitle2);
const Common::String& title3 = _vm->getGameString(kStringTitle3);
- _vm->renderText(title1, 78 - _vm->textWidth(title1) / 2, 120, kColorLightBlue);
- _vm->renderText(title2, 78 - _vm->textWidth(title2) / 2, 132, kColorWhite99);
- _vm->renderText(title3, 78 - _vm->textWidth(title3) / 2, 142, kColorWhite99);
- _gm->wait2(1);
+ _vm->_screen->renderText(title1, 78 - Screen::textWidth(title1) / 2, 120, kColorLightBlue);
+ _vm->_screen->renderText(title2, 78 - Screen::textWidth(title2) / 2, 132, kColorWhite99);
+ _vm->_screen->renderText(title3, 78 - Screen::textWidth(title3) / 2, 142, kColorWhite99);
+ _gm->wait(1);
CursorMan.showMouse(true);
- _vm->playSoundMod(kMusicIntro);
+ _vm->playSound(kMusicIntro);
- Marquee marquee(_vm, Marquee::kMarqueeIntro, _introText.c_str());
+ Marquee marquee(_vm->_screen, Marquee::kMarqueeIntro, _introText.c_str());
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ _gm->updateEvents();
marquee.renderCharacter();
if (_gm->_mouseClicked || _gm->_keyPressed)
break;
@@ -280,8 +190,8 @@ void Intro::titleScreen() {
g_system->delayMillis(_vm->_delay);
}
_vm->playSound(kAudioVoiceYeah);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
_vm->paletteFadeOut();
}
@@ -319,7 +229,7 @@ bool Intro::animate(int section1, int section2, int duration) {
}
bool Intro::animate(int section1, int section2, int duration,
- MessagePosition position, StringID textId) {
+ MessagePosition position, StringId textId) {
Common::KeyCode key = Common::KEYCODE_INVALID;
const Common::String& text = _vm->getGameString(textId);
_vm->renderMessage(text, position);
@@ -344,7 +254,7 @@ bool Intro::animate(int section1, int section2, int duration,
}
bool Intro::animate(int section1, int section2, int section3, int section4,
- int duration, MessagePosition position, StringID textId) {
+ int duration, MessagePosition position, StringId textId) {
Common::KeyCode key = Common::KEYCODE_INVALID;
const Common::String& text = _vm->getGameString(textId);
_vm->renderMessage(text, position);
@@ -381,11 +291,11 @@ void Intro::cutscene() {
_vm->_system->fillScreen(kColorBlack);
_vm->setCurrentImage(31);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
if (!animate(0, 0, 0, kMessageNormal, kStringIntroCutscene1))
return;
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
exitOnEscape(1);
@@ -423,7 +333,7 @@ void Intro::cutscene() {
exitOnEscape(28);
_vm->removeMessage();
- StringID textCounting[4] =
+ StringId textCounting[4] =
{kStringIntroCutscene7, kStringIntroCutscene8, kStringIntroCutscene9, kStringIntroCutscene10};
_vm->setCurrentImage(31);
_vm->renderImage(0);
@@ -527,15 +437,15 @@ void Intro::cutscene() {
return;
_vm->paletteFadeOut();
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
+ while (_vm->_sound->isPlaying())
exitOnEscape(1);
_vm->_system->fillScreen(kColorBlack);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
if (!animate(0, 0, 0, kMessageNormal, kStringIntroCutscene25))
return;
- _vm->_menuBrightness = 5;
+ _vm->_screen->setGuiBrightness(5);
_vm->paletteBrightness();
_vm->setCurrentImage(31);
@@ -558,20 +468,20 @@ void Intro::cutscene() {
return;
CursorMan.showMouse(false);
- _vm->_brightness = 0;
+ _vm->_screen->setViewportBrightness(0);
_vm->paletteBrightness();
exitOnEscape(10);
_vm->playSound(kAudioSnoring);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
exitOnEscape(10);
_vm->playSound(kAudioSnoring);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
exitOnEscape(10);
_vm->playSound(kAudioSnoring);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
exitOnEscape(30);
CursorMan.showMouse(true);
@@ -605,7 +515,7 @@ void Intro::cutscene() {
}
void Intro::leaveCutscene() {
- _vm->_brightness = 255;
+ _vm->_screen->setViewportBrightness(255);
_vm->removeMessage();
_gm->changeRoom(CABIN_R3);
_gm->_guiEnabled = true;
@@ -620,19 +530,19 @@ bool ShipCorridor::interact(Action verb, Object &obj1, Object &obj2) {
_objectState[6].disableProperty(OPENED);
_vm->renderImage(8);
setSectionVisible(9, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(7);
setSectionVisible(8, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(7));
} else {
_vm->playSound(kAudioSlideDoor);
_objectState[6].setProperty(OPENED);
_vm->renderImage(7);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(8);
setSectionVisible(7, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(9);
setSectionVisible(8, false);
}
@@ -649,18 +559,18 @@ bool ShipHall::interact(Action verb, Object &obj1, Object &obj2) {
_objectState[2].disableProperty(OPENED);
_vm->renderImage(3);
setSectionVisible(4, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(2);
setSectionVisible(3, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(2));
} else {
_objectState[2].setProperty(OPENED);
_vm->renderImage(2);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(3);
setSectionVisible(2, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(4);
setSectionVisible(3, false);
_gm->great(1);
@@ -727,13 +637,13 @@ bool ShipSleepCabin::interact(Action verb, Object &obj1, Object &obj2) {
if (daysSleep != 0) {
_gm->_state._timeSleep = daysSleep;
_vm->renderText(kStringShipSleepCabin8, 30, 105, kColorWhite99);
- _gm->wait2(18);
+ _gm->wait(18);
setSectionVisible(5, true);
}
} while (daysSleep == 0);
} else {
_vm->renderText(kStringShipSleepCabin9, 100, 125, kColorLightRed);
- _gm->wait2(18);
+ _gm->wait(18);
}
}
}
@@ -813,12 +723,12 @@ bool ShipSleepCabin::interact(Action verb, Object &obj1, Object &obj2) {
_gm->_state._dream = true;
_gm->loadTime();
}
- _gm->wait2(18);
+ _gm->wait(18);
_vm->paletteFadeIn();
if (_gm->_state._arrivalDaysLeft == 0) {
_vm->playSound(kAudioCrash);
_gm->screenShake();
- _gm->wait2(18);
+ _gm->wait(18);
_vm->renderMessage(kStringShipSleepCabin12);
}
}
@@ -860,10 +770,10 @@ void ShipSleepCabin::animation() {
void ShipSleepCabin::onEntrance() {
if (_gm->_state._dream && (_gm->_rooms[CAVE]->getObject(1)->_exitRoom == MEETUP3)) {
_vm->renderMessage(kStringShipSleepCabin14);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringShipSleepCabin15);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringShipSleepCabin16);
_gm->_state._dream = false;
@@ -1004,7 +914,7 @@ bool ShipCabinL3::interact(Action verb, Object &obj1, Object &obj2) {
setSectionVisible(15, false);
for (int i = 3; i; i--) {
_vm->playSound(kAudioTurntable);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle)) {
+ while (_vm->_sound->isPlaying()) {
if (isSectionVisible(13)) {
_vm->renderImage(14);
setSectionVisible(13, false);
@@ -1012,7 +922,7 @@ bool ShipCabinL3::interact(Action verb, Object &obj1, Object &obj2) {
_vm->renderImage(13);
setSectionVisible(14, false);
}
- _gm->wait2(3);
+ _gm->wait(3);
}
}
@@ -1037,7 +947,7 @@ bool ShipCabinL3::interact(Action verb, Object &obj1, Object &obj2) {
setSectionVisible(10, false);
getObject(10)->_click = 20;
} else if ((verb == ACTION_USE) && Object::combine(obj1, obj2, KNIFE, WIRE2))
- _vm->renderMessage(kStringShipCabinL3_4);
+ _vm->renderMessage(kStringShipCabinL3_4); // cutting near plug
else if ((verb == ACTION_USE) && Object::combine(obj1, obj2, KNIFE, WIRE)) {
r = _gm->_rooms[AIRLOCK];
if (!isSectionVisible(10) && !r->getObject(5)->hasProperty(WORN)) {
@@ -1125,20 +1035,20 @@ bool ShipAirlock::interact(Action verb, Object &obj1, Object &obj2) {
if (getObject(0)->hasProperty(OPENED)) {
getObject(0)->disableProperty(OPENED);
_vm->renderImage(1);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(2);
setSectionVisible(1, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(3);
setSectionVisible(2, false);
} else {
getObject(0)->setProperty(OPENED);
_vm->renderImage(2);
setSectionVisible(3, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(1);
setSectionVisible(2, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(1));
}
_vm->renderImage(_gm->invertSection(10));
@@ -1150,53 +1060,53 @@ bool ShipAirlock::interact(Action verb, Object &obj1, Object &obj2) {
_vm->playSound(kAudioSlideDoor);
getObject(1)->disableProperty(OPENED);
_vm->renderImage(4);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(5);
setSectionVisible(4, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(6);
setSectionVisible(5, false);
_vm->renderImage(16);
setSectionVisible(17, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(15);
setSectionVisible(16, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(14);
setSectionVisible(15, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(13);
setSectionVisible(14, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(12);
setSectionVisible(13, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(_gm->invertSection(12));
} else {
getObject(1)->setProperty(OPENED);
_vm->renderImage(12);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(13);
setSectionVisible(12, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(14);
setSectionVisible(13, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(15);
setSectionVisible(14, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(16);
setSectionVisible(15, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(17);
setSectionVisible(16, false);
_vm->playSound(kAudioSlideDoor);
_vm->renderImage(5);
setSectionVisible(6, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(4);
setSectionVisible(5, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(4));
r = _gm->_rooms[AIRLOCK];
if (!r->getObject(4)->hasProperty(WORN) ||
@@ -1302,13 +1212,13 @@ bool ShipLandingModule::interact(Action verb, Object &obj1, Object &obj2) {
r = _gm->_rooms[SLEEP];
r->setSectionVisible(1, false);
r->setSectionVisible(2, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(2);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(8);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(9);
- _gm->wait2(1);
+ _gm->wait(1);
_vm->renderImage(10);
}
}
@@ -1529,9 +1439,9 @@ bool ArsanoRocks::interact(Action verb, Object &obj1, Object &obj2) {
if (((verb == ACTION_PULL) || (verb == ACTION_PRESS)) &&
(obj1._id == STONE) && !isSectionVisible(3)) {
_vm->renderImage(1);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(2);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(3);
_vm->playSound(kAudioRocks);
obj1._click = 3;
@@ -1544,10 +1454,10 @@ bool ArsanoRocks::interact(Action verb, Object &obj1, Object &obj2) {
void ArsanoMeetup::onEntrance() {
if (isSectionVisible(7)) {
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(6);
setSectionVisible(7, false);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(_gm->invertSection(6));
}
if (!(_gm->_state._greatFlag & 0x8000)) {
@@ -1591,10 +1501,10 @@ bool ArsanoMeetup::interact(Action verb, Object &obj1, Object &obj2) {
_vm->paletteBrightness();
} else if ((verb == ACTION_WALK) && (obj1._id == DOOR)) {
_vm->renderImage(6);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(7);
setSectionVisible(6, false);
- _gm->wait2(3);
+ _gm->wait(3);
return false;
} else if ((verb == ACTION_LOOK) && (obj1._id == MEETUP_SIGN) && _gm->_state._language) {
@@ -1616,21 +1526,21 @@ bool ArsanoMeetup::interact(Action verb, Object &obj1, Object &obj2) {
}
void ArsanoEntrance::animation() {
- if (!_vm->_messageDisplayed && isSectionVisible(kMaxSection - 5)) {
+ if (!_vm->_screen->isMessageShown() && isSectionVisible(kMaxSection - 5)) {
_gm->animationOff(); // to avoid recursive call
_vm->playSound(kAudioSlideDoor);
_vm->renderImage(8);
setSectionVisible(9, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(7);
setSectionVisible(8, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(6);
setSectionVisible(7, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(5);
setSectionVisible(6, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(5));
getObject(11)->_click = 255;
setSectionVisible(kMaxSection - 5, false);
@@ -1695,7 +1605,7 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
}
} else if ((verb == ACTION_WALK) && (obj1._id == STAIRCASE) && (_gm->_state._shoes != 3)) {
_vm->renderImage(3);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(4);
setSectionVisible(3, false);
if (_gm->_rooms[AIRLOCK]->getObject(4)->hasProperty(WORN))
@@ -1706,7 +1616,7 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
_gm->reply(kStringArsanoEntrance12, 1, _gm->invertSection(1));
_vm->renderImage(3);
setSectionVisible(4, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(3));
if (!_gm->_rooms[AIRLOCK]->getObject(4)->hasProperty(WORN)) {
if (_gm->_state._language) {
@@ -1732,13 +1642,13 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
break;
case 3:
_vm->renderImage(3);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(4);
setSectionVisible(3, false);
_gm->reply(kStringArsanoEntrance16, 1, 1 + 128);
_vm->renderImage(3);
setSectionVisible(4, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(3));
break;
}
@@ -1752,16 +1662,16 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
} else if ((verb == ACTION_PRESS) && (obj1._id == BATHROOM_BUTTON)) {
_vm->playSound(kAudioSlideDoor);
_vm->renderImage(5);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(6);
setSectionVisible(5, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(7);
setSectionVisible(6, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(8);
setSectionVisible(7, false);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(9);
setSectionVisible(8, false);
getObject(11)->_click = 9;
@@ -1782,7 +1692,7 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
_vm->renderMessage(kStringArsanoEntrance20);
else {
_vm->renderMessage(kStringArsanoEntrance21);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringArsanoEntrance22);
_gm->takeObject(*getObject(16));
@@ -1829,7 +1739,7 @@ bool ArsanoEntrance::interact(Action verb, Object &obj1, Object &obj2) {
_gm->_rooms[AIRLOCK]->getObject(4)->setProperty(WORN);
_gm->_rooms[AIRLOCK]->getObject(5)->setProperty(WORN);
_gm->_rooms[AIRLOCK]->getObject(6)->setProperty(WORN);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
}
return false;
@@ -2097,12 +2007,12 @@ bool ArsanoRoger::interact(Action verb, Object &obj1, Object &obj2) {
_vm->paletteFadeOut();
_gm->_inventory.remove(*_gm->_rooms[CABIN_R3]->getObject(0)); // Chess board
g_system->fillScreen(kColorBlack);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
_vm->renderMessage(kStringArsanoRoger39);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
_gm->_state._time += ticksToMsec(125000); // 2 hours
_gm->_state._alarmOn = (_gm->_state._timeAlarm > _gm->_state._time);
@@ -2117,7 +2027,7 @@ bool ArsanoRoger::interact(Action verb, Object &obj1, Object &obj2) {
getObject(6)->_click = 7;
_vm->paletteFadeIn();
_vm->renderMessage(kStringArsanoRoger40);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
} else
return false;
@@ -2140,7 +2050,7 @@ bool ArsanoGlider::interact(Action verb, Object &obj1, Object &obj2) {
static char l, r;
if ((verb == ACTION_USE) && Object::combine(obj1, obj2, KEYCARD_R, GLIDER_SLOT)) {
_vm->renderImage(5);
- _gm->wait2(7);
+ _gm->wait(7);
_vm->renderImage(8);
getObject(5)->_click = 10;
_gm->_inventory.remove(*_gm->_rooms[ROGER]->getObject(8));
@@ -2192,7 +2102,7 @@ bool ArsanoGlider::interact(Action verb, Object &obj1, Object &obj2) {
}
}
}
- _gm->wait2(4);
+ _gm->wait(4);
_vm->renderImage(_gm->invertSection(i));
} else if ((verb == ACTION_USE) && (obj1._id == GLIDER_BUTTONS))
_vm->renderMessage(kStringArsanoGlider1);
@@ -2264,40 +2174,40 @@ bool ArsanoMeetup2::interact(Action verb, Object &obj1, Object &obj2) {
_vm->setCurrentImage(13);
_vm->renderImage(0);
_vm->paletteBrightness();
- _gm->wait2(36);
+ _gm->wait(36);
for (int i = 1; i <= 13; i++) {
if (i > 1)
_vm->renderImage(_gm->invertSection(i - 1));
_vm->renderImage(i);
- _gm->wait2(2);
+ _gm->wait(2);
}
_vm->renderImage(_gm->invertSection(13));
- _gm->wait2(20);
+ _gm->wait(20);
_vm->setCurrentImage(14);
_vm->renderImage(0);
_vm->paletteBrightness();
- _gm->wait2(36);
+ _gm->wait(36);
for (int i = 1; i <= 13; i++) {
if (i > 1)
_vm->renderImage(_gm->invertSection(i - 1));
_vm->renderImage(i);
- _gm->wait2(2);
+ _gm->wait(2);
}
_vm->renderImage(_gm->invertSection(13));
- _gm->wait2(9);
+ _gm->wait(9);
_vm->playSound(kAudioCrash);
for (int i = 14; i <= 19; i++) {
_vm->renderImage(i);
- _gm->wait2(3);
+ _gm->wait(3);
}
_vm->paletteFadeOut();
_vm->setCurrentImage(11);
_vm->renderImage(0);
_vm->paletteFadeIn();
- _gm->wait2(18);
+ _gm->wait(18);
_vm->renderMessage(kStringArsanoMeetup2_12);
_gm->great(0);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
_vm->paletteFadeOut();
g_system->fillScreen(kColorBlack);
@@ -2321,14 +2231,14 @@ bool ArsanoMeetup2::interact(Action verb, Object &obj1, Object &obj2) {
}
void ArsanoMeetup2::shipStart() {
- _gm->wait2(12);
+ _gm->wait(12);
for (int i = 2; i <= 11; ++i) {
if (i >= 9)
_vm->renderImage(i - 1 + 128);
else
setSectionVisible(i - 1, false);
_vm->renderImage(i);
- _gm->wait2(2);
+ _gm->wait(2);
}
_vm->renderImage(11 + 128);
}
@@ -2354,34 +2264,34 @@ bool ArsanoMeetup3::interact(Action verb, Object &obj1, Object &obj2) {
_vm->paletteBrightness();
_gm->dialog(3, rowsX, _dialogsX, 0);
_vm->renderImage(1);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(2);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(3);
- _gm->wait2(6);
+ _gm->wait(6);
_vm->renderImage(4);
_vm->playSound(kAudioGunShot);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
_vm->renderImage(5);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(4);
_vm->playSound(kAudioGunShot);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
_vm->renderImage(5);
_vm->paletteFadeOut();
- _gm->wait2(12);
+ _gm->wait(12);
_vm->setCurrentImage(0);
_vm->renderImage(0);
_vm->paletteFadeIn();
- _gm->wait2(18);
+ _gm->wait(18);
_gm->reply(kStringArsanoMeetup3_1, 2, 2 + 128);
- _gm->wait2(10);
+ _gm->wait(10);
_gm->reply(kStringArsanoMeetup3_2, 1, 1 + 128);
do {
@@ -2604,8 +2514,8 @@ bool AxacussCell::interact(Action verb, Object &obj1, Object &obj2) {
return false;
_vm->playSound(kAudioGunShot);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- _gm->wait2(1);
+ while (_vm->_sound->isPlaying())
+ _gm->wait(1);
_vm->playSound(kAudioGunShot);
_vm->playSound(kAudioGunShot);
@@ -2693,26 +2603,29 @@ bool AxacussCorridor5::handleMoneyDialog() {
}
switch (_gm->dialog(4, _rows, _dialog3, 2)) {
case 1:
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(1);
_vm->playSound(kAudioVoiceHalt);
_vm->renderImage(_gm->invertSection(1));
- _gm->wait2(5);
+ _gm->wait(5);
_vm->renderImage(2);
- _gm->wait2(2);
+ _gm->wait(2);
_gm->shot(3, _gm->invertSection(3));
break;
- case 3:
- if (_gm->_state._money >= 900) {
- stopInteract(_gm->_state._money);
- return true;
- }
case 2:
if (_gm->_state._money > 1100) {
stopInteract(_gm->_state._money - 200);
return true;
}
_gm->reply(kStringAxacussCorridor5_6, 1, 1 + 128);
+ break;
+ case 3:
+ if (_gm->_state._money >= 900) {
+ stopInteract(_gm->_state._money);
+ return true;
+ }
+ _gm->reply(kStringAxacussCorridor5_6, 1, 1 + 128);
+ break;
}
}
return false;
@@ -2958,7 +2871,7 @@ bool AxacussExit::interact(Action verb, Object &obj1, Object &obj2) {
_vm->renderImage(i);
if (i == 11)
_vm->playSound(kAudioSmash); // 046/4020
- _gm->wait2(1);
+ _gm->wait(1);
_vm->renderImage(i + 128);
}
_gm->_state._powerOff = true;
@@ -3175,9 +3088,9 @@ bool AxacussElevator::interact(Action verb, Object &obj1, Object &obj2) {
_vm->renderImage(1);
getObject(2)->resetProperty();
_vm->playSound(kAudioSlideDoor);
- _gm->wait2(25);
+ _gm->wait(25);
for (int i = 3; i <= 7; i++) {
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(i);
}
getObject(3)->resetProperty(EXIT);
@@ -3195,10 +3108,10 @@ bool AxacussElevator::interact(Action verb, Object &obj1, Object &obj2) {
getObject(3)->_click = 255;
_vm->playSound(kAudioSlideDoor);
for (int i = 7; i >= 3; i--) {
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(i));
}
- _gm->wait2(25);
+ _gm->wait(25);
_vm->playSound(kAudioSlideDoor);
getObject(2)->resetProperty(EXIT);
_vm->renderImage(_gm->invertSection(2));
@@ -3206,12 +3119,12 @@ bool AxacussElevator::interact(Action verb, Object &obj1, Object &obj2) {
} else if ((verb == ACTION_WALK) && (obj1._id == JUNGLE)) {
_vm->paletteFadeOut();
g_system->fillScreen(kColorBlack);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
_vm->renderMessage(kStringAxacussElevator_3);
- _gm->waitOnInput(_gm->_timer1);
+ _gm->waitOnInput(_gm->_messageDuration);
_vm->removeMessage();
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
_gm->_state._time += ticksToMsec(125000); // 2 hours
_gm->_state._alarmOn = (_gm->_state._timeAlarm > _gm->_state._time);
@@ -3280,24 +3193,24 @@ void Outro::onEntrance() {
_vm->renderImage(0);
_vm->renderImage(1);
_vm->paletteFadeIn();
- _gm->wait2(10);
+ _gm->wait(10);
for (int i = 8; i <= 21; i++) {
_vm->renderImage(i);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(_gm->invertSection(i));
}
- _gm->wait2(18);
+ _gm->wait(18);
_vm->renderImage(_gm->invertSection(1));
for (int i = 2; i <= 7; i++) {
_vm->renderImage(i);
- _gm->wait2(3);
+ _gm->wait(3);
_vm->renderImage(_gm->invertSection(i));
}
- _vm->playSoundMod(kMusicOutro);
- Marquee marquee(_vm, Marquee::kMarqueeOutro, _outroText.c_str());
+ _vm->playSound(kMusicOutro);
+ Marquee marquee(_vm->_screen, Marquee::kMarqueeOutro, _outroText.c_str());
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ _gm->updateEvents();
marquee.renderCharacter();
if (_gm->_mouseClicked || _gm->_keyPressed)
break;
@@ -3310,7 +3223,7 @@ void Outro::onEntrance() {
_vm->paletteFadeIn();
_gm->getInput();
_vm->paletteFadeOut();
- _vm->_brightness = 1;
+ _vm->_screen->setViewportBrightness(1);
Common::Event event;
event.type = Common::EVENT_RTL;
@@ -3324,9 +3237,9 @@ void Outro::animate(int filenumber, int section1, int section2, int duration) {
_vm->setCurrentImage(filenumber);
while (duration) {
_vm->renderImage(section1);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(section2);
- _gm->wait2(2);
+ _gm->wait(2);
--duration;
}
}
@@ -3339,10 +3252,10 @@ void Outro::animate(int filenumber, int section1, int section2, int duration,
while (delay) {
if (section1)
_vm->renderImage(section1);
- _gm->wait2(2);
+ _gm->wait(2);
if (section2)
_vm->renderImage(section2);
- _gm->wait2(2);
+ _gm->wait(2);
--delay;
}
_vm->removeMessage();
@@ -3358,10 +3271,10 @@ void Outro::animate(int filenumber, int section1, int section2, int section3, in
while(duration) {
_vm->renderImage(section1);
_vm->renderImage(section3);
- _gm->wait2(2);
+ _gm->wait(2);
_vm->renderImage(section2);
_vm->renderImage(section4);
- _gm->wait2(2);
+ _gm->wait(2);
duration--;
}
_vm->removeMessage();
diff --git a/engines/supernova/rooms.h b/engines/supernova/rooms.h
index 3cedc356db..5c9b283dcd 100644
--- a/engines/supernova/rooms.h
+++ b/engines/supernova/rooms.h
@@ -27,6 +27,11 @@
#include "msn_def.h"
+namespace Common {
+class ReadStream;
+class WriteStream;
+}
+
namespace Supernova {
class GameManager;
@@ -52,7 +57,7 @@ public:
int getFileNumber() const {
return _fileNumber;
}
- RoomID getId() const {
+ RoomId getId() const {
return _id;
}
@@ -112,7 +117,7 @@ protected:
bool _shown[kMaxSection];
byte _sentenceRemoved[kMaxDialog];
Object _objectState[kMaxObject];
- RoomID _id;
+ RoomId _id;
SupernovaEngine *_vm;
GameManager *_gm;
@@ -129,9 +134,9 @@ public:
private:
bool animate(int section1, int section2, int duration);
bool animate(int section1, int section2, int duration, MessagePosition position,
- StringID text);
+ StringId text);
bool animate(int section1, int section2, int section3, int section4, int duration,
- MessagePosition position, StringID text);
+ MessagePosition position, StringId text);
void titleScreen();
void titleFadeIn();
@@ -681,9 +686,9 @@ public:
virtual void animation();
private:
- StringID _dialog1[5];
- StringID _dialog2[5];
- StringID _dialog3[5];
+ StringId _dialog1[5];
+ StringId _dialog2[5];
+ StringId _dialog3[5];
byte _eyewitness;
};
class ArsanoRemaining : public Room {
@@ -742,7 +747,7 @@ public:
virtual bool interact(Action verb, Object &obj1, Object &obj2);
private:
- StringID _dialog1[4];
+ StringId _dialog1[4];
byte _eyewitness;
byte _hands;
};
@@ -809,10 +814,10 @@ public:
private:
// TODO: change to 6, fix initialization
- StringID _dialog1[2];
- StringID _dialog2[2];
- StringID _dialog3[4];
- StringID _dialog4[3];
+ StringId _dialog1[2];
+ StringId _dialog2[2];
+ StringId _dialog3[4];
+ StringId _dialog4[3];
bool _found;
bool _flug;
@@ -846,11 +851,11 @@ public:
virtual bool interact(Action verb, Object &obj1, Object &obj2);
private:
- StringID _dialog2[4];
- StringID _dialog3[2];
+ StringId _dialog2[4];
+ StringId _dialog3[2];
// TODO: Hack, to be move away and renamed when the other uses are found
- StringID _dialogsX[6];
+ StringId _dialogsX[6];
//
};
@@ -1025,9 +1030,9 @@ private:
bool handleMoneyDialog();
// TODO: Change to 6, or change struct, and fix initialization
- StringID _dialog1[2];
- StringID _dialog2[2];
- StringID _dialog3[4];
+ StringId _dialog1[2];
+ StringId _dialog2[2];
+ StringId _dialog3[4];
byte _rows[6];
};
@@ -1176,7 +1181,7 @@ public:
virtual bool interact(Action verb, Object &obj1, Object &obj2);
private:
- StringID _dialogsX[6];
+ StringId _dialogsX[6];
};
class AxacussExit : public Room {
@@ -1205,7 +1210,7 @@ public:
virtual bool interact(Action verb, Object &obj1, Object &obj2);
private:
- StringID _dialogsX[6];
+ StringId _dialogsX[6];
};
class AxacussOffice1 : public Room {
public:
diff --git a/engines/supernova/screen.cpp b/engines/supernova/screen.cpp
new file mode 100644
index 0000000000..2c441acf7b
--- /dev/null
+++ b/engines/supernova/screen.cpp
@@ -0,0 +1,636 @@
+/* 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/str.h"
+#include "common/system.h"
+#include "engines/util.h"
+#include "graphics/cursorman.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+
+#include "supernova/imageid.h"
+#include "supernova/resman.h"
+#include "supernova/state.h"
+#include "supernova/screen.h"
+#include "supernova/supernova.h"
+
+#include "supernova/screenstatic.cpp"
+
+namespace Supernova {
+
+ScreenBuffer::ScreenBuffer()
+ : _x(0)
+ , _y(0)
+ , _width(0)
+ , _height(0)
+ , _pixels(nullptr) {
+}
+
+ScreenBufferStack::ScreenBufferStack()
+ : _last(_buffer) {
+}
+
+void ScreenBufferStack::push(int x, int y, int width, int height) {
+ if (_last == ARRAYEND(_buffer))
+ return;
+
+ Graphics::Surface *screenSurface = g_system->lockScreen();
+
+ if (x < 0) {
+ width += x;
+ x = 0;
+ }
+
+ if (x + width > screenSurface->w)
+ width = screenSurface->w - x;
+
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+
+ if (y + height > screenSurface->h)
+ height = screenSurface->h - y;
+
+ _last->_pixels = new byte[width * height];
+ byte *pixels = _last->_pixels;
+ const byte *screen = static_cast<const byte *>(screenSurface->getBasePtr(x, y));
+ for (int i = 0; i < height; ++i) {
+ Common::copy(screen, screen + width, pixels);
+ screen += screenSurface->pitch;
+ pixels += width;
+ }
+ g_system->unlockScreen();
+
+ _last->_x = x;
+ _last->_y = y;
+ _last->_width = width;
+ _last->_height = height;
+
+ ++_last;
+}
+
+void ScreenBufferStack::restore() {
+ if (_last == _buffer)
+ return;
+
+ --_last;
+ g_system->lockScreen()->copyRectToSurface(_last->_pixels, _last->_width, _last->_x,
+ _last->_y, _last->_width, _last->_height);
+ g_system->unlockScreen();
+
+ delete[] _last->_pixels;
+}
+
+Marquee::Marquee(Screen *screen, MarqueeId id, const char *text)
+ : _text(text)
+ , _textBegin(text)
+ , _delay(0)
+ , _color(kColorLightBlue)
+ , _loop(false)
+ , _screen(screen) {
+ if (id == kMarqueeIntro) {
+ _y = 191;
+ _loop = true;
+ } else if (id == kMarqueeOutro) {
+ _y = 1;
+ }
+
+ _textWidth = Screen::textWidth(_text);
+ _x = kScreenWidth / 2 - _textWidth / 2;
+ _screen->_textCursorX = _x;
+ _screen->_textCursorY = _y;
+ _screen->_textColor = _color;
+}
+
+void Marquee::clearText() {
+ _screen->renderBox(_x, _y - 1, _textWidth + 1, 9, kColorBlack);
+}
+
+void Marquee::renderCharacter() {
+ if (_delay != 0) {
+ _delay--;
+ return;
+ }
+
+ switch (*_text) {
+ case '\233':
+ if (_loop) {
+ _loop = false;
+ _text = _textBegin;
+ clearText();
+ _textWidth = Screen::textWidth(_text);
+ _x = kScreenWidth / 2 - _textWidth / 2;
+ _screen->_textCursorX = _x;
+ }
+ break;
+ case '\0':
+ clearText();
+ _text++;
+ _textWidth = Screen::textWidth(_text);
+ _x = kScreenWidth / 2 - _textWidth / 2;
+ _screen->_textCursorX = _x;
+ _color = kColorLightBlue;
+ _screen->_textColor = _color;
+ break;
+ case '^':
+ _color = kColorLightYellow;
+ _screen->_textColor = _color;
+ _text++;
+ break;
+ case '#':
+ _delay = 50;
+ _text++;
+ break;
+ default:
+ _screen->renderText((uint16)*_text++);
+ _delay = 1;
+ break;
+ }
+}
+
+Screen::Screen(SupernovaEngine *vm, GameManager *gm, ResourceManager *resMan)
+ : _vm(vm)
+ , _gm(gm)
+ , _resMan(resMan)
+ , _currentImage(nullptr)
+ , _viewportBrightness(255)
+ , _guiBrightness(255)
+ , _screenWidth(320)
+ , _screenHeight(200)
+ , _textColor(kColorBlack)
+ , _textCursorX(0)
+ , _textCursorY(0)
+ , _messageShown(false) {
+
+ CursorMan.replaceCursor(_resMan->getImage(ResourceManager::kCursorNormal),
+ 16, 16, 0, 0, kColorCursorTransparent);
+ CursorMan.replaceCursorPalette(initVGAPalette, 0, 16);
+ CursorMan.showMouse(true);
+}
+
+int Screen::getGuiBrightness() const {
+ return _guiBrightness;
+}
+
+void Screen::setViewportBrightness(int brightness) {
+ _viewportBrightness = brightness;
+}
+
+int Screen::getViewportBrightness() const {
+ return _viewportBrightness;
+}
+
+void Screen::setGuiBrightness(int brightness) {
+ _guiBrightness = brightness;
+}
+
+const MSNImage *Screen::getCurrentImage() const {
+ return _currentImage;
+}
+
+bool Screen::isMessageShown() const {
+ return _messageShown;
+}
+
+Common::Point Screen::getTextCursorPos() {
+ return Common::Point(_textCursorX, _textCursorY);
+}
+
+void Screen::setTextCursorPos(int x, int y) {
+ _textCursorX = x;
+ _textCursorY = y;
+}
+
+byte Screen::getTextCursorColor() {
+ return _textColor;
+}
+
+void Screen::setTextCursorColor(byte color) {
+ _textColor = color;
+}
+
+void Screen::renderMessage(StringId stringId, MessagePosition position,
+ Common::String var1, Common::String var2) {
+ Common::String text = _vm->getGameString(stringId);
+
+ if (!var1.empty()) {
+ if (!var2.empty())
+ text = Common::String::format(text.c_str(), var1.c_str(), var2.c_str());
+ else
+ text = Common::String::format(text.c_str(), var1.c_str());
+ }
+
+ renderMessage(text, position);
+}
+
+void Screen::renderMessage(const Common::String &text, MessagePosition position) {
+ if (!text.empty())
+ renderMessage(text.c_str(), position);
+}
+
+void Screen::renderText(const uint16 character) {
+ char text[2];
+ text[0] = character & 0xFF;
+ text[1] = 0;
+ renderText(text, _textCursorX, _textCursorY, _textColor);
+}
+
+void Screen::renderText(const char *text) {
+ renderText(text, _textCursorX, _textCursorY, _textColor);
+}
+
+void Screen::renderText(StringId stringId) {
+ renderText(_vm->getGameString(stringId));
+}
+
+void Screen::renderText(const Common::String &text) {
+ if (!text.empty())
+ renderText(text.c_str());
+}
+
+void Screen::renderText(const GuiElement &guiElement) {
+ renderText(guiElement.getText(), guiElement.getTextPos().x,
+ guiElement.getTextPos().y, guiElement.getTextColor());
+}
+
+void Screen::renderText(const uint16 character, int x, int y, byte color) {
+ char text[2];
+ text[0] = character & 0xFF;
+ text[1] = 0;
+ renderText(text, x, y, color);
+}
+
+void Screen::renderText(const char *text, int x, int y, byte color) {
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ byte *cursor = static_cast<byte *>(screen->getBasePtr(x, y));
+ const byte *basePtr = cursor;
+
+ byte c;
+ while ((c = *text++) != '\0') {
+ if (c < 32) {
+ continue;
+ } else if (c == 225) {
+ c = 128;
+ }
+
+ for (uint i = 0; i < 5; ++i) {
+ if (font[c - 32][i] == 0xff) {
+ break;
+ }
+
+ byte *ascentLine = cursor;
+ for (byte j = font[c - 32][i]; j != 0; j >>= 1) {
+ if (j & 1) {
+ *cursor = color;
+ }
+ cursor += kScreenWidth;
+ }
+ cursor = ++ascentLine;
+ }
+ ++cursor;
+ }
+ _vm->_system->unlockScreen();
+
+ uint numChars = cursor - basePtr;
+ uint absPosition = y * kScreenWidth + x + numChars;
+ _textCursorX = absPosition % kScreenWidth;
+ _textCursorY = absPosition / kScreenWidth;
+ _textColor = color;
+}
+
+void Screen::renderText(const Common::String &text, int x, int y, byte color) {
+ if (!text.empty())
+ renderText(text.c_str(), x, y, color);
+}
+
+void Screen::renderText(StringId stringId, int x, int y, byte color) {
+ renderText(_vm->getGameString(stringId), x, y, color);
+}
+
+void Screen::renderImageSection(const MSNImage *image, int section) {
+ // Note: inverting means we are removing the section. So we should get the rect for that
+ // section but draw the background (section 0) instead.
+ bool invert = false;
+ if (section > 128) {
+ section -= 128;
+ invert = true;
+ }
+ if (section > image->_numSections - 1)
+ return;
+
+ Common::Rect sectionRect(image->_section[section].x1,
+ image->_section[section].y1,
+ image->_section[section].x2 + 1,
+ image->_section[section].y2 + 1);
+ if (image->_filenumber == 1 || image->_filenumber == 2) {
+ sectionRect.setWidth(640);
+ sectionRect.setHeight(480);
+ if (_screenWidth != 640) {
+ _screenWidth = 640;
+ _screenHeight = 480;
+ initGraphics(_screenWidth, _screenHeight);
+ }
+ } else {
+ if (_screenWidth != 320) {
+ _screenWidth = 320;
+ _screenHeight = 200;
+ initGraphics(_screenWidth, _screenHeight);
+ }
+ }
+
+ uint offset = 0;
+ int pitch = sectionRect.width();
+ if (invert) {
+ pitch = image->_pitch;
+ offset = image->_section[section].y1 * pitch +
+ image->_section[section].x1;
+ section = 0;
+ }
+
+ void *pixels = image->_sectionSurfaces[section]->getPixels();
+ _vm->_system->copyRectToScreen(static_cast<const byte *>(pixels) + offset,
+ pitch, sectionRect.left, sectionRect.top,
+ sectionRect.width(), sectionRect.height());
+}
+
+void Screen::renderImage(ImageId id, bool removeImage) {
+ ImageInfo info = imageInfo[id];
+ const MSNImage *image = _resMan->getImage(info.filenumber);
+
+ if (_currentImage != image) {
+ _currentImage = image;
+ _vm->_system->getPaletteManager()->setPalette(image->getPalette(), 16, 239);
+ }
+
+ do {
+ if (removeImage)
+ renderImageSection(image, info.section + 128);
+ else
+ renderImageSection(image, info.section);
+
+ info.section = image->_section[info.section].next;
+ } while (info.section != 0);
+}
+
+void Screen::renderImage(int section) {
+ if (!_currentImage)
+ return;
+
+ bool sectionVisible = true;
+
+ if (section > 128) {
+ sectionVisible = false;
+ section -= 128;
+ }
+
+ _gm->_currentRoom->setSectionVisible(section, sectionVisible);
+
+ do {
+ if (sectionVisible)
+ renderImageSection(_currentImage, section);
+ else
+ renderImageSection(_currentImage, section + 128);
+ section = _currentImage->_section[section].next;
+ } while (section != 0);
+}
+
+bool Screen::setCurrentImage(int filenumber) {
+ _currentImage = _resMan->getImage(filenumber);
+ _vm->_system->getPaletteManager()->setPalette(_currentImage->getPalette(), 16, 239);
+ paletteBrightness();
+
+ return true;
+}
+
+void Screen::saveScreen(int x, int y, int width, int height) {
+ _screenBuffer.push(x, y, width, height);
+}
+
+void Screen::saveScreen(const GuiElement &guiElement) {
+ saveScreen(guiElement.left, guiElement.top, guiElement.width(), guiElement.height());
+}
+
+void Screen::restoreScreen() {
+ _screenBuffer.restore();
+}
+
+void Screen::renderRoom(Room &room) {
+ if (room.getId() == INTRO)
+ return;
+
+ if (setCurrentImage(room.getFileNumber())) {
+ for (int i = 0; i < _currentImage->_numSections; ++i) {
+ int section = i;
+ if (room.isSectionVisible(section)) {
+ do {
+ renderImageSection(_currentImage, section);
+ section = _currentImage->_section[section].next;
+ } while (section != 0);
+ }
+ }
+ }
+}
+
+int Screen::textWidth(const uint16 key) {
+ char text[2];
+ text[0] = key & 0xFF;
+ text[1] = 0;
+ return textWidth(text);
+}
+
+int Screen::textWidth(const char *text) {
+ int charWidth = 0;
+ while (*text != '\0') {
+ byte c = *text++;
+ if (c < 32) {
+ continue;
+ } else if (c == 225) {
+ c = 35;
+ }
+
+ for (uint i = 0; i < 5; ++i) {
+ if (font[c - 32][i] == 0xff) {
+ break;
+ }
+ ++charWidth;
+ }
+ ++charWidth;
+ }
+
+ return charWidth;
+}
+
+int Screen::textWidth(const Common::String &text) {
+ return Screen::textWidth(text.c_str());
+}
+
+void Screen::renderMessage(const char *text, MessagePosition position) {
+ Common::String t(text);
+ char *row[20];
+ Common::String::iterator p = t.begin();
+ uint numRows = 0;
+ int rowWidthMax = 0;
+ int x = 0;
+ int y = 0;
+ byte textColor = 0;
+
+ while (*p != '\0') {
+ row[numRows] = p;
+ ++numRows;
+ while ((*p != '\0') && (*p != '|')) {
+ ++p;
+ }
+ if (*p == '|') {
+ *p = '\0';
+ ++p;
+ }
+ }
+ for (uint i = 0; i < numRows; ++i) {
+ int rowWidth = textWidth(row[i]);
+ if (rowWidth > rowWidthMax)
+ rowWidthMax = rowWidth;
+ }
+
+ switch (position) {
+ case kMessageNormal:
+ x = 160 - rowWidthMax / 2;
+ textColor = kColorWhite99;
+ break;
+ case kMessageTop:
+ x = 160 - rowWidthMax / 2;
+ textColor = kColorLightYellow;
+ break;
+ case kMessageCenter:
+ x = 160 - rowWidthMax / 2;
+ textColor = kColorLightRed;
+ break;
+ case kMessageLeft:
+ x = 3;
+ textColor = kColorLightYellow;
+ break;
+ case kMessageRight:
+ x = 317 - rowWidthMax;
+ textColor = kColorLightGreen;
+ break;
+ }
+
+ if (position == kMessageNormal) {
+ y = 70 - ((numRows * 9) / 2);
+ } else if (position == kMessageTop) {
+ y = 5;
+ } else {
+ y = 142;
+ }
+
+ int message_columns = x - 3;
+ int message_rows = y - 3;
+ int message_width = rowWidthMax + 6;
+ int message_height = numRows * 9 + 5;
+ saveScreen(message_columns, message_rows, message_width, message_height);
+ renderBox(message_columns, message_rows, message_width, message_height, kColorWhite35);
+ for (uint i = 0; i < numRows; ++i) {
+ renderText(row[i], x, y, textColor);
+ y += 9;
+ }
+
+ _messageShown = true;
+ _gm->_messageDuration = (Common::strnlen(text, 512) + 20) * _vm->_textSpeed / 10;
+}
+
+void Screen::removeMessage() {
+ if (_messageShown) {
+ restoreScreen();
+ _messageShown = false;
+ }
+}
+
+void Screen::renderBox(int x, int y, int width, int height, byte color) {
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ screen->fillRect(Common::Rect(x, y, x + width, y + height), color);
+ _vm->_system->unlockScreen();
+}
+
+void Screen::renderBox(const GuiElement &guiElement) {
+ renderBox(guiElement.left, guiElement.top, guiElement.width(),
+ guiElement.height(), guiElement.getBackgroundColor());
+}
+
+void Screen::initPalette() {
+ g_system->getPaletteManager()->setPalette(initVGAPalette, 0, 256);
+}
+
+void Screen::paletteBrightness() {
+ byte palette[768];
+
+ _vm->_system->getPaletteManager()->grabPalette(palette, 0, 255);
+ for (uint i = 0; i < 48; ++i) {
+ palette[i] = (initVGAPalette[i] * _guiBrightness) >> 8;
+ }
+ for (uint i = 0; i < 717; ++i) {
+ const byte *imagePalette;
+ if (_currentImage && _currentImage->getPalette()) {
+ imagePalette = _currentImage->getPalette();
+ } else {
+ imagePalette = palette + 48;
+ }
+ palette[i + 48] = (imagePalette[i] * _viewportBrightness) >> 8;
+ }
+ _vm->_system->getPaletteManager()->setPalette(palette, 0, 255);
+}
+
+void Screen::paletteFadeOut() {
+ while (_guiBrightness > 10) {
+ _guiBrightness -= 10;
+ if (_viewportBrightness > _guiBrightness)
+ _viewportBrightness = _guiBrightness;
+ paletteBrightness();
+ _vm->_system->updateScreen();
+ _vm->_system->delayMillis(_vm->_delay);
+ }
+ _guiBrightness = 0;
+ _viewportBrightness = 0;
+ paletteBrightness();
+ _vm->_system->updateScreen();
+}
+
+void Screen::paletteFadeIn() {
+ while (_guiBrightness < 245) {
+ if (_viewportBrightness < _gm->_roomBrightness)
+ _viewportBrightness += 10;
+ _guiBrightness += 10;
+ paletteBrightness();
+ _vm->_system->updateScreen();
+ _vm->_system->delayMillis(_vm->_delay);
+ }
+ _guiBrightness = 255;
+ _viewportBrightness = _gm->_roomBrightness;
+ paletteBrightness();
+ _vm->_system->updateScreen();
+}
+
+void Screen::setColor63(byte value) {
+ byte color[3] = {value, value, value};
+ _vm->_system->getPaletteManager()->setPalette(color, 63, 1);
+}
+
+}
diff --git a/engines/supernova/screen.h b/engines/supernova/screen.h
new file mode 100644
index 0000000000..d57fb53ed2
--- /dev/null
+++ b/engines/supernova/screen.h
@@ -0,0 +1,197 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef SUPERNOVA_SCREEN_H
+#define SUPERNOVA_SCREEN_H
+
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/scummsys.h"
+
+#include "supernova/imageid.h"
+#include "supernova/msn_def.h"
+
+namespace Supernova {
+
+class SupernovaEngine;
+class GameManager;
+class ResourceManager;
+class GuiElement;
+class Room;
+class MSNImage;
+class Screen;
+
+const int kScreenWidth = 320;
+const int kScreenHeight = 200;
+const int kFontWidth = 5;
+const int kFontHeight = 8;
+
+enum Color {
+ kColorBlack = 0,
+ kColorWhite25 = 1,
+ kColorWhite35 = 2,
+ kColorWhite44 = 3,
+ kColorWhite99 = 4,
+ kColorDarkGreen = 5,
+ kColorGreen = 6,
+ kColorDarkRed = 7,
+ kColorRed = 8,
+ kColorDarkBlue = 9,
+ kColorBlue = 10,
+ kColorWhite63 = 11,
+ kColorLightBlue = 12,
+ kColorLightGreen = 13,
+ kColorLightYellow = 14,
+ kColorLightRed = 15,
+ kColorCursorTransparent = kColorWhite25
+};
+
+class ScreenBuffer {
+ friend class ScreenBufferStack;
+
+public:
+ ScreenBuffer();
+
+private:
+ byte *_pixels;
+ int _x;
+ int _y;
+ int _width;
+ int _height;
+};
+
+class ScreenBufferStack {
+public:
+ ScreenBufferStack();
+
+ void push(int x, int y, int width, int height);
+ void restore();
+
+private:
+ ScreenBuffer _buffer[8];
+ ScreenBuffer *_last;
+};
+
+class Marquee {
+public:
+ enum MarqueeId {
+ kMarqueeIntro,
+ kMarqueeOutro
+ };
+
+ Marquee(Screen *screen, MarqueeId id, const char *text);
+
+ void renderCharacter();
+
+private:
+ void clearText();
+
+ Screen *_screen;
+ const char *const _textBegin;
+ const char *_text;
+ bool _loop;
+ int _delay;
+ int _color;
+ int _x;
+ int _y;
+ int _textWidth;
+};
+
+class Screen {
+ friend class Marquee;
+
+public:
+ struct ImageInfo {
+ int filenumber;
+ int section;
+ };
+
+public:
+ static void initPalette();
+ static int textWidth(const uint16 key);
+ static int textWidth(const char *text);
+ static int textWidth(const Common::String &text);
+
+public:
+ Screen(SupernovaEngine *vm, GameManager *gm, ResourceManager *resMan);
+
+ int getViewportBrightness() const;
+ void setViewportBrightness(int brightness);
+ int getGuiBrightness() const;
+ void setGuiBrightness(int brightness);
+ const MSNImage *getCurrentImage() const;
+ bool isMessageShown() const;
+ void paletteFadeIn();
+ void paletteFadeOut();
+ void paletteBrightness();
+ void renderImage(ImageId id, bool removeImage = false);
+ void renderImage(int section);
+ bool setCurrentImage(int filenumber);
+ void saveScreen(int x, int y, int width, int height);
+ void saveScreen(const GuiElement &guiElement);
+ void restoreScreen();
+ void renderRoom(Room &room);
+ void renderMessage(const char *text, MessagePosition position = kMessageNormal);
+ void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal);
+ void renderMessage(StringId stringId, MessagePosition position = kMessageNormal,
+ Common::String var1 = "", Common::String var2 = "");
+ void removeMessage();
+ void renderText(const uint16 character);
+ void renderText(const char *text);
+ void renderText(const Common::String &text);
+ void renderText(StringId stringId);
+ void renderText(const uint16 character, int x, int y, byte color);
+ void renderText(const char *text, int x, int y, byte color);
+ void renderText(const Common::String &text, int x, int y, byte color);
+ void renderText(StringId stringId, int x, int y, byte color);
+ void renderText(const GuiElement &guiElement);
+ void renderBox(int x, int y, int width, int height, byte color);
+ void renderBox(const GuiElement &guiElement);
+ void setColor63(byte value);
+ Common::Point getTextCursorPos();
+ void setTextCursorPos(int x, int y);
+ byte getTextCursorColor();
+ void setTextCursorColor(byte color);
+ void update();
+
+private:
+ void renderImageSection(const MSNImage *image, int section);
+
+private:
+ SupernovaEngine *_vm;
+ GameManager *_gm;
+ ResourceManager *_resMan;
+ const MSNImage *_currentImage;
+ ScreenBufferStack _screenBuffer;
+ int _screenWidth;
+ int _screenHeight;
+ int _textCursorX;
+ int _textCursorY;
+ int _textColor;
+ byte _viewportBrightness;
+ byte _guiBrightness;
+ bool _messageShown;
+};
+
+}
+
+#endif
diff --git a/engines/supernova/screenstatic.cpp b/engines/supernova/screenstatic.cpp
new file mode 100644
index 0000000000..db987bf2fb
--- /dev/null
+++ b/engines/supernova/screenstatic.cpp
@@ -0,0 +1,328 @@
+/* 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 Supernova {
+
+static const Screen::ImageInfo imageInfo[] = {
+ { 0, 0}, { 0, 1}, { 0, 2},
+ { 1, 0},
+ { 2, 0},
+ { 3, 0}, { 3, 1}, { 3, 2}, { 3, 3}, { 3, 4}, { 3, 5},
+ { 3, 6}, { 3, 7}, { 3, 8}, { 3, 9}, { 3, 10}, { 3, 11},
+ { 4, 0}, { 4, 1}, { 4, 2}, { 4, 3},
+ { 5, 0}, { 5, 1}, { 5, 2}, { 5, 3}, { 5, 4}, { 5, 5},
+ { 5, 6}, { 5, 7}, { 5, 8}, { 5, 9},
+ { 6, 0}, { 6, 1}, { 6, 2}, { 6, 3}, { 6, 4}, { 6, 5},
+ { 6, 6}, { 6, 7}, { 6, 8}, { 6, 9}, { 6, 10}, { 6, 11},
+ { 6, 12}, { 6, 13}, { 6, 14}, { 6, 15}, { 6, 16}, { 6, 17},
+ { 6, 18}, { 6, 19}, { 6, 20}, { 6, 21},
+ { 7, 0}, { 7, 1}, { 7, 2}, { 7, 3}, { 7, 4}, { 7, 5},
+ { 7, 6}, { 7, 7}, { 7, 8}, { 7, 9}, { 7, 10}, { 7, 11},
+ { 7, 12}, { 7, 13}, { 7, 14}, { 7, 15}, { 7, 16}, { 7, 17},
+ { 7, 18}, { 7, 19}, { 7, 20}, { 7, 21}, { 7, 22},
+ { 8, 0}, { 8, 1}, { 8, 2}, { 8, 3}, { 8, 4}, { 8, 5},
+ { 8, 6}, { 8, 7}, { 8, 8}, { 8, 9}, { 8, 10}, { 8, 11},
+ { 8, 12},
+ { 9, 0}, { 9, 1}, { 9, 2}, { 9, 3}, { 9, 4}, { 9, 5},
+ { 9, 6}, { 9, 7}, { 9, 8}, { 9, 9}, { 9, 10}, { 9, 11},
+ { 9, 12}, { 9, 13}, { 9, 14}, { 9, 15}, { 9, 16}, { 9, 17},
+ { 9, 18}, { 9, 19}, { 9, 20}, { 9, 21}, { 9, 22}, { 9, 23},
+ {10, 0}, {10, 1}, {10, 2}, {10, 3}, {10, 4}, {10, 5},
+ {10, 6}, {10, 7}, {10, 8}, {10, 9}, {10, 10}, {10, 11},
+ {10, 12}, {10, 13}, {10, 14}, {10, 15}, {10, 16},
+ {11, 0},
+ {12, 0}, {12, 1}, {12, 2}, {12, 3},
+ {13, 0}, {13, 1}, {13, 2}, {13, 3}, {13, 4}, {13, 5},
+ {13, 6}, {13, 7}, {13, 8}, {13, 9}, {13, 10}, {13, 11},
+ {13, 12}, {13, 13},
+ {14, 0}, {14, 1}, {14, 2}, {14, 3}, {14, 4}, {14, 5},
+ {14, 6}, {14, 7}, {14, 8}, {14, 9}, {14, 10}, {14, 11},
+ {14, 12}, {14, 13}, {14, 14}, {14, 15}, {14, 16}, {14, 17},
+ {14, 18}, {14, 19},
+ {15, 0}, {15, 1}, {15, 2}, {15, 3}, {15, 4}, {15, 5},
+ {16, 0}, {16, 1}, {16, 2}, {16, 3}, {16, 4}, {16, 5},
+ {16, 6}, {16, 7}, {16, 8}, {16, 9}, {16, 10}, {16, 11},
+ {16, 12}, {16, 13}, {16, 14}, {16, 15}, {16, 16}, {16, 17},
+ {16, 18}, {16, 19}, {16, 20}, {16, 21}, {16, 22}, {16, 23},
+ {16, 24}, {16, 25}, {16, 26}, {16, 27}, {16, 28}, {16, 29},
+ {16, 30}, {16, 31}, {16, 32}, {16, 33},
+ {17, 0}, {17, 1}, {17, 2}, {17, 3}, {17, 4}, {17, 5},
+ {17, 6}, {17, 7}, {17, 8}, {17, 9}, {17, 10}, {17, 11},
+ {17, 12}, {17, 13}, {17, 14}, {17, 15},
+ {18, 0}, {18, 1}, {18, 2}, {18, 3}, {18, 4}, {18, 5},
+ {18, 6}, {18, 7}, {18, 8}, {18, 9}, {18, 10}, {18, 11},
+ {18, 12}, {18, 13}, {18, 14}, {18, 15}, {18, 16}, {18, 17},
+ {18, 18}, {18, 19}, {18, 20}, {18, 21},
+ {19, 0}, {19, 1}, {19, 2}, {19, 3}, {19, 4}, {19, 5},
+ {19, 6}, {19, 7}, {19, 8}, {19, 9}, {19, 10}, {19, 11},
+ {19, 12}, {19, 13}, {19, 14}, {19, 15}, {19, 16}, {19, 17},
+ {19, 18}, {19, 19}, {19, 20}, {19, 21}, {19, 22}, {19, 23},
+ {19, 24}, {19, 25}, {19, 26}, {19, 27}, {19, 28}, {19, 29},
+ {19, 30}, {19, 31}, {19, 32}, {19, 33}, {19, 34}, {19, 35},
+ {19, 36}, {19, 37}, {19, 38}, {19, 39}, {19, 40},
+ {20, 0},
+ {21, 0}, {21, 1}, {21, 2}, {21, 3}, {21, 4}, {21, 5},
+ {21, 6}, {21, 7}, {21, 8}, {21, 9}, {21, 10}, {21, 11},
+ {21, 12}, {21, 13}, {21, 14}, {21, 15}, {21, 16}, {21, 17},
+ {21, 18}, {21, 19}, {21, 20}, {21, 21}, {21, 22}, {21, 23},
+ {21, 24}, {21, 25}, {21, 26}, {21, 27}, {21, 28}, {21, 29},
+ {21, 30}, {21, 31}, {21, 32}, {21, 33}, {21, 34}, {21, 35},
+ {21, 36}, {21, 37}, {21, 38},
+ {22, 0}, {22, 1}, {22, 2}, {22, 3}, {22, 4}, {22, 5},
+ {22, 6}, {22, 7}, {22, 8}, {22, 9}, {22, 10}, {22, 11},
+ {22, 12}, {22, 13}, {22, 14}, {22, 15}, {22, 16}, {22, 17},
+ {22, 18},
+ {23, 0},
+ {24, 0}, {24, 1}, {24, 2}, {24, 3}, {24, 4}, {24, 5},
+ {24, 6}, {24, 7}, {24, 8},
+ {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
+ {25, 6}, {25, 7}, {25, 8}, {25, 9}, {25, 10}, {25, 11},
+ {25, 12}, {25, 13}, {25, 14}, {25, 15}, {25, 16}, {25, 17},
+ {25, 18},
+ {26, 0},
+ {27, 0},
+ {28, 0}, {28, 1}, {28, 2}, {28, 3}, {28, 4}, {28, 5},
+ {28, 6}, {28, 7}, {28, 8}, {28, 9}, {28, 10}, {28, 11},
+ {28, 12}, {28, 13}, {28, 14}, {28, 15}, {28, 16}, {28, 17},
+ {28, 18}, {28, 19}, {28, 20}, {28, 21}, {28, 22},
+ {29, 0}, {29, 1}, {29, 2}, {29, 3}, {29, 4}, {29, 5},
+ {29, 6}, {29, 7}, {29, 8}, {29, 9}, {29, 10}, {29, 11},
+ {29, 12}, {29, 13},
+ {30, 0}, {30, 1},
+ {31, 0}, {31, 1}, {31, 2}, {31, 3}, {31, 4}, {31, 5},
+ {31, 6},
+ {32, 0}, {32, 1}, {32, 2}, {32, 3},
+ {33, 0}, {33, 1}, {33, 2}, {33, 3}, {33, 4}, {33, 5},
+ {34, 0}, {34, 1}, {34, 2}, {34, 3}, {34, 4}, {34, 5},
+ {34, 6}, {34, 7}, {34, 8}, {34, 9}, {34, 10}, {34, 11},
+ {34, 12}, {34, 13}, {34, 14}, {34, 15}, {34, 16}, {34, 17},
+ {35, 0}, {35, 1}, {35, 2}, {35, 3}, {35, 4}, {35, 5},
+ {35, 6}, {35, 7}, {35, 8}, {35, 9}, {35, 10}, {35, 11},
+ {35, 12}, {35, 13}, {35, 14}, {35, 15}, {35, 16}, {35, 17},
+ {35, 18}, {35, 19}, {35, 20}, {35, 21},
+ {36, 0}, {36, 1}, {36, 2}, {36, 3}, {36, 4}, {36, 5},
+ {37, 0}, {37, 1}, {37, 2}, {37, 3}, {37, 4}, {37, 5},
+ {37, 6}, {37, 7}, {37, 8}, {37, 9}, {37, 10}, {37, 11},
+ {37, 12}, {37, 13}, {37, 14}, {37, 15}, {37, 16}, {37, 17},
+ {37, 18}, {37, 19}, {37, 20}, {37, 21}, {37, 22}, {37, 23},
+ {37, 24}, {37, 25}, {37, 26},
+ {38, 0}, {38, 1}, {38, 2}, {38, 3}, {38, 4}, {38, 5},
+ {38, 6}, {38, 7}, {38, 8}, {38, 9}, {38, 10}, {38, 11},
+ {38, 12},
+ {39, 0},
+ {40, 0}, {40, 1}, {40, 2}, {40, 3}, {40, 4}, {40, 5},
+ {40, 6}, {40, 7},
+ {41, 0}, {41, 1}, {41, 2}, {41, 3},
+ {42, 0}, {42, 1}, {42, 2}, {42, 3}, {42, 4}, {42, 5},
+ {42, 6}, {42, 7}, {42, 8}, {42, 9}, {42, 10}, {42, 11},
+ {43, 0}, {43, 1}, {43, 2}, {43, 3}, {43, 4}, {43, 5},
+ {43, 6}, {43, 7}, {43, 8}, {43, 9}, {43, 10}, {43, 11},
+ {43, 12}, {43, 13}, {43, 14}, {43, 15}, {43, 16}, {43, 17},
+ {43, 18}, {43, 19}, {43, 20}, {43, 21}, {43, 22}, {43, 23},
+ {43, 24}, {43, 25}, {43, 26}, {43, 27}, {43, 28}, {43, 29},
+ {43, 30}, {43, 31}
+};
+
+// Default palette
+static const byte initVGAPalette[768] = {
+ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x58, 0x58, 0x58, 0x70, 0x70, 0x70, 0xfc, 0xfc, 0xfc, 0x00, 0xd0, 0x00,
+ 0x00, 0xfc, 0x00, 0xd8, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0xb0, 0xa0, 0xa0, 0xa0,
+ 0x50, 0xc8, 0xfc, 0x28, 0xfc, 0x28, 0xf0, 0xf0, 0x00, 0xfc, 0x28, 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14,
+ 0x20, 0x20, 0x20, 0x2c, 0x2c, 0x2c, 0x38, 0x38, 0x38, 0x44, 0x44, 0x44, 0x50, 0x50, 0x50, 0x60, 0x60, 0x60,
+ 0x70, 0x70, 0x70, 0x80, 0x80, 0x80, 0x90, 0x90, 0x90, 0xa0, 0xa0, 0xa0, 0xb4, 0xb4, 0xb4, 0xc8, 0xc8, 0xc8,
+ 0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc,
+ 0xfc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00,
+ 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc, 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x00,
+ 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x40, 0x00, 0xfc, 0x7c, 0x00, 0xfc, 0xbc, 0x00, 0xfc, 0xfc, 0x00, 0xbc, 0xfc,
+ 0x00, 0x7c, 0xfc, 0x00, 0x40, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc,
+ 0xfc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c,
+ 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc, 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0x7c,
+ 0x7c, 0xfc, 0x7c, 0x7c, 0xfc, 0x9c, 0x7c, 0xfc, 0xbc, 0x7c, 0xfc, 0xdc, 0x7c, 0xfc, 0xfc, 0x7c, 0xdc, 0xfc,
+ 0x7c, 0xbc, 0xfc, 0x7c, 0x9c, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc,
+ 0xfc, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4,
+ 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc, 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0xb4,
+ 0xb4, 0xfc, 0xb4, 0xb4, 0xfc, 0xc4, 0xb4, 0xfc, 0xd8, 0xb4, 0xfc, 0xe8, 0xb4, 0xfc, 0xfc, 0xb4, 0xe8, 0xfc,
+ 0xb4, 0xd8, 0xfc, 0xb4, 0xc4, 0xfc, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70,
+ 0x70, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00,
+ 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70, 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x00,
+ 0x00, 0x70, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x38, 0x00, 0x70, 0x54, 0x00, 0x70, 0x70, 0x00, 0x54, 0x70,
+ 0x00, 0x38, 0x70, 0x00, 0x1c, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70,
+ 0x70, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38,
+ 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70, 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x38,
+ 0x38, 0x70, 0x38, 0x38, 0x70, 0x44, 0x38, 0x70, 0x54, 0x38, 0x70, 0x60, 0x38, 0x70, 0x70, 0x38, 0x60, 0x70,
+ 0x38, 0x54, 0x70, 0x38, 0x44, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70,
+ 0x70, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50,
+ 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70, 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x50,
+ 0x50, 0x70, 0x50, 0x50, 0x70, 0x58, 0x50, 0x70, 0x60, 0x50, 0x70, 0x68, 0x50, 0x70, 0x70, 0x50, 0x68, 0x70,
+ 0x50, 0x60, 0x70, 0x50, 0x58, 0x70, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40,
+ 0x40, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00,
+ 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40, 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x40, 0x10, 0x00, 0x40, 0x20, 0x00, 0x40, 0x30, 0x00, 0x40, 0x40, 0x00, 0x30, 0x40,
+ 0x00, 0x20, 0x40, 0x00, 0x10, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40,
+ 0x40, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20,
+ 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40, 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x20,
+ 0x20, 0x40, 0x20, 0x20, 0x40, 0x28, 0x20, 0x40, 0x30, 0x20, 0x40, 0x38, 0x20, 0x40, 0x40, 0x20, 0x38, 0x40,
+ 0x20, 0x30, 0x40, 0x20, 0x28, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40,
+ 0x40, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c,
+ 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40, 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x2c,
+ 0x2c, 0x40, 0x2c, 0x2c, 0x40, 0x30, 0x2c, 0x40, 0x34, 0x2c, 0x40, 0x3c, 0x2c, 0x40, 0x40, 0x2c, 0x3c, 0x40,
+ 0x2c, 0x34, 0x40, 0x2c, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const byte font[][5] = {
+ {0x00,0x00,0x00,0xff,0x00},
+ {0x5f,0xff,0x00,0x00,0x00},
+ {0x03,0x00,0x03,0xff,0x00},
+ {0x14,0x7f,0x14,0x7f,0x14},
+ {0x24,0x2a,0x7f,0x2a,0x12},
+ {0x61,0x10,0x08,0x04,0x43},
+ {0x38,0x4e,0x59,0x26,0x50},
+ {0x03,0xff,0x00,0x00,0x00},
+ {0x3e,0x41,0xff,0x00,0x00},
+ {0x41,0x3e,0xff,0x00,0x00},
+ {0x10,0x54,0x38,0x54,0x10},
+ {0x10,0x10,0x7c,0x10,0x10},
+ {0x80,0x40,0xff,0x00,0x00},
+ {0x10,0x10,0x10,0x10,0x10},
+ {0x40,0xff,0x00,0x00,0x00},
+ {0x60,0x10,0x08,0x04,0x03},
+
+ {0x3e,0x41,0x41,0x41,0x3e}, /* digits */
+ {0x04,0x02,0x7f,0xff,0x00},
+ {0x42,0x61,0x51,0x49,0x46},
+ {0x22,0x41,0x49,0x49,0x36},
+ {0x18,0x14,0x12,0x7f,0x10},
+ {0x27,0x45,0x45,0x45,0x39},
+ {0x3e,0x49,0x49,0x49,0x32},
+ {0x01,0x61,0x19,0x07,0x01},
+ {0x36,0x49,0x49,0x49,0x36},
+ {0x26,0x49,0x49,0x49,0x3e},
+
+ {0x44,0xff,0x00,0x00,0x00},
+ {0x80,0x44,0xff,0x00,0x00},
+ {0x10,0x28,0x44,0xff,0x00},
+ {0x28,0x28,0x28,0x28,0x28},
+ {0x44,0x28,0x10,0xff,0x00},
+ {0x02,0x01,0x51,0x09,0x06},
+ {0x3e,0x41,0x5d,0x5d,0x1e},
+
+ {0x7c,0x12,0x11,0x12,0x7c}, /* uppercase letters*/
+ {0x7f,0x49,0x49,0x49,0x36},
+ {0x3e,0x41,0x41,0x41,0x22},
+ {0x7f,0x41,0x41,0x22,0x1c},
+ {0x7f,0x49,0x49,0x49,0xff},
+ {0x7f,0x09,0x09,0x09,0xff},
+ {0x3e,0x41,0x41,0x49,0x3a},
+ {0x7f,0x08,0x08,0x08,0x7f},
+ {0x41,0x7f,0x41,0xff,0x00},
+ {0x20,0x40,0x40,0x3f,0xff},
+ {0x7f,0x08,0x14,0x22,0x41},
+ {0x7f,0x40,0x40,0x40,0xff},
+ {0x7f,0x02,0x04,0x02,0x7f},
+ {0x7f,0x02,0x0c,0x10,0x7f},
+ {0x3e,0x41,0x41,0x41,0x3e},
+ {0x7f,0x09,0x09,0x09,0x06},
+ {0x3e,0x41,0x51,0x21,0x5e},
+ {0x7f,0x09,0x19,0x29,0x46},
+ {0x26,0x49,0x49,0x49,0x32},
+ {0x01,0x01,0x7f,0x01,0x01},
+ {0x3f,0x40,0x40,0x40,0x3f},
+ {0x07,0x18,0x60,0x18,0x07},
+ {0x1f,0x60,0x18,0x60,0x1f},
+ {0x63,0x14,0x08,0x14,0x63},
+ {0x03,0x04,0x78,0x04,0x03},
+ {0x61,0x51,0x49,0x45,0x43},
+
+ {0x7f,0x41,0x41,0xff,0x00},
+ {0x03,0x04,0x08,0x10,0x60},
+ {0x41,0x41,0x7f,0xff,0x00},
+ {0x02,0x01,0x02,0xff,0x00},
+ {0x80,0x80,0x80,0x80,0x80},
+ {0x01,0x02,0xff,0x00,0x00},
+
+ {0x38,0x44,0x44,0x44,0x7c}, /* lowercase letters */
+ {0x7f,0x44,0x44,0x44,0x38},
+ {0x38,0x44,0x44,0x44,0x44},
+ {0x38,0x44,0x44,0x44,0x7f},
+ {0x38,0x54,0x54,0x54,0x58},
+ {0x04,0x7e,0x05,0x01,0xff},
+ {0x98,0xa4,0xa4,0xa4,0x7c},
+ {0x7f,0x04,0x04,0x04,0x78},
+ {0x7d,0xff,0x00,0x00,0x00},
+ {0x80,0x80,0x7d,0xff,0x00},
+ {0x7f,0x10,0x28,0x44,0xff},
+ {0x7f,0xff,0x00,0x00,0x00},
+ {0x7c,0x04,0x7c,0x04,0x78},
+ {0x7c,0x04,0x04,0x04,0x78},
+ {0x38,0x44,0x44,0x44,0x38},
+ {0xfc,0x24,0x24,0x24,0x18},
+ {0x18,0x24,0x24,0x24,0xfc},
+ {0x7c,0x08,0x04,0x04,0xff},
+ {0x48,0x54,0x54,0x54,0x24},
+ {0x04,0x3e,0x44,0x40,0xff},
+ {0x7c,0x40,0x40,0x40,0x3c},
+ {0x0c,0x30,0x40,0x30,0x0c},
+ {0x3c,0x40,0x3c,0x40,0x3c},
+ {0x44,0x28,0x10,0x28,0x44},
+ {0x9c,0xa0,0xa0,0xa0,0x7c},
+ {0x44,0x64,0x54,0x4c,0x44},
+
+ {0x08,0x36,0x41,0xff,0x00},
+ {0x77,0xff,0x00,0x00,0x00},
+ {0x41,0x36,0x08,0xff,0x00},
+ {0x02,0x01,0x02,0x01,0xff},
+ {0xff,0x00,0x00,0x00,0x00},
+
+ {0xfe,0x49,0x49,0x4e,0x30}, /* sharp S */
+
+ {0x7c,0x41,0x40,0x41,0x3c}, /* umlauts */
+
+ {0x04,0x06,0x7f,0x06,0x04}, /* arrows */
+ {0x20,0x60,0xfe,0x60,0x20},
+
+ {0x38,0x45,0x44,0x45,0x7c}, /* umlauts */
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0x79,0x14,0x12,0x14,0x79},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0x38,0x45,0x44,0x45,0x38},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0xff,0x00,0x00,0x00,0x00},
+ {0x3d,0x42,0x42,0x42,0x3d},
+ {0x3d,0x40,0x40,0x40,0x3d},
+};
+
+}
diff --git a/engines/supernova/sound.cpp b/engines/supernova/sound.cpp
new file mode 100644
index 0000000000..e7f3ce83bd
--- /dev/null
+++ b/engines/supernova/sound.cpp
@@ -0,0 +1,65 @@
+/* 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 "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+#include "audio/mods/protracker.h"
+#include "common/system.h"
+
+#include "supernova/resman.h"
+#include "supernova/sound.h"
+#include "supernova/supernova.h"
+
+namespace Supernova {
+
+Sound::Sound(Audio::Mixer *mixer, ResourceManager *resMan)
+ : _mixer(mixer)
+ , _resMan(resMan) {
+}
+
+void Sound::play(AudioId index) {
+ Audio::AudioStream *stream = _resMan->getSoundStream(index);
+
+ stop();
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, stream,
+ -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+}
+
+void Sound::play(MusicId index) {
+ Audio::AudioStream *stream = _resMan->getSoundStream(index);
+
+ stop();
+ _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, stream,
+ -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO);
+}
+
+bool Sound::isPlaying() {
+ return _mixer->isSoundHandleActive(_soundHandle);
+}
+
+void Sound::stop() {
+ if (_mixer->isSoundHandleActive(_soundHandle))
+ _mixer->stopHandle(_soundHandle);
+}
+
+}
diff --git a/engines/supernova/sound.h b/engines/supernova/sound.h
new file mode 100644
index 0000000000..100c9a372b
--- /dev/null
+++ b/engines/supernova/sound.h
@@ -0,0 +1,80 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SUPERNOVA_SOUND_H
+#define SUPERNOVA_SOUND_H
+
+#include "audio/mixer.h"
+
+namespace Supernova {
+
+class SupernovaEngine;
+class ResourceManager;
+
+enum AudioId {
+ kAudioFoundLocation, // 44|0
+ kAudioCrash, // 45|0
+ kAudioVoiceHalt, // 46|0
+ kAudioGunShot, // 46|2510
+ kAudioSmash, // 46|4020
+ kAudioVoiceSupernova, // 47|0
+ kAudioVoiceYeah, // 47|24010
+ kAudioRobotShock, // 48|0
+ kAudioRobotBreaks, // 48|2510
+ kAudioShock, // 48|10520
+ kAudioTurntable, // 48|13530
+ kAudioSiren, // 50|0
+ kAudioSnoring, // 50|12786
+ kAudioRocks, // 51|0
+ kAudioDeath, // 53|0
+ kAudioAlarm, // 54|0
+ kAudioSuccess, // 54|8010
+ kAudioSlideDoor, // 54|24020
+ kAudioDoorOpen, // 54|30030
+ kAudioDoorClose, // 54|31040
+ kAudioNumSamples
+};
+
+enum MusicId {
+ kMusicIntro = 49,
+ kMusicOutro = 52
+};
+
+class Sound {
+public:
+
+public:
+ Sound(Audio::Mixer *mixer, ResourceManager *resMan);
+
+ void play(AudioId index);
+ void play(MusicId index);
+ void stop();
+ bool isPlaying();
+private:
+ Audio::Mixer *_mixer;
+ ResourceManager *_resMan;
+ Audio::SoundHandle _soundHandle;
+};
+
+}
+
+#endif
diff --git a/engines/supernova/state.cpp b/engines/supernova/state.cpp
index e41edbf1d5..f50d665000 100644
--- a/engines/supernova/state.cpp
+++ b/engines/supernova/state.cpp
@@ -21,11 +21,13 @@
*/
#include "common/system.h"
+#include "graphics/cursorman.h"
#include "graphics/palette.h"
#include "gui/message.h"
+
+#include "supernova/screen.h"
#include "supernova/supernova.h"
#include "supernova/state.h"
-#include "graphics/cursorman.h"
namespace Supernova {
@@ -136,13 +138,13 @@ bool GameManager::deserialize(Common::ReadStream *in, int version) {
_inventoryScroll = in->readSint32LE();
_inventory.clear();
for (int i = 0; i < inventorySize; ++i) {
- RoomID objectRoom = static_cast<RoomID>(in->readSint32LE());
+ RoomId objectRoom = static_cast<RoomId>(in->readSint32LE());
int objectIndex = in->readSint32LE();
_inventory.add(*_rooms[objectRoom]->getObject(objectIndex));
}
// Rooms
- RoomID curRoomId = static_cast<RoomID>(in->readByte());
+ RoomId curRoomId = static_cast<RoomId>(in->readByte());
for (int i = 0; i < NUMROOMS; ++i) {
_rooms[i]->deserialize(in, version);
}
@@ -194,16 +196,16 @@ Object *Inventory::get(int index) const {
if (index < _numObjects)
return _inventory[index];
- return const_cast<Object *>(&Object::nullObject);
+ return _nullObject;
}
-Object *Inventory::get(ObjectID id) const {
+Object *Inventory::get(ObjectId id) const {
for (int i = 0; i < _numObjects; ++i) {
if (_inventory[i]->_id == id)
return _inventory[i];
}
- return const_cast<Object *>(&Object::nullObject);
+ return _nullObject;
}
@@ -275,19 +277,20 @@ static Common::String timeToString(int msec) {
return Common::String(s);
}
-StringID GameManager::guiCommands[] = {
+StringId GameManager::guiCommands[] = {
kStringCommandGo, kStringCommandLook, kStringCommandTake, kStringCommandOpen, kStringCommandClose,
kStringCommandPress, kStringCommandPull, kStringCommandUse, kStringCommandTalk, kStringCommandGive
};
-StringID GameManager::guiStatusCommands[] = {
+StringId GameManager::guiStatusCommands[] = {
kStringStatusCommandGo, kStringStatusCommandLook, kStringStatusCommandTake, kStringStatusCommandOpen, kStringStatusCommandClose,
kStringStatusCommandPress, kStringStatusCommandPull, kStringStatusCommandUse, kStringStatusCommandTalk, kStringStatusCommandGive
};
-GameManager::GameManager(SupernovaEngine *vm)
- : _inventory(_inventoryScroll)
- , _vm(vm) {
+GameManager::GameManager(SupernovaEngine *vm, Sound *sound)
+ : _inventory(&_nullObject, _inventoryScroll)
+ , _vm(vm)
+ , _sound(sound) {
initRooms();
changeRoom(INTRO);
initState();
@@ -351,11 +354,10 @@ void GameManager::destroyRooms() {
delete _rooms[OUTRO];
}
-
void GameManager::initState() {
- Object::setObjectNull(_currentInputObject);
- Object::setObjectNull(_inputObject[0]);
- Object::setObjectNull(_inputObject[1]);
+ _currentInputObject = &_nullObject;
+ _inputObject[0] = &_nullObject;
+ _inputObject[1] = &_nullObject;
_inputVerb = ACTION_WALK;
_processInput = false;
_guiEnabled = true;
@@ -370,7 +372,7 @@ void GameManager::initState() {
_oldTime = g_system->getMillis();
_timerPaused = 0;
_timePaused = false;
- _timer1 = 0;
+ _messageDuration = 0;
_animationTimer = 0;
_currentSentence = -1;
@@ -466,7 +468,7 @@ void GameManager::initGui() {
int cmdAvailableSpace = 320 - (cmdCount - 1) * 2;
for (int i = 0; i < cmdCount; ++i) {
const Common::String &text = _vm->getGameString(guiCommands[i]);
- cmdAvailableSpace -= _vm->textWidth(text);
+ cmdAvailableSpace -= Screen::textWidth(text);
}
int commandButtonX = 0;
@@ -476,7 +478,7 @@ void GameManager::initGui() {
if (i < cmdCount - 1) {
int space = cmdAvailableSpace / (cmdCount - i);
cmdAvailableSpace -= space;
- width = _vm->textWidth(text) + space;
+ width = Screen::textWidth(text) + space;
} else
width = 320 - commandButtonX;
@@ -503,6 +505,75 @@ void GameManager::initGui() {
_guiInventoryArrow[1].setTextPosition(273, 186);
}
+void GameManager::updateEvents() {
+ handleTime();
+ if (_animationEnabled && !_vm->_screen->isMessageShown() && _animationTimer == 0)
+ _currentRoom->animation();
+
+ if (_state._eventCallback != kNoFn && _state._time >= _state._eventTime) {
+ _vm->_allowLoadGame = false;
+ _vm->_allowSaveGame = false;
+ _state._eventTime = kMaxTimerValue;
+ EventFunction fn = _state._eventCallback;
+ _state._eventCallback = kNoFn;
+ switch (fn) {
+ case kNoFn:
+ break;
+ case kSupernovaFn:
+ supernovaEvent();
+ break;
+ case kGuardReturnedFn:
+ guardReturnedEvent();
+ break;
+ case kGuardWalkFn:
+ guardWalkEvent();
+ break;
+ case kTaxiFn:
+ taxiEvent();
+ break;
+ case kSearchStartFn:
+ searchStartEvent();
+ break;
+ }
+ _vm->_allowLoadGame = true;
+ _vm->_allowSaveGame = true;
+ return;
+ }
+
+ if (_state._alarmOn && _state._timeAlarm <= _state._time) {
+ _state._alarmOn = false;
+ alarm();
+ return;
+ }
+
+ _mouseClicked = false;
+ _keyPressed = false;
+ Common::Event event;
+ while (g_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ _keyPressed = true;
+ processInput(event.kbd);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ // fallthrough
+ case Common::EVENT_RBUTTONUP:
+ if (_currentRoom->getId() != INTRO && _sound->isPlaying())
+ return;
+ _mouseClicked = true;
+ // fallthrough
+ case Common::EVENT_MOUSEMOVE:
+ _mouseClickType = event.type;
+ _mouseX = event.mouse.x;
+ _mouseY = event.mouse.y;
+ if (_guiEnabled)
+ processInput();
+ break;
+ default:
+ break;
+ }
+ }
+}
void GameManager::processInput(Common::KeyState &state) {
_key = state;
@@ -529,14 +600,18 @@ void GameManager::processInput(Common::KeyState &state) {
_vm->quitGame();
}
break;
+ case Common::KEYCODE_d:
+ if (state.flags & Common::KBD_CTRL)
+ _vm->_console->attach();
+ break;
default:
break;
}
}
void GameManager::resetInputState() {
- Object::setObjectNull(_inputObject[0]);
- Object::setObjectNull(_inputObject[1]);
+ setObjectNull(_inputObject[0]);
+ setObjectNull(_inputObject[1]);
_inputVerb = ACTION_WALK;
_processInput = false;
_mouseClicked = false;
@@ -571,7 +646,7 @@ void GameManager::processInput() {
mouseLocation = onNone;
if (_mouseClickType == Common::EVENT_LBUTTONUP) {
- if (_vm->_messageDisplayed) {
+ if (_vm->_screen->isMessageShown()) {
// Hide the message and consume the event
_vm->removeMessage();
if (mouseLocation != onCmdButton)
@@ -583,7 +658,7 @@ void GameManager::processInput() {
case onInventory:
// Fallthrough
if (_inputVerb == ACTION_GIVE || _inputVerb == ACTION_USE) {
- if (Object::isNullObject(_inputObject[0])) {
+ if (isNullObject(_inputObject[0])) {
_inputObject[0] = _currentInputObject;
if (!_inputObject[0]->hasProperty(COMBINABLE))
_processInput = true;
@@ -593,7 +668,7 @@ void GameManager::processInput() {
}
} else {
_inputObject[0] = _currentInputObject;
- if (!Object::isNullObject(_currentInputObject))
+ if (!isNullObject(_currentInputObject))
_processInput = true;
}
break;
@@ -614,13 +689,13 @@ void GameManager::processInput() {
}
} else if (_mouseClickType == Common::EVENT_RBUTTONUP) {
- if (_vm->_messageDisplayed) {
+ if (_vm->_screen->isMessageShown()) {
// Hide the message and consume the event
_vm->removeMessage();
return;
}
- if (Object::isNullObject(_currentInputObject))
+ if (isNullObject(_currentInputObject))
return;
if (mouseLocation == onObject || mouseLocation == onInventory) {
@@ -666,8 +741,9 @@ void GameManager::processInput() {
for (int i = 0; (_currentRoom->getObject(i)->_id != INVALIDOBJECT) &&
(field == -1) && i < kMaxObject; i++) {
click = _currentRoom->getObject(i)->_click;
- if (click != 255 && _vm->_currentImage) {
- MSNImageDecoder::ClickField *clickField = _vm->_currentImage->_clickField;
+ const MSNImage *image = _vm->_screen->getCurrentImage();
+ if (click != 255 && image) {
+ const MSNImage::ClickField *clickField = image->_clickField;
do {
if ((_mouseX >= clickField[click].x1) && (_mouseX <= clickField[click].x2) &&
(_mouseY >= clickField[click].y1) && (_mouseY <= clickField[click].y2))
@@ -698,7 +774,7 @@ void GameManager::processInput() {
break;
}
- Object::setObjectNull(_currentInputObject);
+ setObjectNull(_currentInputObject);
_mouseField = field;
if (_mouseField >= 0 && _mouseField < 256)
@@ -737,6 +813,14 @@ void GameManager::processInput() {
}
}
+void GameManager::setObjectNull(Object *&obj) {
+ obj = &_nullObject;
+}
+
+bool GameManager::isNullObject(Object *obj) {
+ return obj == &_nullObject;
+}
+
void GameManager::corridorOnEntrance() {
if (_state._corridorSearch)
busted(0);
@@ -761,7 +845,7 @@ void GameManager::telomat(int nr) {
"Alga Hurz Li"
};
- StringID dial1[4];
+ StringId dial1[4];
dial1[0] = kStringTelomat1;
dial1[1] = kNoString;
dial1[2] = kStringTelomat3;
@@ -769,7 +853,7 @@ void GameManager::telomat(int nr) {
static byte rows1[3] = {1, 2, 1};
- StringID dial2[4];
+ StringId dial2[4];
dial2[0] = kStringTelomat4;
dial2[1] = kStringTelomat5;
dial2[2] = kStringTelomat6;
@@ -792,9 +876,9 @@ void GameManager::telomat(int nr) {
_vm->renderBox(0, 0, 320, 200, kColorDarkBlue);
_vm->renderText(kStringTelomat12, 50, 80, kColorGreen);
_vm->renderText(kStringTelomat13, 50, 91, kColorGreen);
- do
+ do {
edit(input, 50, 105, 30);
- while ((_key.keycode != Common::KEYCODE_RETURN) && (_key.keycode != Common::KEYCODE_ESCAPE));
+ } while ((_key.keycode != Common::KEYCODE_RETURN) && (_key.keycode != Common::KEYCODE_ESCAPE));
if (_key.keycode == Common::KEYCODE_ESCAPE) {
_vm->renderBox(0, 0, 320, 200, kColorBlack);
@@ -813,7 +897,7 @@ void GameManager::telomat(int nr) {
i >>= 1;
if (i == 4) {
_vm->renderText(kStringTelomat14, 50, 120, kColorGreen);
- wait2(10);
+ wait(10);
_vm->renderBox(0, 0, 320, 200, kColorBlack);
_vm->renderRoom(*_currentRoom);
_vm->paletteBrightness();
@@ -824,7 +908,7 @@ void GameManager::telomat(int nr) {
if ((i == nr) || _rooms[BCORRIDOR]->getObject(4 + i)->hasProperty(CAUGHT)) {
_vm->renderText(kStringTelomat15, 50, 120, kColorGreen);
- wait2(10);
+ wait(10);
_vm->renderBox(0, 0, 320, 200, kColorBlack);
_vm->renderRoom(*_currentRoom);
_vm->paletteBrightness();
@@ -834,12 +918,12 @@ void GameManager::telomat(int nr) {
}
_vm->renderText(kStringTelomat16, 50, 120, kColorGreen);
- wait2(10);
+ wait(10);
_vm->renderBox(0, 0, 320, 200, kColorBlack);
_vm->renderRoom(*_currentRoom);
_vm->paletteBrightness();
_vm->renderMessage(kStringTelomat17, kMessageTop, name2[i]);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
if (_state._nameSeen[nr]) {
Common::String string = _vm->getGameString(kStringTelomat2);
@@ -851,7 +935,7 @@ void GameManager::telomat(int nr) {
switch (dialog(3, rows1, dial1, 1)) {
case 1: _vm->renderMessage(kStringTelomat18, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
if ((_state._destination == 255) && !_rooms[BCORRIDOR]->isSectionVisible(7)) {
_state._eventTime = _state._time + ticksToMsec(150);
@@ -861,10 +945,10 @@ void GameManager::telomat(int nr) {
}
break;
case 0: _vm->renderMessage(kStringTelomat19, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
if (dialog(4, rows2, dial2, 0) != 3) {
- wait2(10);
+ wait(10);
say(kStringTelomat20);
}
_rooms[BCORRIDOR]->setSectionVisible(7, true);
@@ -882,13 +966,13 @@ void GameManager::telomat(int nr) {
_vm->renderBox(0, 0, 320, 200, kColorDarkBlue);
_vm->renderText(kStringTelomat21, 100, 90, kColorGreen);
input = "";
- do
+ do {
edit(input, 100, 105, 30);
- while ((_key.keycode != Common::KEYCODE_RETURN) && (_key.keycode != Common::KEYCODE_ESCAPE));
+ } while ((_key.keycode != Common::KEYCODE_RETURN) && (_key.keycode != Common::KEYCODE_ESCAPE));
if (_key.keycode == Common::KEYCODE_RETURN) {
_vm->renderText(kStringShipSleepCabin9, 100, 120, kColorGreen);
- wait2(10);
+ wait(10);
}
// fallthrough
case Common::KEYCODE_ESCAPE:
@@ -926,7 +1010,7 @@ void GameManager::guardNoticed() {
_vm->paletteFadeIn();
_vm->renderImage(2);
reply(kStringGuardNoticed1, 2, 5);
- wait2(2);
+ wait(2);
reply(kStringGuardNoticed2, 2, 5);
_vm->paletteFadeOut();
_currentRoom->setSectionVisible(2, false);
@@ -947,19 +1031,19 @@ void GameManager::busted(int i) {
i = 5;
if (!_currentRoom->getObject(0)->hasProperty(OPENED)) {
_vm->renderImage(i - 1);
- _vm->playSound(kAudioDoorOpen);
- wait2(2);
+ _sound->play(kAudioDoorOpen);
+ wait(2);
}
_vm->renderImage(i);
- wait2(3);
+ wait(3);
_vm->renderImage(i + 3);
- _vm->playSound(kAudioVoiceHalt);
+ _sound->play(kAudioVoiceHalt);
_vm->renderImage(i);
- wait2(5);
+ wait(5);
if (_currentRoom->getId() == OFFICE_L2)
i = 13;
_vm->renderImage(i + 1);
- wait2(3);
+ wait(3);
_vm->renderImage(i + 2);
shot(0, 0);
} else if (_currentRoom->getId() == BCORRIDOR)
@@ -973,8 +1057,8 @@ void GameManager::busted(int i) {
else
_vm->renderImage(33); // above
}
- _vm->playSound(kAudioVoiceHalt);
- wait2(3);
+ _sound->play(kAudioVoiceHalt);
+ wait(3);
shot(0, 0);
}
@@ -1025,7 +1109,7 @@ void GameManager::supernovaEvent() {
CursorMan.showMouse(false);
if (_currentRoom->getId() <= CAVE) {
_vm->renderMessage(kStringSupernova1);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->paletteFadeOut();
changeRoom(MEETUP);
@@ -1038,7 +1122,7 @@ void GameManager::supernovaEvent() {
_vm->paletteFadeIn();
}
_vm->renderMessage(kStringSupernova2);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->setCurrentImage(26);
_vm->renderImage(0);
@@ -1046,28 +1130,28 @@ void GameManager::supernovaEvent() {
novaScroll();
_vm->paletteFadeOut();
_vm->renderBox(0, 0, 320, 200, kColorBlack);
- _vm->_menuBrightness = 255;
+ _vm->_screen->setGuiBrightness(255);
_vm->paletteBrightness();
if (_currentRoom->getId() == GLIDER) {
_vm->renderMessage(kStringSupernova3);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
_vm->renderRoom(*_currentRoom);
_vm->paletteFadeIn();
_vm->renderMessage(kStringSupernova4, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringSupernova5, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringSupernova6, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringSupernova7, kMessageTop);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
changeRoom(MEETUP2);
_rooms[MEETUP2]->setSectionVisible(1, true);
@@ -1077,9 +1161,9 @@ void GameManager::supernovaEvent() {
_inventory.remove(*(_rooms[ROGER]->getObject(8)));
} else {
_vm->renderMessage(kStringSupernova8);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
- _vm->_menuBrightness = 0;
+ _vm->_screen->setGuiBrightness(0);
_vm->paletteBrightness();
changeRoom(MEETUP2);
if (_rooms[ROGER]->getObject(3)->hasProperty(CARRIED) && !_rooms[GLIDER]->isSectionVisible(5)) {
@@ -1121,7 +1205,7 @@ void GameManager::walk(int imgId) {
_vm->renderImage(_prevImgId + 128);
_vm->renderImage(imgId);
_prevImgId = imgId;
- wait2(3);
+ wait(3);
}
void GameManager::guardWalkEvent() {
@@ -1130,14 +1214,14 @@ void GameManager::guardWalkEvent() {
_rooms[BCORRIDOR]->getObject(_state._origin + 4)->hasProperty(OPENED));
_rooms[BCORRIDOR]->getObject(_state._origin + 4)->disableProperty(OCCUPIED);
if (_currentRoom == _rooms[BCORRIDOR]) {
- if (_vm->_messageDisplayed)
+ if (_vm->_screen->isMessageShown())
_vm->removeMessage();
if (!behind) {
_vm->renderImage(_state._origin + 1);
_prevImgId = _state._origin + 1;
- _vm->playSound(kAudioDoorOpen);
- wait2(3);
+ _sound->play(kAudioDoorOpen);
+ wait(3);
}
int imgId;
@@ -1158,13 +1242,13 @@ void GameManager::guardWalkEvent() {
}
_vm->renderImage(imgId);
if (!behind) {
- wait2(3);
+ wait(3);
_vm->renderImage(_prevImgId + 128);
- _vm->playSound(kAudioDoorClose);
+ _sound->play(kAudioDoorClose);
}
_prevImgId = imgId;
- wait2(3);
+ wait(3);
switch (_state._origin) {
case 0:
walk(12);
@@ -1221,12 +1305,12 @@ void GameManager::guardWalkEvent() {
if (behind) {
_vm->renderImage(_state._destination + 1);
- _vm->playSound(kAudioDoorOpen);
- wait2(3);
+ _sound->play(kAudioDoorOpen);
+ wait(3);
_vm->renderImage(_prevImgId + 128);
- wait2(3);
+ wait(3);
_vm->renderImage(_state._destination + 1 + 128);
- _vm->playSound(kAudioDoorClose);
+ _sound->play(kAudioDoorClose);
_rooms[BCORRIDOR]->getObject(_state._destination + 4)->setProperty(OCCUPIED);
_state._destination = 255;
} else if (_rooms[BCORRIDOR]->isSectionVisible(_state._destination + 1)) {
@@ -1236,7 +1320,7 @@ void GameManager::guardWalkEvent() {
_state._eventTime = _state._time + ticksToMsec(60);
_state._eventCallback = kGuardWalkFn;
} else {
- wait2(18);
+ wait(18);
SWAP(_state._origin, _state._destination);
_state._eventCallback = kGuardWalkFn;
}
@@ -1266,7 +1350,7 @@ void GameManager::taxiEvent() {
_vm->renderImage(1);
_vm->renderImage(2);
- _vm->playSound(kAudioRocks);
+ _sound->play(kAudioRocks);
screenShake();
_vm->renderImage(9);
_currentRoom->getObject(1)->setProperty(OPENED);
@@ -1274,7 +1358,7 @@ void GameManager::taxiEvent() {
_currentRoom->setSectionVisible(2, false);
_vm->renderImage(3);
for (int i = 4; i <= 8; i++) {
- wait2(2);
+ wait(2);
_vm->renderImage(invertSection(i - 1));
_vm->renderImage(i);
}
@@ -1292,7 +1376,7 @@ void GameManager::great(uint number) {
if (number && (_state._greatFlag & (1 << number)))
return;
- _vm->playSound(kAudioSuccess);
+ _sound->play(kAudioSuccess);
_state._greatFlag |= 1 << number;
}
@@ -1321,7 +1405,7 @@ void GameManager::sentence(int number, bool brightness) {
}
}
-void GameManager::say(StringID textId) {
+void GameManager::say(StringId textId) {
Common::String str = _vm->getGameString(textId);
if (!str.empty())
say(str.c_str());
@@ -1351,7 +1435,7 @@ void GameManager::say(const char *text) {
_vm->renderBox(0, 138, 320, 62, kColorBlack);
}
-void GameManager::reply(StringID textId, int aus1, int aus2) {
+void GameManager::reply(StringId textId, int aus1, int aus2) {
Common::String str = _vm->getGameString(textId);
if (!str.empty())
reply(str.c_str(), aus1, aus2);
@@ -1375,7 +1459,7 @@ void GameManager::reply(const char *text, int aus1, int aus2) {
_vm->removeMessage();
}
-int GameManager::dialog(int num, byte rowLength[6], StringID text[6], int number) {
+int GameManager::dialog(int num, byte rowLength[6], StringId text[6], int number) {
_vm->_allowLoadGame = false;
_guiEnabled = false;
@@ -1407,7 +1491,12 @@ int GameManager::dialog(int num, byte rowLength[6], StringID text[6], int number
_currentSentence = -1;
do {
- mouseInput3();
+ do {
+ updateEvents();
+ mousePosDialog(_mouseX, _mouseY);
+ g_system->updateScreen();
+ g_system->delayMillis(_vm->_delay);
+ } while (!_mouseClicked && !_vm->shouldQuit());
} while (_currentSentence == -1 && !_vm->shouldQuit());
_vm->renderBox(0, 138, 320, 62, kColorBlack);
@@ -1443,7 +1532,7 @@ void GameManager::turnOn() {
return;
_state._powerOff = false;
- _vm->_brightness = 255;
+ _vm->_screen->setViewportBrightness(255);
_rooms[SLEEP]->setSectionVisible(1, false);
_rooms[SLEEP]->setSectionVisible(2, false);
_rooms[COCKPIT]->setSectionVisible(22, false);
@@ -1462,7 +1551,7 @@ void GameManager::takeObject(Object &obj) {
void GameManager::drawCommandBox() {
for (int i = 0; i < ARRAYSIZE(_guiCommandButton); ++i) {
_vm->renderBox(_guiCommandButton[i]);
- int space = (_guiCommandButton[i].width() - _vm->textWidth(_guiCommandButton[i].getText())) / 2;
+ int space = (_guiCommandButton[i].width() - Screen::textWidth(_guiCommandButton[i].getText())) / 2;
_vm->renderText(_guiCommandButton[i].getText(),
_guiCommandButton[i].getTextPos().x + space,
_guiCommandButton[i].getTextPos().y,
@@ -1491,7 +1580,7 @@ void GameManager::drawInventory() {
uint16 GameManager::getKeyInput(bool blockForPrintChar) {
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ updateEvents();
if (_keyPressed) {
if (blockForPrintChar) {
if (Common::isPrint(_key.keycode) ||
@@ -1521,7 +1610,7 @@ uint16 GameManager::getKeyInput(bool blockForPrintChar) {
Common::EventType GameManager::getMouseInput() {
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ updateEvents();
if (_mouseClicked)
return _mouseClickType;
g_system->updateScreen();
@@ -1532,7 +1621,7 @@ Common::EventType GameManager::getMouseInput() {
void GameManager::getInput() {
while (!_vm->shouldQuit()) {
- _vm->updateEvents();
+ updateEvents();
if (_mouseClicked || _keyPressed)
break;
g_system->updateScreen();
@@ -1540,15 +1629,6 @@ void GameManager::getInput() {
}
}
-void GameManager::mouseInput3() {
- do {
- _vm->updateEvents();
- mousePosDialog(_mouseX, _mouseY);
- g_system->updateScreen();
- g_system->delayMillis(_vm->_delay);
- } while (!_mouseClicked && !_vm->shouldQuit());
-}
-
void GameManager::roomBrightness() {
_roomBrightness = 255;
if ((_currentRoom->getId() != OUTSIDE) && (_currentRoom->getId() < ROCKS) && _state._powerOff)
@@ -1558,22 +1638,22 @@ void GameManager::roomBrightness() {
else if ((_currentRoom->getId() == GUARD3) && _state._powerOff)
_roomBrightness = 0;
- if (_vm->_brightness != 0)
- _vm->_brightness = _roomBrightness;
+ if (_vm->_screen->getViewportBrightness() != 0)
+ _vm->_screen->setViewportBrightness(_roomBrightness);
_vm->paletteBrightness();
}
-void GameManager::changeRoom(RoomID id) {
+void GameManager::changeRoom(RoomId id) {
_currentRoom = _rooms[id];
_newRoom = true;
}
-void GameManager::wait2(int ticks) {
+void GameManager::wait(int ticks) {
int32 end = _state._time + ticksToMsec(ticks);
do {
g_system->delayMillis(_vm->_delay);
- _vm->updateEvents();
+ updateEvents();
g_system->updateScreen();
} while (_state._time < end && !_vm->shouldQuit());
}
@@ -1582,7 +1662,7 @@ void GameManager::waitOnInput(int ticks) {
int32 end = _state._time + ticksToMsec(ticks);
do {
g_system->delayMillis(_vm->_delay);
- _vm->updateEvents();
+ updateEvents();
g_system->updateScreen();
} while (_state._time < end && !_vm->shouldQuit() && !_keyPressed && !_mouseClicked);
}
@@ -1592,7 +1672,7 @@ bool GameManager::waitOnInput(int ticks, Common::KeyCode &keycode) {
int32 end = _state._time + ticksToMsec(ticks);
do {
g_system->delayMillis(_vm->_delay);
- _vm->updateEvents();
+ updateEvents();
g_system->updateScreen();
if (_keyPressed) {
keycode = _key.keycode;
@@ -1652,14 +1732,14 @@ void GameManager::saveTime() {
void GameManager::screenShake() {
for (int i = 0; i < 12; ++i) {
_vm->_system->setShakePos(8);
- wait2(1);
+ wait(1);
_vm->_system->setShakePos(0);
- wait2(1);
+ wait(1);
}
}
void GameManager::shock() {
- _vm->playSound(kAudioShock);
+ _sound->play(kAudioShock);
dead(kStringShock);
}
@@ -1704,24 +1784,24 @@ void GameManager::edit(Common::String &input, int x, int y, uint length) {
kScreenWidth - x : (length + 1) * (kFontWidth + 2);
while (isEditing) {
- _vm->_textCursorX = x;
- _vm->_textCursorY = y;
- _vm->_textColor = kColorWhite99;
+ _vm->_screen->setTextCursorPos(x, y);
+ _vm->_screen->setTextCursorColor(kColorWhite99);
_vm->renderBox(x, y - 1, overdrawWidth, 9, kColorDarkBlue);
for (uint i = 0; i < input.size(); ++i) {
// Draw char highlight depending on cursor position
if (i == cursorIndex) {
- _vm->renderBox(_vm->_textCursorX, y - 1, _vm->textWidth(input[i]), 9, kColorWhite99);
- _vm->_textColor = kColorDarkBlue;
+ _vm->renderBox(_vm->_screen->getTextCursorPos().x, y - 1,
+ Screen::textWidth(input[i]), 9, kColorWhite99);
+ _vm->_screen->setTextCursorColor(kColorDarkBlue);
_vm->renderText(input[i]);
- _vm->_textColor = kColorWhite99;
+ _vm->_screen->setTextCursorColor(kColorWhite99);
} else
_vm->renderText(input[i]);
}
if (cursorIndex == input.size()) {
- _vm->renderBox(_vm->_textCursorX + 1, y - 1, 6, 9, kColorDarkBlue);
- _vm->renderBox(_vm->_textCursorX , y - 1, 1, 9, kColorWhite99);
+ _vm->renderBox(_vm->_screen->getTextCursorPos().x + 1, y - 1, 6, 9, kColorDarkBlue);
+ _vm->renderBox(_vm->_screen->getTextCursorPos().x, y - 1, 1, 9, kColorWhite99);
}
getKeyInput(true);
@@ -1767,15 +1847,15 @@ void GameManager::edit(Common::String &input, int x, int y, uint length) {
void GameManager::shot(int a, int b) {
if (a)
_vm->renderImage(a);
- _vm->playSound(kAudioGunShot);
- wait2(2);
+ _sound->play(kAudioGunShot);
+ wait(2);
if (b)
_vm->renderImage(b);
- wait2(2);
+ wait(2);
if (a)
_vm->renderImage(a);
- _vm->playSound(kAudioGunShot);
- wait2(2);
+ _sound->play(kAudioGunShot);
+ wait(2);
if (b)
_vm->renderImage(b);
@@ -1801,7 +1881,7 @@ void GameManager::drawStatus() {
_vm->renderBox(0, 140, 320, 9, kColorWhite25);
_vm->renderText(_vm->getGameString(guiStatusCommands[index]), 1, 141, kColorDarkGreen);
- if (Object::isNullObject(_inputObject[0]))
+ if (isNullObject(_inputObject[0]))
_vm->renderText(_currentInputObject->_name);
else {
_vm->renderText(_inputObject[0]->_name);
@@ -1832,19 +1912,18 @@ void GameManager::closeLocker(const Room *room, Object *obj, Object *lock, int s
}
}
-void GameManager::dead(StringID messageId) {
+void GameManager::dead(StringId messageId) {
_vm->paletteFadeOut();
_guiEnabled = false;
_vm->setCurrentImage(11);
_vm->renderImage(0);
_vm->renderMessage(messageId);
- _vm->playSound(kAudioDeath);
+ _sound->play(kAudioDeath);
_vm->paletteFadeIn();
getInput();
_vm->paletteFadeOut();
_vm->removeMessage();
- // TODO: Load screen
destroyRooms();
initRooms();
initState();
@@ -1926,10 +2005,10 @@ bool GameManager::genericInteract(Action verb, Object &obj1, Object &obj2) {
}
} else if ((verb == ACTION_LOOK) && (obj1._id == NEWSPAPER)) {
_vm->renderMessage(kStringGenericInteract_10);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringGenericInteract_11);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->setCurrentImage(2);
_vm->renderImage(0);
@@ -2127,7 +2206,7 @@ bool GameManager::genericInteract(Action verb, Object &obj1, Object &obj2) {
_vm->renderMessage(kStringGenericInteract_30);
else if ((verb == ACTION_LOOK) && (obj1._id == BOOK2)) {
_vm->renderMessage(kStringGenericInteract_31);
- waitOnInput(_timer1);
+ waitOnInput(_messageDuration);
_vm->removeMessage();
_vm->renderMessage(kStringGenericInteract_32);
} else
@@ -2192,7 +2271,7 @@ void GameManager::handleInput() {
byte i = _inputObject[0]->_click;
_inputObject[0]->_click = _inputObject[0]->_click2;
_inputObject[0]->_click2 = i;
- _vm->playSound(kAudioDoorOpen);
+ _sound->play(kAudioDoorOpen);
}
break;
@@ -2211,7 +2290,7 @@ void GameManager::handleInput() {
byte i = _inputObject[0]->_click;
_inputObject[0]->_click = _inputObject[0]->_click2;
_inputObject[0]->_click2 = i;
- _vm->playSound(kAudioDoorClose);
+ _sound->play(kAudioDoorClose);
}
break;
@@ -2230,7 +2309,7 @@ void GameManager::handleInput() {
}
void GameManager::executeRoom() {
- if (_processInput && !_vm->_messageDisplayed && _guiEnabled) {
+ if (_processInput && !_vm->_screen->isMessageShown() && _guiEnabled) {
handleInput();
if (_mouseClicked) {
Common::Event event;
@@ -2246,7 +2325,7 @@ void GameManager::executeRoom() {
}
if (_guiEnabled) {
- if (!_vm->_messageDisplayed) {
+ if (!_vm->_screen->isMessageShown()) {
g_system->fillScreen(kColorBlack);
_vm->renderRoom(*_currentRoom);
}
@@ -2257,7 +2336,7 @@ void GameManager::executeRoom() {
}
roomBrightness();
- if (_vm->_brightness == 0)
+ if (_vm->_screen->getViewportBrightness() == 0)
_vm->paletteFadeIn();
if (!_currentRoom->hasSeen() && _newRoom) {
@@ -2269,31 +2348,31 @@ void GameManager::executeRoom() {
void GameManager::guardShot() {
_vm->renderImage(2);
_vm->renderImage(5);
- wait2(3);
+ wait(3);
_vm->renderImage(2);
- _vm->playSound(kAudioVoiceHalt);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- wait2(1);
+ _sound->play(kAudioVoiceHalt);
+ while (_sound->isPlaying())
+ wait(1);
_vm->renderImage(5);
- wait2(5);
+ wait(5);
_vm->renderImage(3);
- wait2(3);
+ wait(3);
shot(4, 3);
}
void GameManager::guard3Shot() {
_vm->renderImage(1);
- wait2(3);
- _vm->playSound(kAudioVoiceHalt); // 46/0
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle))
- wait2(1);
+ wait(3);
+ _sound->play(kAudioVoiceHalt); // 46/0
+ while (_sound->isPlaying())
+ wait(1);
- wait2(5);
+ wait(5);
_vm->renderImage(2);
- wait2(3);
+ wait(3);
shot(3,2);
}
@@ -2337,12 +2416,12 @@ void GameManager::alarmSound() {
_vm->removeMessage();
_vm->renderMessage(kStringAlarm);
- int32 end = _state._time + ticksToMsec(_timer1);
+ int32 end = _state._time + ticksToMsec(_messageDuration);
do {
- _vm->playSound(kAudioAlarm);
- while (_vm->_mixer->isSoundHandleActive(_vm->_soundHandle)) {
+ _sound->play(kAudioAlarm);
+ while (_sound->isPlaying()) {
g_system->delayMillis(_vm->_delay);
- _vm->updateEvents();
+ updateEvents();
g_system->updateScreen();
}
} while (_state._time < end && !_vm->shouldQuit());
diff --git a/engines/supernova/state.h b/engines/supernova/state.h
index ab21842296..7d7b2284ad 100644
--- a/engines/supernova/state.h
+++ b/engines/supernova/state.h
@@ -23,9 +23,11 @@
#ifndef SUPERNOVA_STATE_H
#define SUPERNOVA_STATE_H
+#include "common/events.h"
#include "common/rect.h"
#include "common/keyboard.h"
#include "supernova/rooms.h"
+#include "supernova/sound.h"
namespace Supernova {
@@ -63,8 +65,9 @@ struct GameState {
class Inventory {
public:
- Inventory(int &inventoryScroll)
+ Inventory(Object *nullObject, int &inventoryScroll)
: _numObjects(0)
+ , _nullObject(nullObject)
, _inventoryScroll(inventoryScroll)
{}
@@ -72,11 +75,12 @@ public:
void remove(Object &obj);
void clear();
Object *get(int index) const;
- Object *get(ObjectID id) const;
+ Object *get(ObjectId id) const;
int getSize() const { return _numObjects; }
private:
Object *_inventory[kMaxCarry];
+ Object *_nullObject;
int &_inventoryScroll;
int _numObjects;
};
@@ -121,18 +125,20 @@ private:
class GameManager {
public:
- GameManager(SupernovaEngine *vm);
+ GameManager(SupernovaEngine *vm, Sound *sound);
~GameManager();
+ void updateEvents();
void processInput(Common::KeyState &state);
void processInput();
void executeRoom();
bool serialize(Common::WriteStream *out);
bool deserialize(Common::ReadStream *in, int version);
- static StringID guiCommands[];
- static StringID guiStatusCommands[];
+ static StringId guiCommands[];
+ static StringId guiStatusCommands[];
SupernovaEngine *_vm;
+ Sound *_sound;
Common::KeyState _key;
Common::EventType _mouseClickType;
bool _mouseClicked;
@@ -150,13 +156,13 @@ public:
bool _animationEnabled;
byte _roomBrightness;
Action _inputVerb;
+ Object _nullObject;
Object *_currentInputObject;
Object *_inputObject[2];
- bool _waitEvent;
int32 _oldTime;
uint _timePaused;
bool _timerPaused;
- int32 _timer1;
+ int32 _messageDuration;
int32 _animationTimer;
int _inventoryScroll;
int _exitList[25];
@@ -166,11 +172,13 @@ public:
// Dialog
int _currentSentence;
int _sentenceNumber[6];
- StringID _texts[6];
+ StringId _texts[6];
byte _rows[6];
byte _rowsStart[6];
void takeObject(Object &obj);
+ void setObjectNull(Object *&obj);
+ bool isNullObject(Object *obj);
void initState();
void initRooms();
@@ -184,8 +192,7 @@ public:
Common::EventType getMouseInput();
uint16 getKeyInput(bool blockForPrintChar = false);
void getInput();
- void mouseInput3();
- void wait2(int ticks);
+ void wait(int ticks);
void waitOnInput(int ticks);
bool waitOnInput(int ticks, Common::KeyCode &keycode);
void turnOff();
@@ -203,7 +210,7 @@ public:
void drawStatus();
void drawCommandBox();
void drawInventory();
- void changeRoom(RoomID id);
+ void changeRoom(RoomId id);
void resetInputState();
void handleInput();
void handleTime();
@@ -211,12 +218,12 @@ public:
void loadTime();
void saveTime();
void setAnimationTimer(int ticks);
- void dead(StringID messageId);
- int dialog(int num, byte rowLength[6], StringID text[6], int number);
+ void dead(StringId messageId);
+ int dialog(int num, byte rowLength[6], StringId text[6], int number);
void sentence(int number, bool brightness);
- void say(StringID textId);
+ void say(StringId textId);
void say(const char *text);
- void reply(StringID textId, int aus1, int aus2);
+ void reply(StringId textId, int aus1, int aus2);
void reply(const char *text, int aus1, int aus2);
void mousePosDialog(int x, int y);
void shot(int a, int b);
diff --git a/engines/supernova/supernova.cpp b/engines/supernova/supernova.cpp
index 50731ae52f..c47e476de7 100644
--- a/engines/supernova/supernova.cpp
+++ b/engines/supernova/supernova.cpp
@@ -20,7 +20,6 @@
*
*/
-#include "audio/mods/protracker.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/debug-channels.h"
@@ -42,36 +41,14 @@
#include "graphics/thumbnail.h"
#include "gui/saveload.h"
+#include "supernova/resman.h"
+#include "supernova/screen.h"
+#include "supernova/sound.h"
#include "supernova/supernova.h"
#include "supernova/state.h"
namespace Supernova {
-const AudioInfo audioInfo[kAudioNumSamples] = {
- {44, 0, -1},
- {45, 0, -1},
- {46, 0, 2510},
- {46, 2510, 4020},
- {46, 4020, -1},
- {47, 0, 24010},
- {47, 24010, -1},
- {48, 0, 2510},
- {48, 2510, 10520},
- {48, 10520, 13530},
- {48, 13530, -1},
- {50, 0, 12786},
- {50, 12786, -1},
- {51, 0, -1},
- {53, 0, -1},
- {54, 0, 8010},
- {54, 8010, 24020},
- {54, 24020, 30030},
- {54, 30030, 31040},
- {54, 31040, -1}
-};
-
-const Object Object::nullObject;
-
ObjectType operator|(ObjectType a, ObjectType b) {
return static_cast<ObjectType>(+a | +b);
}
@@ -98,74 +75,37 @@ ObjectType &operator^=(ObjectType &a, ObjectType b) {
SupernovaEngine::SupernovaEngine(OSystem *syst)
: Engine(syst)
- , _console(NULL)
- , _gm(NULL)
- , _currentImage(NULL)
- , _soundMusicIntro(NULL)
- , _soundMusicOutro(NULL)
- , _rnd("supernova")
- , _brightness(255)
- , _menuBrightness(255)
+ , _console(nullptr)
+ , _gm(nullptr)
+ , _sound(nullptr)
+ , _resMan(nullptr)
+ , _screen(nullptr)
, _delay(33)
, _textSpeed(kTextSpeed[2])
- , _screenWidth(320)
- , _screenHeight(200)
- , _messageDisplayed(false)
, _allowLoadGame(true)
- , _allowSaveGame(true)
-{
-// const Common::FSNode gameDataDir(ConfMan.get("path"));
-// SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
-
+ , _allowSaveGame(true) {
if (ConfMan.hasKey("textspeed"))
_textSpeed = ConfMan.getInt("textspeed");
- // setup engine specific debug channels
DebugMan.addDebugChannel(kDebugGeneral, "general", "Supernova general debug channel");
}
SupernovaEngine::~SupernovaEngine() {
DebugMan.clearAllDebugChannels();
- delete _currentImage;
delete _console;
delete _gm;
- delete _soundMusicIntro;
- delete _soundMusicOutro;
+ delete _sound;
+ delete _resMan;
+ delete _screen;
}
Common::Error SupernovaEngine::run() {
- Graphics::ModeList modes;
- modes.push_back(Graphics::Mode(320, 200));
- modes.push_back(Graphics::Mode(640, 480));
- initGraphicsModes(modes);
- initGraphics(_screenWidth, _screenHeight);
-
- Common::Error status = loadGameStrings();
- if (status.getCode() != Common::kNoError)
- return status;
-
- _gm = new GameManager(this);
- _console = new Console(this, _gm);
-
- initData();
- initPalette();
-
- CursorMan.replaceCursor(_mouseNormal, 16, 16, 0, 0, kColorCursorTransparent);
- CursorMan.replaceCursorPalette(initVGAPalette, 0, 16);
- CursorMan.showMouse(true);
-
- setTotalPlayTime(0);
-
- int saveSlot = ConfMan.getInt("save_slot");
- if (saveSlot >= 0) {
- if (loadGameState(saveSlot).getCode() != Common::kNoError)
- error("Failed to load save game from slot %i", saveSlot);
- }
+ init();
while (!shouldQuit()) {
uint32 start = _system->getMillis();
- updateEvents();
+ _gm->updateEvents();
_gm->executeRoom();
_console->onFrame();
_system->updateScreen();
@@ -174,89 +114,34 @@ Common::Error SupernovaEngine::run() {
_system->delayMillis(end);
}
- stopSound();
+ _mixer->stopAll();
return Common::kNoError;
}
-void SupernovaEngine::updateEvents() {
- _gm->handleTime();
- if (_gm->_animationEnabled && !_messageDisplayed && _gm->_animationTimer == 0)
- _gm->_currentRoom->animation();
-
- if (_gm->_state._eventCallback != kNoFn && _gm->_state._time >= _gm->_state._eventTime) {
- _allowLoadGame = false;
- _allowSaveGame = false;
- _gm->_state._eventTime = kMaxTimerValue;
- EventFunction fn = _gm->_state._eventCallback;
- _gm->_state._eventCallback = kNoFn;
- switch (fn) {
- case kNoFn:
- break;
- case kSupernovaFn:
- _gm->supernovaEvent();
- break;
- case kGuardReturnedFn:
- _gm->guardReturnedEvent();
- break;
- case kGuardWalkFn:
- _gm->guardWalkEvent();
- break;
- case kTaxiFn:
- _gm->taxiEvent();
- break;
- case kSearchStartFn:
- _gm->searchStartEvent();
- break;
- }
- _allowLoadGame = true;
- _allowSaveGame = true;
- return;
- }
-
- if (_gm->_state._alarmOn && _gm->_state._timeAlarm <= _gm->_state._time) {
- _gm->_state._alarmOn = false;
- _gm->alarm();
- return;
- }
+void SupernovaEngine::init() {
+ Graphics::ModeList modes;
+ modes.push_back(Graphics::Mode(320, 200));
+ modes.push_back(Graphics::Mode(640, 480));
+ initGraphicsModes(modes);
+ initGraphics(320, 200);
- _gm->_mouseClicked = false;
- _gm->_keyPressed = false;
- Common::Event event;
- while (g_system->getEventManager()->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- _gm->_keyPressed = true;
- if (event.kbd.keycode == Common::KEYCODE_d &&
- (event.kbd.flags & Common::KBD_CTRL)) {
- _console->attach();
- }
- if (event.kbd.keycode == Common::KEYCODE_x &&
- (event.kbd.flags & Common::KBD_CTRL)) {
- // TODO: Draw exit box
- }
+ Common::Error status = loadGameStrings();
+ if (status.getCode() != Common::kNoError)
+ error("Failed reading game strings");
- _gm->processInput(event.kbd);
- break;
+ _resMan = new ResourceManager();
+ _sound = new Sound(_mixer, _resMan);
+ _gm = new GameManager(this, _sound);
+ _screen = new Screen(this, _gm, _resMan);
+ _console = new Console(this, _gm);
- case Common::EVENT_LBUTTONUP:
- // fallthrough
- case Common::EVENT_RBUTTONUP:
- if (_gm->_currentRoom->getId() != INTRO && _mixer->isSoundHandleActive(_soundHandle))
- return;
- _gm->_mouseClicked = true;
- // fallthrough
- case Common::EVENT_MOUSEMOVE:
- _gm->_mouseClickType = event.type;
- _gm->_mouseX = event.mouse.x;
- _gm->_mouseY = event.mouse.y;
- if (_gm->_guiEnabled)
- _gm->processInput();
- break;
+ setTotalPlayTime(0);
- default:
- break;
- }
+ int saveSlot = ConfMan.getInt("save_slot");
+ if (saveSlot >= 0) {
+ if (loadGameState(saveSlot).getCode() != Common::kNoError)
+ error("Failed to load save game from slot %i", saveSlot);
}
}
@@ -337,440 +222,133 @@ Common::Error SupernovaEngine::loadGameStrings() {
return Common::kReadingFailed;
}
-void SupernovaEngine::initData() {
- // Sound
- // Note:
- // - samples start with a header of 6 bytes: 01 SS SS 00 AD 00
- // where SS SS (LE uint16) is the size of the sound sample + 2
- // - samples end with a footer of 4 bytes: 00 00
- // Skip those in the buffer
- Common::File file;
-
- for (int i = 0; i < kAudioNumSamples; ++i) {
- if (!file.open(Common::String::format("msn_data.%03d", audioInfo[i]._filenumber))) {
- error("File %s could not be read!", file.getName());
- }
-
- if (audioInfo[i]._offsetEnd == -1) {
- file.seek(0, SEEK_END);
- _soundSamples[i]._length = file.pos() - audioInfo[i]._offsetStart - 10;
- } else {
- _soundSamples[i]._length = audioInfo[i]._offsetEnd - audioInfo[i]._offsetStart - 10;
- }
- _soundSamples[i]._buffer = new byte[_soundSamples[i]._length];
- file.seek(audioInfo[i]._offsetStart + 6);
- file.read(_soundSamples[i]._buffer, _soundSamples[i]._length);
- file.close();
- }
-
- _soundMusicIntro = convertToMod("msn_data.049");
- _soundMusicOutro = convertToMod("msn_data.052");
-
- // Cursor
- const uint16 *bufferNormal = reinterpret_cast<const uint16 *>(mouseNormal);
- const uint16 *bufferWait = reinterpret_cast<const uint16 *>(mouseWait);
- for (uint i = 0; i < sizeof(mouseNormal) / 4; ++i) {
- for (uint bit = 0; bit < 16; ++bit) {
- uint mask = 0x8000 >> bit;
- uint bitIndex = i * 16 + bit;
-
- _mouseNormal[bitIndex] = (READ_LE_UINT16(bufferNormal + i) & mask) ? kColorCursorTransparent : kColorBlack;
- if (READ_LE_UINT16(bufferNormal + i + 16) & mask)
- _mouseNormal[bitIndex] = kColorLightRed;
- _mouseWait[bitIndex] = (READ_LE_UINT16(bufferWait + i) & mask) ? kColorCursorTransparent : kColorBlack;
- if (READ_LE_UINT16(bufferWait + i + 16) & mask)
- _mouseWait[bitIndex] = kColorLightRed;
- }
- }
+const Common::String &SupernovaEngine::getGameString(int idx) const {
+ if (idx < 0 || idx >= (int)_gameStrings.size())
+ return _nullString;
+ return _gameStrings[idx];
}
-void SupernovaEngine::initPalette() {
- _system->getPaletteManager()->setPalette(initVGAPalette, 0, 256);
-}
-
-void SupernovaEngine::playSound(AudioIndex sample) {
- if (sample > kAudioNumSamples - 1)
+void SupernovaEngine::setGameString(int idx, const Common::String &string) {
+ if (idx < 0)
return;
-
- Audio::SeekableAudioStream *audioStream = Audio::makeRawStream(
- _soundSamples[sample]._buffer, _soundSamples[sample]._length,
- 11931, Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN, DisposeAfterUse::NO);
- stopSound();
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, audioStream);
-}
-
-void SupernovaEngine::stopSound() {
- if (_mixer->isSoundHandleActive(_soundHandle))
- _mixer->stopHandle(_soundHandle);
+ while ((int)_gameStrings.size() <= idx)
+ _gameStrings.push_back(Common::String());
+ _gameStrings[idx] = string;
}
-void SupernovaEngine::playSoundMod(int filenumber)
-{
- Audio::AudioStream *audioStream;
- if (filenumber == 49)
- audioStream = Audio::makeProtrackerStream(_soundMusicIntro);
- else if (filenumber == 52)
- audioStream = Audio::makeProtrackerStream(_soundMusicOutro);
- else
- return;
-
- stopSound();
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, audioStream,
- -1, Audio::Mixer::kMaxChannelVolume, 0);
+void SupernovaEngine::playSound(AudioId sample) {
+ _sound->play(sample);
}
-void SupernovaEngine::renderImageSection(int section) {
- // Note: inverting means we are removing the section. So we should get the rect for that
- // section but draw the background (section 0) instead.
- bool invert = false;
- if (section > 128) {
- section -= 128;
- invert = true;
- }
- if (!_currentImage || section > _currentImage->_numSections - 1)
- return;
-
- Common::Rect sectionRect(_currentImage->_section[section].x1,
- _currentImage->_section[section].y1,
- _currentImage->_section[section].x2 + 1,
- _currentImage->_section[section].y2 + 1) ;
- if (_currentImage->_filenumber == 1 || _currentImage->_filenumber == 2) {
- sectionRect.setWidth(640);
- sectionRect.setHeight(480);
- if (_screenWidth != 640) {
- _screenWidth = 640;
- _screenHeight = 480;
- initGraphics(_screenWidth, _screenHeight);
- }
- } else {
- if (_screenWidth != 320) {
- _screenWidth = 320;
- _screenHeight = 200;
- initGraphics(_screenWidth, _screenHeight);
- }
- }
-
- uint offset = 0;
- int pitch = sectionRect.width();
- if (invert) {
- pitch = _currentImage->_pitch;
- offset = _currentImage->_section[section].y1 * pitch + _currentImage->_section[section].x1;
- section = 0;
- }
-
- _system->copyRectToScreen(static_cast<const byte *>(_currentImage->_sectionSurfaces[section]->getPixels()) + offset,
- pitch,
- sectionRect.left, sectionRect.top,
- sectionRect.width(), sectionRect.height());
+void SupernovaEngine::playSound(MusicId index) {
+ _sound->play(index);
}
void SupernovaEngine::renderImage(int section) {
- if (!_currentImage)
- return;
-
- bool sectionVisible = true;
-
- if (section > 128) {
- sectionVisible = false;
- section -= 128;
- }
-
- _gm->_currentRoom->setSectionVisible(section, sectionVisible);
-
- do {
- if (sectionVisible)
- renderImageSection(section);
- else
- renderImageSection(section + 128);
- section = _currentImage->_section[section].next;
- } while (section != 0);
+ _screen->renderImage(section);
}
bool SupernovaEngine::setCurrentImage(int filenumber) {
- if (_currentImage && _currentImage->_filenumber == filenumber)
- return true;
-
- delete _currentImage;
- _currentImage = new MSNImageDecoder();
- if (!_currentImage->init(filenumber)) {
- delete _currentImage;
- _currentImage = NULL;
- return false;
- }
-
- _system->getPaletteManager()->setPalette(_currentImage->getPalette(), 16, 239);
- paletteBrightness();
- return true;
+ return _screen->setCurrentImage(filenumber);
}
void SupernovaEngine::saveScreen(int x, int y, int width, int height) {
- _screenBuffer.push(x, y, width, height);
+ _screen->saveScreen(x, y, width, height);
}
void SupernovaEngine::saveScreen(const GuiElement &guiElement) {
- saveScreen(guiElement.left, guiElement.top, guiElement.width(), guiElement.height());
+ _screen->saveScreen(guiElement);
}
void SupernovaEngine::restoreScreen() {
- _screenBuffer.restore();
+ _screen->restoreScreen();
}
void SupernovaEngine::renderRoom(Room &room) {
- if (room.getId() == INTRO)
- return;
-
- if (setCurrentImage(room.getFileNumber())) {
- for (int i = 0; i < _currentImage->_numSections; ++i) {
- int section = i;
- if (room.isSectionVisible(section)) {
- do {
- renderImageSection(section);
- section = _currentImage->_section[section].next;
- } while (section != 0);
- }
- }
- }
+ _screen->renderRoom(room);
}
-int SupernovaEngine::textWidth(const uint16 key) {
- char text[2];
- text[0] = key & 0xFF;
- text[1] = 0;
- return textWidth(text);
+void SupernovaEngine::renderMessage(const char *text, MessagePosition position) {
+ _screen->renderMessage(text, position);
}
-int SupernovaEngine::textWidth(const char *text) {
- int charWidth = 0;
- while (*text != '\0') {
- byte c = *text++;
- if (c < 32) {
- continue;
- } else if (c == 225) {
- c = 35;
- }
-
- for (uint i = 0; i < 5; ++i) {
- if (font[c - 32][i] == 0xff) {
- break;
- }
- ++charWidth;
- }
- ++charWidth;
- }
-
- return charWidth;
+void SupernovaEngine::renderMessage(const Common::String &text, MessagePosition position) {
+ _screen->renderMessage(text, position);
}
-void SupernovaEngine::renderMessage(const char *text, MessagePosition position) {
- Common::String t(text);
- char *row[20];
- Common::String::iterator p = t.begin();
- uint numRows = 0;
- int rowWidthMax = 0;
- int x = 0;
- int y = 0;
- byte textColor = 0;
-
- while (*p != '\0') {
- row[numRows] = p;
- ++numRows;
- while ((*p != '\0') && (*p != '|')) {
- ++p;
- }
- if (*p == '|') {
- *p = '\0';
- ++p;
- }
- }
- for (uint i = 0; i < numRows; ++i) {
- int rowWidth = textWidth(row[i]);
- if (rowWidth > rowWidthMax)
- rowWidthMax = rowWidth;
- }
-
- switch (position) {
- case kMessageNormal:
- x = 160 - rowWidthMax / 2;
- textColor = kColorWhite99;
- break;
- case kMessageTop:
- x = 160 - rowWidthMax / 2;
- textColor = kColorLightYellow;
- break;
- case kMessageCenter:
- x = 160 - rowWidthMax / 2;
- textColor = kColorLightRed;
- break;
- case kMessageLeft:
- x = 3;
- textColor = kColorLightYellow;
- break;
- case kMessageRight:
- x = 317 - rowWidthMax;
- textColor = kColorLightGreen;
- break;
- }
-
- if (position == kMessageNormal) {
- y = 70 - ((numRows * 9) / 2);
- } else if (position == kMessageTop) {
- y = 5;
- } else {
- y = 142;
- }
-
- int message_columns = x - 3;
- int message_rows = y - 3;
- int message_width = rowWidthMax + 6;
- int message_height = numRows * 9 + 5;
- saveScreen(message_columns, message_rows, message_width, message_height);
- renderBox(message_columns, message_rows, message_width, message_height, kColorWhite35);
- for (uint i = 0; i < numRows; ++i) {
- renderText(row[i], x, y, textColor);
- y += 9;
- }
-
- _messageDisplayed = true;
- _gm->_timer1 = (Common::strnlen(text, 512) + 20) * _textSpeed / 10;
+void SupernovaEngine::renderMessage(StringId stringId, MessagePosition position, Common::String var1, Common::String var2) {
+ _screen->renderMessage(stringId, position, var1, var2);
}
void SupernovaEngine::removeMessage() {
- if (_messageDisplayed) {
- restoreScreen();
- _messageDisplayed = false;
- }
+ _screen->removeMessage();
}
-void SupernovaEngine::renderText(const char *text, int x, int y, byte color) {
- Graphics::Surface *screen = _system->lockScreen();
- byte *cursor = static_cast<byte *>(screen->getBasePtr(x, y));
- const byte *basePtr = cursor;
-
- byte c;
- while ((c = *text++) != '\0') {
- if (c < 32) {
- continue;
- } else if (c == 225) {
- c = 128;
- }
+void SupernovaEngine::renderText(const uint16 character) {
+ _screen->renderText(character);
+}
- for (uint i = 0; i < 5; ++i) {
- if (font[c - 32][i] == 0xff) {
- break;
- }
+void SupernovaEngine::renderText(const char *text) {
+ _screen->renderText(text);
+}
- byte *ascentLine = cursor;
- for (byte j = font[c - 32][i]; j != 0; j >>= 1) {
- if (j & 1) {
- *cursor = color;
- }
- cursor += kScreenWidth;
- }
- cursor = ++ascentLine;
- }
- ++cursor;
- }
- _system->unlockScreen();
+void SupernovaEngine::renderText(const Common::String &text) {
+ _screen->renderText(text);
+}
- uint numChars = cursor - basePtr;
- uint absPosition = y * kScreenWidth + x + numChars;
- _textCursorX = absPosition % kScreenWidth;
- _textCursorY = absPosition / kScreenWidth;
- _textColor = color;
+void SupernovaEngine::renderText(StringId stringId) {
+ _screen->renderText(stringId);
+}
+
+void SupernovaEngine::renderText(const GuiElement &guiElement) {
+ _screen->renderText(guiElement);
}
void SupernovaEngine::renderText(const uint16 character, int x, int y, byte color) {
- char text[2];
- text[0] = character & 0xFF;
- text[1] = 0;
- renderText(text, x, y, color);
+ _screen->renderText(character, x, y, color);
}
-void SupernovaEngine::renderText(const char *text) {
- renderText(text, _textCursorX, _textCursorY, _textColor);
+void SupernovaEngine::renderText(const char *text, int x, int y, byte color) {
+ _screen->renderText(text, x, y, color);
}
-void SupernovaEngine::renderText(const uint16 character) {
- char text[2];
- text[0] = character & 0xFF;
- text[1] = 0;
- renderText(text, _textCursorX, _textCursorY, _textColor);
+void SupernovaEngine::renderText(const Common::String &text, int x, int y, byte color) {
+ _screen->renderText(text, x, y, color);
}
-void SupernovaEngine::renderText(const GuiElement &guiElement) {
- renderText(guiElement.getText(), guiElement.getTextPos().x,
- guiElement.getTextPos().y, guiElement.getTextColor());
+
+void SupernovaEngine::renderText(StringId stringId, int x, int y, byte color) {
+ _screen->renderText(stringId, x, y, color);
}
void SupernovaEngine::renderBox(int x, int y, int width, int height, byte color) {
- Graphics::Surface *screen = _system->lockScreen();
- screen->fillRect(Common::Rect(x, y, x + width, y + height), color);
- _system->unlockScreen();
+ _screen->renderBox(x, y, width, height, color);
}
void SupernovaEngine::renderBox(const GuiElement &guiElement) {
- renderBox(guiElement.left, guiElement.top, guiElement.width(),
- guiElement.height(), guiElement.getBackgroundColor());
+ _screen->renderBox(guiElement);
}
void SupernovaEngine::paletteBrightness() {
- byte palette[768];
-
- _system->getPaletteManager()->grabPalette(palette, 0, 255);
- for (uint i = 0; i < 48; ++i) {
- palette[i] = (initVGAPalette[i] * _menuBrightness) >> 8;
- }
- for (uint i = 0; i < 717; ++i) {
- const byte *imagePalette;
- if (_currentImage && _currentImage->getPalette()) {
- imagePalette = _currentImage->getPalette();
- } else {
- imagePalette = palette + 48;
- }
- palette[i + 48] = (imagePalette[i] * _brightness) >> 8;
- }
- _system->getPaletteManager()->setPalette(palette, 0, 255);
+ _screen->paletteBrightness();
}
void SupernovaEngine::paletteFadeOut() {
- while (_menuBrightness > 10) {
- _menuBrightness -= 10;
- if (_brightness > _menuBrightness)
- _brightness = _menuBrightness;
- paletteBrightness();
- _system->updateScreen();
- _system->delayMillis(_delay);
- }
- _menuBrightness = 0;
- _brightness = 0;
- paletteBrightness();
- _system->updateScreen();
+ _screen->paletteFadeOut();
}
void SupernovaEngine::paletteFadeIn() {
- while (_menuBrightness < 245) {
- if (_brightness < _gm->_roomBrightness)
- _brightness += 10;
- _menuBrightness += 10;
- paletteBrightness();
- _system->updateScreen();
- _system->delayMillis(_delay);
- }
- _menuBrightness = 255;
- _brightness = _gm->_roomBrightness;
- paletteBrightness();
- _system->updateScreen();
+ _screen->paletteFadeIn();
}
void SupernovaEngine::setColor63(byte value) {
- byte color[3] = {value, value, value};
- _system->getPaletteManager()->setPalette(color, 63, 1);
+ _screen->setColor63(value);
}
void SupernovaEngine::setTextSpeed() {
- const Common::String& textSpeedString = getGameString(kStringTextSpeed);
- int stringWidth = textWidth(textSpeedString);
- int textX = (320 - stringWidth) / 2;
+ const Common::String &textSpeedString = getGameString(kStringTextSpeed);
+ int stringWidth = Screen::textWidth(textSpeedString);
+ int textX = (kScreenWidth - stringWidth) / 2;
int textY = 100;
stringWidth += 4;
- int boxX = stringWidth > 110 ? (320 - stringWidth) / 2 : 105;
+ int boxX = stringWidth > 110 ? (kScreenWidth - stringWidth) / 2 : 105;
int boxY = 97;
int boxWidth = stringWidth > 110 ? stringWidth : 110;
int boxHeight = 27;
@@ -878,191 +456,6 @@ bool SupernovaEngine::quitGameDialog() {
return quit;
}
-Common::MemoryReadStream *SupernovaEngine::convertToMod(const char *filename, int version) {
- // MSN format
- struct {
- uint16 seg;
- uint16 start;
- uint16 end;
- uint16 loopStart;
- uint16 loopEnd;
- char volume;
- char dummy[5];
- } instr2[22];
- int nbInstr2; // 22 for version1, 15 for version 2
- int16 songLength;
- char arrangement[128];
- int16 patternNumber;
- int32 note2[28][64][4];
-
- nbInstr2 = ((version == 1) ? 22 : 15);
-
- Common::File msnFile;
- msnFile.open(filename);
- if (!msnFile.isOpen()) {
- warning("Data file '%s' not found", msnFile.getName());
- return NULL;
- }
-
- for (int i = 0 ; i < nbInstr2 ; ++i) {
- instr2[i].seg = msnFile.readUint16LE();
- instr2[i].start = msnFile.readUint16LE();
- instr2[i].end = msnFile.readUint16LE();
- instr2[i].loopStart = msnFile.readUint16LE();
- instr2[i].loopEnd = msnFile.readUint16LE();
- instr2[i].volume = msnFile.readByte();
- msnFile.read(instr2[i].dummy, 5);
- }
- songLength = msnFile.readSint16LE();
- msnFile.read(arrangement, 128);
- patternNumber = msnFile.readSint16LE();
- for (int p = 0 ; p < patternNumber ; ++p) {
- for (int n = 0 ; n < 64 ; ++n) {
- for (int k = 0 ; k < 4 ; ++k) {
- note2[p][n][k] = msnFile.readSint32LE();
- }
- }
- }
-
- /* MOD format */
- struct {
- char iname[22];
- uint16 length;
- char finetune;
- char volume;
- uint16 loopStart;
- uint16 loopLength;
- } instr[31];
- int32 note[28][64][4];
-
- // We can't recover some MOD effects since several of them are mapped to 0.
- // Assume the MSN effect of value 0 is Arpeggio (MOD effect of value 0).
- const char invConvEff[8] = {0, 1, 2, 3, 10, 12, 13 ,15};
-
- // Reminder from convertToMsn
- // 31 30 29 28 27 26 25 24 - 23 22 21 20 19 18 17 16 - 15 14 13 12 11 10 09 08 - 07 06 05 04 03 02 01 00
- // h h h h g g g g f f f f e e e e d d d d c c c c b b b b a a a a
- //
- // MSN:
- // hhhh (4 bits) Cleared to 0
- // dddd c (5 bits) Sample index | after mapping through convInstr
- // ccc (3 bits) Effect type | after mapping through convEff
- // bbbb aaaa (8 bits) Effect value | unmodified
- // gggg ffff eeee (12 bits) Sample period | unmodified
- //
- // MS2:
- // hhhh (4 bits) Cleared to 0
- // dddd (4 bits) Sample index | after mapping through convInstr
- // cccc (4 bits) Effect type | unmodified
- // bbbb aaaa (8 bits) Effect value | unmodified
- // gggg ffff eeee (12 bits) Sample period | transformed (0xE000 / p) - 256
- //
- // MOD:
- // hhhh dddd (8 bits) Sample index
- // cccc (4 bits) Effect type for this channel/division
- // bbbb aaaa (8 bits) Effect value
- // gggg ffff eeee (12 bits) Sample period
-
- // Can we recover the instruments mapping? I don't think so as part of the original instrument index is cleared.
- // And it doesn't really matter as long as we are consistent.
- // However we need to make sure 31 (or 15 in MS2) is mapped to 0 in MOD.
- // We just add 1 to all other values, and this means a 1 <-> 1 mapping for the instruments
- for (int p = 0; p < patternNumber; ++p) {
- for (int n = 0; n < 64; ++n) {
- for (int k = 0; k < 4; ++k) {
- int32* l = &(note[p][n][k]);
- *l = note2[p][n][k];
- int32 i = 0;
- if (nbInstr2 == 22) { // version 1
- i = ((*l & 0xF800) >> 11);
- int32 e = ((*l & 0x0700) >> 8);
- int32 e1 = invConvEff[e];
- *l &= 0x0FFF00FF;
- *l |= (e1 << 8);
- } else { // version 2
- int32 h = (*l >> 16);
- i = ((*l & 0xF000) >> 12);
- *l &= 0x00000FFF;
- if (h)
- h = 0xE000 / (h + 256);
- *l |= (h << 16);
- if (i == 15)
- i = 31;
- }
-
- // Add back index in note
- if (i != 31) {
- ++i;
- *l |= ((i & 0x0F) << 12);
- *l |= ((i & 0xF0) << 24);
- }
- }
- }
- }
-
- for (int i = 0; i < 31; ++i) {
- // iname is not stored in the mod file. Just set it to 'instrument#'
- // finetune is not stored either. Assume 0.
- memset(instr[i].iname, 0, 22);
- sprintf(instr[i].iname, "instrument%d", i+1);
- instr[i].length = 0;
- instr[i].finetune = 0;
- instr[i].volume = 0;
- instr[i].loopStart = 0;
- instr[i].loopLength = 0;
-
- if (i < nbInstr2) {
- instr[i].length = ((instr2[i].end - instr2[i].start) >> 1);
- instr[i].loopStart = ((instr2[i].loopStart - instr2[i].start) >> 1);
- instr[i].loopLength = (( instr2[i].loopEnd - instr2[i].loopStart) >> 1);
- instr[i].volume = instr2[i].volume;
- }
- }
-
- // The ciaaSpeed is kind of useless and not present in the MSN file.
- // Traditionally 0x78 in SoundTracker. Was used in NoiseTracker as a restart point.
- // ProTracker uses 0x7F. FastTracker uses it as a restart point, whereas ScreamTracker 3 uses 0x7F like ProTracker.
- // You can use this to roughly detect which tracker made a MOD, and detection gets more accurate for more obscure MOD types.
- char ciaaSpeed = 0x7F;
-
- // The mark cannot be recovered either. Since we have 4 channels and 31 instrument it can be either ID='M.K.' or ID='4CHN'.
- // Assume 'M.K.'
- const char mark[4] = { 'M', '.', 'K', '.' };
-
- Common::MemoryWriteStreamDynamic buffer(DisposeAfterUse::NO);
-
- buffer.write(msnFile.getName(), 19);
- buffer.writeByte(0);
-
- for (int i = 0 ; i < 31 ; ++i) {
- buffer.write(instr[i].iname, 22);
- buffer.writeUint16BE(instr[i].length);
- buffer.writeByte(instr[i].finetune);
- buffer.writeByte(instr[i].volume);
- buffer.writeUint16BE(instr[i].loopStart);
- buffer.writeUint16BE(instr[i].loopLength);
- }
- buffer.writeByte((char)songLength);
- buffer.writeByte(ciaaSpeed);
- buffer.write(arrangement, 128);
- buffer.write(mark, 4);
-
- for (int p = 0 ; p < patternNumber ; ++p) {
- for (int n = 0 ; n < 64 ; ++n) {
- for (int k = 0 ; k < 4 ; ++k) {
-// buffer.writeUint32BE(*((uint32*)(note[p][n]+k)));
- buffer.writeSint32BE(note[p][n][k]);
- }
- }
- }
-
- uint nb;
- char buf[4096];
- while ((nb = msnFile.read(buf, 4096)) > 0)
- buffer.write(buf, nb);
-
- return new Common::MemoryReadStream(buffer.getData(), buffer.size(), DisposeAfterUse::YES);
-}
bool SupernovaEngine::canLoadGameStateCurrently() {
return _allowLoadGame;
@@ -1117,10 +510,11 @@ bool SupernovaEngine::loadGame(int slot) {
_gm->deserialize(savefile, saveVersion);
if (saveVersion >= 5) {
- _menuBrightness = savefile->readByte();
- _brightness = savefile->readByte();
+ _screen->setGuiBrightness(savefile->readByte());
+ _screen->setViewportBrightness(savefile->readByte());
} else {
- _menuBrightness = _brightness = 255;
+ _screen->setGuiBrightness(255);
+ _screen->setViewportBrightness(255);
}
delete savefile;
@@ -1153,8 +547,8 @@ bool SupernovaEngine::saveGame(int slot, const Common::String &description) {
Graphics::saveThumbnail(*savefile);
_gm->serialize(savefile);
- savefile->writeByte(_menuBrightness);
- savefile->writeByte(_brightness);
+ savefile->writeByte(_screen->getGuiBrightness());
+ savefile->writeByte(_screen->getViewportBrightness());
savefile->finalize();
delete savefile;
@@ -1169,59 +563,5 @@ void SupernovaEngine::errorTempSave(bool saving) {
error("Unrecoverable error");
}
-ScreenBufferStack::ScreenBufferStack()
- : _last(_buffer) {
-}
-
-void ScreenBufferStack::push(int x, int y, int width, int height) {
- if (_last == ARRAYEND(_buffer))
- return;
-
- Graphics::Surface* screenSurface = g_system->lockScreen();
-
- if (x < 0) {
- width += x;
- x = 0;
- }
- if (x + width > screenSurface->w)
- width = screenSurface->w - x;
-
- if (y < 0) {
- height += y;
- y = 0;
- }
- if (y + height > screenSurface->h)
- height = screenSurface->h - y;
-
- _last->_pixels = new byte[width * height];
- byte *pixels = _last->_pixels;
- const byte *screen = static_cast<const byte *>(screenSurface->getBasePtr(x, y));
- for (int i = 0; i < height; ++i) {
- Common::copy(screen, screen + width, pixels);
- screen += screenSurface->pitch;
- pixels += width;
- }
- g_system->unlockScreen();
-
- _last->_x = x;
- _last->_y = y;
- _last->_width = width;
- _last->_height = height;
-
- ++_last;
-}
-
-void ScreenBufferStack::restore() {
- if (_last == _buffer)
- return;
-
- --_last;
- g_system->lockScreen()->copyRectToSurface(
- _last->_pixels, _last->_width, _last->_x, _last->_y,
- _last->_width, _last->_height);
- g_system->unlockScreen();
-
- delete[] _last->_pixels;
-}
}
diff --git a/engines/supernova/supernova.h b/engines/supernova/supernova.h
index e01fb778a5..132e25deeb 100644
--- a/engines/supernova/supernova.h
+++ b/engines/supernova/supernova.h
@@ -23,9 +23,6 @@
#ifndef SUPERNOVA_SUPERNOVA_H
#define SUPERNOVA_SUPERNOVA_H
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "audio/decoders/raw.h"
#include "common/array.h"
#include "common/events.h"
#include "common/random.h"
@@ -38,6 +35,7 @@
#include "supernova/graphics.h"
#include "supernova/msn_def.h"
#include "supernova/rooms.h"
+#include "supernova/sound.h"
namespace Supernova {
@@ -48,96 +46,55 @@ namespace Supernova {
#define SUPERNOVA_DAT "supernova.dat"
#define SUPERNOVA_DAT_VERSION 1
-
-struct ScreenBuffer {
- ScreenBuffer()
- : _x(0)
- , _y(0)
- , _width(0)
- , _height(0)
- , _pixels(NULL)
- {}
-
- byte *_pixels;
- int _x;
- int _y;
- int _width;
- int _height;
-};
-class ScreenBufferStack {
-public:
- ScreenBufferStack();
-
- void push(int x, int y, int width, int height);
- void restore();
-
-private:
- ScreenBuffer _buffer[8];
- ScreenBuffer *_last;
-};
-
-struct SoundSample {
- SoundSample()
- : _buffer(NULL)
- , _length(0)
- {}
-
- ~SoundSample() {
- delete[] _buffer;
- }
-
- byte *_buffer;
- int _length;
-};
-
class GuiElement;
+class ResourceManager;
+class Sound;
+class console;
+class GameManager;
+class Screen;
+
class SupernovaEngine : public Engine {
public:
explicit SupernovaEngine(OSystem *syst);
~SupernovaEngine();
virtual Common::Error run();
+ virtual Common::Error loadGameState(int slot);
+ virtual bool canLoadGameStateCurrently();
+ virtual Common::Error saveGameState(int slot, const Common::String &desc);
+ virtual bool canSaveGameStateCurrently();
+ virtual bool hasFeature(EngineFeature f) const;
+ virtual void pauseEngineIntern(bool pause);
- Common::RandomSource _rnd;
GameManager *_gm;
Console *_console;
- Audio::SoundHandle _soundHandle;
- ScreenBufferStack _screenBuffer;
- byte _mouseNormal[256];
- byte _mouseWait[256];
- MSNImageDecoder *_currentImage;
- SoundSample _soundSamples[kAudioNumSamples];
- Common::MemoryReadStream *_soundMusicIntro;
- Common::MemoryReadStream *_soundMusicOutro;
- int _screenWidth;
- int _screenHeight;
+ Sound *_sound;
+ ResourceManager *_resMan;
+ Screen *_screen;
bool _allowLoadGame;
bool _allowSaveGame;
Common::StringArray _gameStrings;
Common::String _nullString;
- byte _menuBrightness;
- byte _brightness;
uint _delay;
- bool _messageDisplayed;
int _textSpeed;
- int _textCursorX;
- int _textCursorY;
- int _textColor;
- int textWidth(const char *text);
- int textWidth(const uint16 key);
Common::Error loadGameStrings();
- void initData();
- void initPalette();
+ void init();
+ bool loadGame(int slot);
+ bool saveGame(int slot, const Common::String &description);
+ bool quitGameDialog();
+ void errorTempSave(bool saving);
+ void setTextSpeed();
+ const Common::String &getGameString(int idx) const;
+ void setGameString(int idx, const Common::String &string);
+
+ // forwarding calls
+ void playSound(AudioId sample);
+ void playSound(MusicId index);
void paletteFadeIn();
void paletteFadeOut();
void paletteBrightness();
- void updateEvents();
- void playSound(AudioIndex sample);
- void playSoundMod(int filenumber);
- void stopSound();
- void renderImageSection(int section);
void renderImage(int section);
bool setCurrentImage(int filenumber);
void saveScreen(int x, int y, int width, int height);
@@ -145,77 +102,22 @@ public:
void restoreScreen();
void renderRoom(Room &room);
void renderMessage(const char *text, MessagePosition position = kMessageNormal);
+ void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal);
+ void renderMessage(StringId stringId, MessagePosition position = kMessageNormal,
+ Common::String var1 = "", Common::String var2 = "");
void removeMessage();
- void renderText(const char *text, int x, int y, byte color);
- void renderText(const uint16 character, int x, int y, byte color);
- void renderText(const char *text);
void renderText(const uint16 character);
+ void renderText(const char *text);
+ void renderText(const Common::String &text);
+ void renderText(StringId stringId);
+ void renderText(const uint16 character, int x, int y, byte color);
+ void renderText(const char *text, int x, int y, byte color);
+ void renderText(const Common::String &text, int x, int y, byte color);
+ void renderText(StringId stringId, int x, int y, byte color);
void renderText(const GuiElement &guiElement);
void renderBox(int x, int y, int width, int height, byte color);
void renderBox(const GuiElement &guiElement);
void setColor63(byte value);
- bool loadGame(int slot);
- bool saveGame(int slot, const Common::String &description);
- bool quitGameDialog();
- void errorTempSave(bool saving);
- void setTextSpeed();
-
- const Common::String &getGameString(int idx) const {
- if (idx < 0 || idx >= (int)_gameStrings.size())
- return _nullString;
- return _gameStrings[idx];
- }
-
- void setGameString(int idx, const Common::String &string) {
- if (idx < 0)
- return;
- while ((int)_gameStrings.size() <= idx)
- _gameStrings.push_back(Common::String());
- _gameStrings[idx] = string;
- }
-
- int textWidth(const Common::String &text) {
- if (text.empty())
- return 0;
- return textWidth(text.c_str());
- }
- void renderMessage(StringID stringId, MessagePosition position = kMessageNormal, Common::String var1 = "", Common::String var2 = "") {
- Common::String text = getGameString(stringId);
- if (!var1.empty()) {
- if (!var2.empty())
- text = Common::String::format(text.c_str(), var1.c_str(), var2.c_str());
- else
- text = Common::String::format(text.c_str(), var1.c_str());
- }
- renderMessage(text, position);
- }
- void renderMessage(const Common::String &text, MessagePosition position = kMessageNormal) {
- if (!text.empty())
- renderMessage(text.c_str(), position);
- }
- void renderText(StringID stringId, int x, int y, byte color) {
- renderText(getGameString(stringId), x, y, color);
- }
- void renderText(const Common::String &text, int x, int y, byte color) {
- if (!text.empty())
- renderText(text.c_str(), x, y, color);
- }
- void renderText(StringID stringId) {
- renderText(getGameString(stringId));
- }
- void renderText(const Common::String &text) {
- if (!text.empty())
- renderText(text.c_str());
- }
-
- Common::MemoryReadStream *convertToMod(const char *filename, int version = 1);
-
- virtual Common::Error loadGameState(int slot);
- virtual bool canLoadGameStateCurrently();
- virtual Common::Error saveGameState(int slot, const Common::String &desc);
- virtual bool canSaveGameStateCurrently();
- virtual bool hasFeature(EngineFeature f) const;
- virtual void pauseEngineIntern(bool pause);
};
}
diff --git a/engines/sword1/detection.cpp b/engines/sword1/detection.cpp
index d4343c8a9f..52394cec41 100644
--- a/engines/sword1/detection.cpp
+++ b/engines/sword1/detection.cpp
@@ -87,9 +87,9 @@ public:
}
virtual bool hasFeature(MetaEngineFeature f) const;
- virtual GameList getSupportedGames() const;
- virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const Common::FSList &fslist) const;
+ PlainGameList getSupportedGames() const override;
+ PlainGameDescriptor findGame(const char *gameId) const override;
+ DetectedGames detectGames(const Common::FSList &fslist) const override;
virtual SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const;
virtual void removeSaveState(const char *target, int slot) const;
@@ -116,31 +116,31 @@ bool Sword1::SwordEngine::hasFeature(EngineFeature f) const {
(f == kSupportsLoadingDuringRuntime);
}
-GameList SwordMetaEngine::getSupportedGames() const {
- GameList games;
- games.push_back(GameDescriptor(sword1FullSettings, GUIO_NOMIDI));
- games.push_back(GameDescriptor(sword1DemoSettings, GUIO_NOMIDI));
- games.push_back(GameDescriptor(sword1MacFullSettings, GUIO_NOMIDI));
- games.push_back(GameDescriptor(sword1MacDemoSettings, GUIO_NOMIDI));
- games.push_back(GameDescriptor(sword1PSXSettings, GUIO_NOMIDI));
- games.push_back(GameDescriptor(sword1PSXDemoSettings, GUIO_NOMIDI));
+PlainGameList SwordMetaEngine::getSupportedGames() const {
+ PlainGameList games;
+ games.push_back(sword1FullSettings);
+ games.push_back(sword1DemoSettings);
+ games.push_back(sword1MacFullSettings);
+ games.push_back(sword1MacDemoSettings);
+ games.push_back(sword1PSXSettings);
+ games.push_back(sword1PSXDemoSettings);
return games;
}
-GameDescriptor SwordMetaEngine::findGame(const char *gameid) const {
- if (0 == scumm_stricmp(gameid, sword1FullSettings.gameId))
+PlainGameDescriptor SwordMetaEngine::findGame(const char *gameId) const {
+ 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();
+ return PlainGameDescriptor::empty();
}
void Sword1CheckDirectory(const Common::FSList &fslist, bool *filesFound, bool recursion = false) {
@@ -175,9 +175,9 @@ void Sword1CheckDirectory(const Common::FSList &fslist, bool *filesFound, bool r
}
}
-GameList SwordMetaEngine::detectGames(const Common::FSList &fslist) const {
+DetectedGames SwordMetaEngine::detectGames(const Common::FSList &fslist) const {
int i, j;
- GameList detectedGames;
+ DetectedGames detectedGames;
bool filesFound[NUM_FILES_TO_CHECK];
for (i = 0; i < NUM_FILES_TO_CHECK; i++)
filesFound[i] = false;
@@ -212,31 +212,33 @@ GameList SwordMetaEngine::detectGames(const Common::FSList &fslist) const {
if (!filesFound[i] || psxFilesFound)
psxDemoFilesFound = false;
- GameDescriptor gd;
+ DetectedGame game;
if (mainFilesFound && pcFilesFound && demoFilesFound)
- gd = GameDescriptor(sword1DemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
+ game = DetectedGame(sword1DemoSettings);
else if (mainFilesFound && pcFilesFound && psxFilesFound)
- gd = GameDescriptor(sword1PSXSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
+ game = DetectedGame(sword1PSXSettings);
else if (mainFilesFound && pcFilesFound && psxDemoFilesFound)
- gd = GameDescriptor(sword1PSXDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
+ game = DetectedGame(sword1PSXDemoSettings);
else if (mainFilesFound && pcFilesFound && !psxFilesFound)
- gd = GameDescriptor(sword1FullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
+ game = DetectedGame(sword1FullSettings);
else if (mainFilesFound && macFilesFound)
- gd = GameDescriptor(sword1MacFullSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
+ game = DetectedGame(sword1MacFullSettings);
else if (mainFilesFound && macDemoFilesFound)
- gd = GameDescriptor(sword1MacDemoSettings, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
+ game = DetectedGame(sword1MacDemoSettings);
else
return detectedGames;
- gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY));
- gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::DE_DEU));
- gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::FR_FRA));
- gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::IT_ITA));
- gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::ES_ESP));
- gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::PT_BRA));
- gd.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::CZ_CZE));
+ game.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
- detectedGames.push_back(gd);
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::EN_ANY));
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::DE_DEU));
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::FR_FRA));
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::IT_ITA));
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::ES_ESP));
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::PT_BRA));
+ game.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(Common::CZ_CZE));
+
+ detectedGames.push_back(game);
return detectedGames;
}
@@ -300,7 +302,11 @@ SaveStateDescriptor SwordMetaEngine::querySaveMetaInfos(const char *target, int
in->skip(1);
if (Graphics::checkThumbnailHeader(*in)) {
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*in);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*in, thumbnail)) {
+ delete in;
+ return SaveStateDescriptor();
+ }
desc.setThumbnail(thumbnail);
}
diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp
index a2761eb5ce..4d8399e630 100644
--- a/engines/sword2/sword2.cpp
+++ b/engines/sword2/sword2.cpp
@@ -92,10 +92,10 @@ public:
}
virtual bool hasFeature(MetaEngineFeature f) const;
- virtual GameList getSupportedGames() const;
+ PlainGameList getSupportedGames() const override;
virtual const ExtraGuiOptions getExtraGuiOptions(const Common::String &target) const;
- virtual GameDescriptor findGame(const char *gameid) const;
- virtual GameList detectGames(const Common::FSList &fslist) const;
+ PlainGameDescriptor findGame(const char *gameid) const override;
+ virtual DetectedGames detectGames(const Common::FSList &fslist) const;
virtual SaveStateList listSaves(const char *target) const;
virtual int getMaximumSaveSlot() const;
virtual void removeSaveState(const char *target, int slot) const;
@@ -119,11 +119,11 @@ bool Sword2::Sword2Engine::hasFeature(EngineFeature f) const {
(f == kSupportsLoadingDuringRuntime);
}
-GameList Sword2MetaEngine::getSupportedGames() const {
+PlainGameList Sword2MetaEngine::getSupportedGames() const {
const Sword2::GameSettings *g = Sword2::sword2_settings;
- GameList games;
+ PlainGameList games;
while (g->gameid) {
- games.push_back(GameDescriptor(g->gameid, g->description));
+ games.push_back(PlainGameDescriptor::of(g->gameid, g->description));
g++;
}
return games;
@@ -135,20 +135,20 @@ const ExtraGuiOptions Sword2MetaEngine::getExtraGuiOptions(const Common::String
return options;
}
-GameDescriptor Sword2MetaEngine::findGame(const char *gameid) const {
+PlainGameDescriptor Sword2MetaEngine::findGame(const char *gameid) const {
const Sword2::GameSettings *g = Sword2::sword2_settings;
while (g->gameid) {
if (0 == scumm_stricmp(gameid, g->gameid))
break;
g++;
}
- return GameDescriptor(g->gameid, g->description);
+ return PlainGameDescriptor::of(g->gameid, g->description);
}
bool isFullGame(const Common::FSList &fslist) {
Common::FSList::const_iterator file;
- // We distinguish between the two versions by the presense of paris.clu
+ // We distinguish between the two versions by the presence of paris.clu
for (file = fslist.begin(); file != fslist.end(); ++file) {
if (!file->isDirectory()) {
if (file->getName().equalsIgnoreCase("paris.clu"))
@@ -159,8 +159,8 @@ bool isFullGame(const Common::FSList &fslist) {
return false;
}
-GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) {
- GameList detectedGames;
+DetectedGames detectGamesImpl(const Common::FSList &fslist, bool recursion = false) {
+ DetectedGames detectedGames;
const Sword2::GameSettings *g;
Common::FSList::const_iterator file;
bool isFullVersion = isFullGame(fslist);
@@ -192,7 +192,10 @@ GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) {
continue;
// Match found, add to list of candidates, then abort inner loop.
- detectedGames.push_back(GameDescriptor(g->gameid, g->description, Common::UNK_LANG, Common::kPlatformUnknown, GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)));
+ DetectedGame game = DetectedGame(g->gameid, g->description);
+ game.setGUIOptions(GUIO2(GUIO_NOMIDI, GUIO_NOASPECT));
+
+ detectedGames.push_back(game);
break;
}
}
@@ -208,7 +211,7 @@ GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) {
if (file->getName().equalsIgnoreCase("clusters")) {
Common::FSList recList;
if (file->getChildren(recList, Common::FSNode::kListAll)) {
- GameList recGames(detectGamesImpl(recList, true));
+ DetectedGames recGames = detectGamesImpl(recList, true);
if (!recGames.empty()) {
detectedGames.push_back(recGames);
break;
@@ -223,7 +226,7 @@ GameList detectGamesImpl(const Common::FSList &fslist, bool recursion = false) {
return detectedGames;
}
-GameList Sword2MetaEngine::detectGames(const Common::FSList &fslist) const {
+DetectedGames Sword2MetaEngine::detectGames(const Common::FSList &fslist) const {
return detectGamesImpl(fslist);
}
@@ -278,10 +281,10 @@ Common::Error Sword2MetaEngine::createInstance(OSystem *syst, Engine **engine) c
// Invoke the detector
Common::String gameid = ConfMan.get("gameid");
- GameList detectedGames = detectGames(fslist);
+ DetectedGames detectedGames = detectGames(fslist);
for (uint i = 0; i < detectedGames.size(); i++) {
- if (detectedGames[i].gameid() == gameid) {
+ if (detectedGames[i].gameId == gameid) {
*engine = new Sword2::Sword2Engine(syst);
return Common::kNoError;
}
diff --git a/engines/sword25/gfx/graphicengine.cpp b/engines/sword25/gfx/graphicengine.cpp
index fd3b63aeee..ca1f37c9d3 100644
--- a/engines/sword25/gfx/graphicengine.cpp
+++ b/engines/sword25/gfx/graphicengine.cpp
@@ -362,7 +362,7 @@ void GraphicEngine::updateLastFrameDuration() {
}
bool GraphicEngine::saveThumbnailScreenshot(const Common::String &filename) {
- // Note: In ScumMVM, rather than saivng the thumbnail to a file, we store it in memory
+ // Note: In ScummVM, rather than saving the thumbnail to a file, we store it in memory
// until needed when creating savegame files
delete _thumbnail;
@@ -373,10 +373,10 @@ bool GraphicEngine::saveThumbnailScreenshot(const Common::String &filename) {
void GraphicEngine::ARGBColorToLuaColor(lua_State *L, uint color) {
lua_Number components[4] = {
- (lua_Number)((color >> 16) & 0xff), // Red
- (lua_Number)((color >> 8) & 0xff), // Green
- (lua_Number)(color & 0xff), // Blue
- (lua_Number)(color >> 24), // Alpha
+ (lua_Number)((color >> 16) & 0xff), // Red
+ (lua_Number)((color >> 8) & 0xff), // Green
+ (lua_Number)( color & 0xff), // Blue
+ (lua_Number)( color >> 24), // Alpha
};
lua_newtable(L);
diff --git a/engines/sword25/sfx/soundengine.cpp b/engines/sword25/sfx/soundengine.cpp
index 8bc20180af..2e7b41c431 100644
--- a/engines/sword25/sfx/soundengine.cpp
+++ b/engines/sword25/sfx/soundengine.cpp
@@ -203,8 +203,8 @@ bool SoundEngine::playSound(const Common::String &fileName, SOUND_TYPES type, fl
}
uint SoundEngine::playSoundEx(const Common::String &fileName, SOUND_TYPES type, float volume, float pan, bool loop, int loopStart, int loopEnd, uint layer, uint handleId) {
- Common::SeekableReadStream *in = Kernel::getInstance()->getPackage()->getStream(fileName);
#ifdef USE_VORBIS
+ Common::SeekableReadStream *in = Kernel::getInstance()->getPackage()->getStream(fileName);
Audio::SeekableAudioStream *stream = Audio::makeVorbisStream(in, DisposeAfterUse::YES);
#endif
uint id = handleId;
diff --git a/engines/sword25/util/lua/llex.cpp b/engines/sword25/util/lua/llex.cpp
index 423f0285ca..ebda9ffbdf 100644
--- a/engines/sword25/util/lua/llex.cpp
+++ b/engines/sword25/util/lua/llex.cpp
@@ -377,8 +377,10 @@ static int llex (LexState *ls, SemInfo *seminfo) {
read_long_string(ls, seminfo, sep);
return TK_STRING;
}
- else if (sep == -1) return '[';
- else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
+ else if (sep == -1)
+ return '[';
+ luaX_lexerror(ls, "invalid long string delimiter", TK_STRING);
+ break;
}
case '=': {
next(ls);
diff --git a/engines/sword25/util/lua/lstrlib.cpp b/engines/sword25/util/lua/lstrlib.cpp
index 5da45e1fea..78122030f9 100644
--- a/engines/sword25/util/lua/lstrlib.cpp
+++ b/engines/sword25/util/lua/lstrlib.cpp
@@ -799,10 +799,8 @@ static int str_format (lua_State *L) {
luaL_addvalue(&b);
continue; /* skip the `addsize' at the end */
}
- else {
- sprintf(buff, form, s);
- break;
- }
+ sprintf(buff, form, s);
+ break;
}
default: { /* also treat cases `pnLlh' */
return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp
index caa7bdbec9..e35e7033d5 100644
--- a/engines/teenagent/detection.cpp
+++ b/engines/teenagent/detection.cpp
@@ -178,8 +178,11 @@ public:
SaveStateDescriptor ssd(slot, desc);
//checking for the thumbnail
- if (Graphics::Surface *const thumb = Graphics::loadThumbnail(*in))
- ssd.setThumbnail(thumb);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*in, thumbnail)) {
+ return SaveStateDescriptor();
+ }
+ ssd.setThumbnail(thumbnail);
return ssd;
}
diff --git a/engines/testbed/graphics.cpp b/engines/testbed/graphics.cpp
index 1b5af76ee7..65833d1de8 100644
--- a/engines/testbed/graphics.cpp
+++ b/engines/testbed/graphics.cpp
@@ -464,7 +464,7 @@ TestExitStatus GFXtests::fullScreenMode() {
}
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureFullscreenMode, !isFeatureEnabled);
+ g_system->setFeatureState(OSystem::kFeatureFullscreenMode, !isFeatureEnabled);
g_system->endGFXTransaction();
// Current state should be now !isFeatureEnabled
@@ -482,7 +482,7 @@ TestExitStatus GFXtests::fullScreenMode() {
}
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureFullscreenMode, !isFeatureEnabled);
+ g_system->setFeatureState(OSystem::kFeatureFullscreenMode, !isFeatureEnabled);
g_system->endGFXTransaction();
g_system->delayMillis(1000);
@@ -536,7 +536,7 @@ TestExitStatus GFXtests::filteringMode() {
if (g_system->hasFeature(OSystem::kFeatureFullscreenMode) && !g_system->getFeatureState(OSystem::kFeatureFullscreenMode)) {
fullScreenToggled = true;
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureFullscreenMode, true);
+ g_system->setFeatureState(OSystem::kFeatureFullscreenMode, true);
g_system->endGFXTransaction();
}
@@ -557,7 +557,7 @@ TestExitStatus GFXtests::filteringMode() {
}
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureFilteringMode, !isFeatureEnabled);
+ g_system->setFeatureState(OSystem::kFeatureFilteringMode, !isFeatureEnabled);
g_system->endGFXTransaction();
// Current state should be now !isFeatureEnabled
@@ -575,7 +575,7 @@ TestExitStatus GFXtests::filteringMode() {
}
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureFilteringMode, !isFeatureEnabled);
+ g_system->setFeatureState(OSystem::kFeatureFilteringMode, !isFeatureEnabled);
g_system->endGFXTransaction();
g_system->delayMillis(1000);
@@ -591,7 +591,7 @@ TestExitStatus GFXtests::filteringMode() {
// Restore fullscreen state
if (fullScreenToggled) {
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureFullscreenMode, false);
+ g_system->setFeatureState(OSystem::kFeatureFullscreenMode, false);
g_system->endGFXTransaction();
}
@@ -601,7 +601,7 @@ TestExitStatus GFXtests::filteringMode() {
return passed;
}
-
+
/**
* Tests the aspect ratio correction by: drawing an ellipse, when corrected the ellipse should render to a circle
*/
@@ -639,7 +639,7 @@ TestExitStatus GFXtests::aspectRatio() {
}
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, !isFeatureEnabled);
+ g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, !isFeatureEnabled);
g_system->endGFXTransaction();
g_system->delayMillis(1000);
@@ -653,7 +653,7 @@ TestExitStatus GFXtests::aspectRatio() {
}
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, isFeatureEnabled);
+ g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, isFeatureEnabled);
g_system->endGFXTransaction();
} else {
Testsuite::displayMessage("feature not supported");
@@ -835,13 +835,13 @@ TestExitStatus GFXtests::iconifyWindow() {
// Toggle
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureIconifyWindow, !isFeatureEnabled);
+ g_system->setFeatureState(OSystem::kFeatureIconifyWindow, !isFeatureEnabled);
g_system->endGFXTransaction();
g_system->delayMillis(1000);
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureIconifyWindow, isFeatureEnabled);
+ g_system->setFeatureState(OSystem::kFeatureIconifyWindow, isFeatureEnabled);
g_system->endGFXTransaction();
} else {
Testsuite::displayMessage("feature not supported");
@@ -884,7 +884,7 @@ TestExitStatus GFXtests::scaledCursors() {
if (isAspectRatioCorrected) {
g_system->beginGFXTransaction();
- g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, false);
+ g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, false);
g_system->endGFXTransaction();
}
@@ -911,8 +911,8 @@ TestExitStatus GFXtests::scaledCursors() {
g_system->beginGFXTransaction();
- bool isGFXModeSet = g_system->setGraphicsMode(gfxMode->id);
- g_system->initSize(320, 200);
+ bool isGFXModeSet = g_system->setGraphicsMode(gfxMode->id);
+ g_system->initSize(320, 200);
OSystem::TransactionError gfxError = g_system->endGFXTransaction();
@@ -947,12 +947,13 @@ TestExitStatus GFXtests::scaledCursors() {
// Restore Original State
g_system->beginGFXTransaction();
- bool isGFXModeSet = g_system->setGraphicsMode(currGFXMode);
- g_system->initSize(320, 200);
- if (isAspectRatioCorrected) {
- g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, true);
- }
+ bool isGFXModeSet = g_system->setGraphicsMode(currGFXMode);
+ g_system->initSize(320, 200);
+
+ if (isAspectRatioCorrected) {
+ g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, true);
+ }
OSystem::TransactionError gfxError = g_system->endGFXTransaction();
@@ -1226,7 +1227,7 @@ TestExitStatus GFXtests::pixelFormats() {
// Switch to that pixel Format
g_system->beginGFXTransaction();
- g_system->initSize(320, 200, &(*iter));
+ g_system->initSize(320, 200, &(*iter));
g_system->endGFXTransaction();
Testsuite::clearScreen(true);
@@ -1272,7 +1273,7 @@ TestExitStatus GFXtests::pixelFormats() {
// Revert back to 8bpp
g_system->beginGFXTransaction();
- g_system->initSize(320, 200);
+ g_system->initSize(320, 200);
g_system->endGFXTransaction();
GFXTestSuite::setCustomColor(255, 0, 0);
initMousePalette();
diff --git a/engines/tinsel/cursor.cpp b/engines/tinsel/cursor.cpp
index e69031d572..c23e4f2845 100644
--- a/engines/tinsel/cursor.cpp
+++ b/engines/tinsel/cursor.cpp
@@ -375,6 +375,10 @@ void SetAuxCursor(SCNHANDLE hFilm) {
DelAuxCursor(); // Get rid of previous
+ // WORKAROUND: There's no palette when loading a DW1 savegame with a held item, so exit if so
+ if (!BgPal())
+ return;
+
GetCursorXY(&x, &y, false); // Note: also waits for cursor to appear
pim = GetImageFromFilm(hFilm, 0, &pfr, &pmi, &pfilm);// Get pointer to image
diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp
index d6bcfe5ea0..1c60c5eb8a 100644
--- a/engines/tinsel/detection.cpp
+++ b/engines/tinsel/detection.cpp
@@ -97,7 +97,7 @@ public:
}
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
- const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override;
virtual bool hasFeature(MetaEngineFeature f) const;
virtual SaveStateList listSaves(const char *target) const;
@@ -185,7 +185,7 @@ typedef Common::Array<const ADGameDescription *> ADGameDescList;
* Fallback detection scans the list of Discworld 2 targets to see if it can detect an installation
* where the files haven't been renamed (i.e. don't have the '1' just before the extension)
*/
-const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const {
+ADDetectedGame TinselMetaEngine::fallbackDetect(const FileMap &allFilesXXX, const Common::FSList &fslist) const {
Common::String extra;
FileMap allFiles;
SizeMD5Map filesSizeMD5;
@@ -194,7 +194,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile
const Tinsel::TinselGameDescription *g;
if (fslist.empty())
- return NULL;
+ return ADDetectedGame();
// TODO: The following code is essentially a slightly modified copy of the
// complete code of function detectGame() in engines/advancedDetector.cpp.
@@ -262,7 +262,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile
}
}
- ADGameDescList matched;
+ ADDetectedGame matched;
int maxFilesMatched = 0;
// MD5 based matching
@@ -310,22 +310,15 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile
for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++)
curFilesMatched++;
- if (curFilesMatched > maxFilesMatched) {
+ if (curFilesMatched >= maxFilesMatched) {
maxFilesMatched = curFilesMatched;
- matched.clear(); // Remove any prior, lower ranked matches.
- matched.push_back((const ADGameDescription *)g);
- } else if (curFilesMatched == maxFilesMatched) {
- matched.push_back((const ADGameDescription *)g);
+ matched = ADDetectedGame(&g->desc);
}
}
}
- // We didn't find a match
- if (matched.empty())
- return NULL;
-
- return *matched.begin();
+ return matched;
}
int TinselMetaEngine::getMaximumSaveSlot() const { return 99; }
diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp
index b5d090ec15..755b9275c6 100644
--- a/engines/tinsel/dialogs.cpp
+++ b/engines/tinsel/dialogs.cpp
@@ -1907,6 +1907,11 @@ extern void HoldItem(int item, bool bKeepFilm) {
invObj = GetInvObject(item);
SetAuxCursor(invObj->hIconFilm); // and is aux. cursor
}
+
+ // WORKAROUND: If a held item is being removed that's not in either inventory (i.e. it was picked up
+ // but never put in them), then when removing it from being held, drop it in the luggage
+ if (g_heldItem != INV_NOICON && InventoryPos(g_heldItem) == INV_HELDNOTIN)
+ AddToInventory(INV_1, g_heldItem);
}
g_heldItem = item; // Item held
diff --git a/engines/tinsel/multiobj.cpp b/engines/tinsel/multiobj.cpp
index 75894aea89..2cd46ae90b 100644
--- a/engines/tinsel/multiobj.cpp
+++ b/engines/tinsel/multiobj.cpp
@@ -122,8 +122,7 @@ void MultiDeleteObject(OBJECT **pObjList, OBJECT *pMultiObj) {
// next obj in list
pMultiObj = pMultiObj->pSlave;
- }
- while (pMultiObj != NULL);
+ } while (pMultiObj != NULL);
}
/**
@@ -180,8 +179,7 @@ void MultiVerticalFlip(OBJECT *pFlipObj) {
// next obj in list
pFlipObj = pFlipObj->pSlave;
- }
- while (pFlipObj != NULL);
+ } while (pFlipObj != NULL);
}
/**
@@ -351,8 +349,7 @@ void MultiSetZPosition(OBJECT *pMultiObj, int newZ) {
// next obj in list
pMultiObj = pMultiObj->pSlave;
- }
- while (pMultiObj != NULL);
+ } while (pMultiObj != NULL);
}
/**
diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp
index dc19f39405..8899eea65b 100644
--- a/engines/tinsel/pcode.cpp
+++ b/engines/tinsel/pcode.cpp
@@ -156,6 +156,7 @@ static const byte fragment14[] = {OP_LIBCALL | OPSIZE8, 58,
OP_IMM, FRAGMENT_DWORD((42 << 23)), OP_ONE, OP_ZERO, OP_LIBCALL | OPSIZE8, 44,
OP_LIBCALL | OPSIZE8, 97, OP_JUMP | OPSIZE16, FRAGMENT_WORD(2220)
};
+static const byte fragment15[] = { OP_JMPFALSE | OPSIZE16, FRAGMENT_WORD(154) };
#undef FRAGMENT_WORD
@@ -226,6 +227,9 @@ const WorkaroundEntry workaroundList[] = {
// quitting the game when no user input happens for a while
{TINSEL_V1, true, true, Common::kPlatformPSX, 0, 2186, sizeof(fragment14), fragment14},
+ // DW1-GRA: Fixes hang in Temple, when trying to use items on the big hammer
+ {TINSEL_V1, false, false, Common::kPlatformUnknown, 276915849, 0x98, sizeof(fragment15), fragment15},
+
{TINSEL_V0, false, false, Common::kPlatformUnknown, 0, 0, 0, NULL}
};
diff --git a/engines/titanic/continue_save_dialog.cpp b/engines/titanic/continue_save_dialog.cpp
index 6de267e9fe..0aee87328b 100644
--- a/engines/titanic/continue_save_dialog.cpp
+++ b/engines/titanic/continue_save_dialog.cpp
@@ -185,7 +185,7 @@ void CContinueSaveDialog::mouseMove(const Point &mousePos) {
void CContinueSaveDialog::leftButtonDown(const Point &mousePos) {
Rect eye1(188, 190, 192, 195), eye2(209, 192, 213, 197);
- if (g_vm->_events->isSpecialPressed(MK_SHIFT) &&
+ if (g_vm->_events->isSpecialPressed(MK_SHIFT) &&
(eye1.contains(mousePos) || eye2.contains(mousePos))) {
// Show the Easter Egg "Evil Twin"
_evilTwinShown = true;
diff --git a/engines/titanic/core/game_object.cpp b/engines/titanic/core/game_object.cpp
index af34526329..d75bca0a7e 100644
--- a/engines/titanic/core/game_object.cpp
+++ b/engines/titanic/core/game_object.cpp
@@ -697,6 +697,7 @@ void CGameObject::playClip(uint startFrame, uint endFrame) {
CRoomItem *room = gameManager->getRoom();
gameManager->playClip(clip, room, room);
+ delete clip;
}
void CGameObject::playRandomClip(const char *const *names, uint flags) {
diff --git a/engines/titanic/core/list.h b/engines/titanic/core/list.h
index 09068fb06a..6da3a9224a 100644
--- a/engines/titanic/core/list.h
+++ b/engines/titanic/core/list.h
@@ -106,7 +106,7 @@ public:
for (uint idx = 0; idx < count; ++idx) {
// Validate the class start header
- if (!file->IsClassStart())
+ if (!file->isClassStart())
error("Unexpected class end");
// Get item's class name and use it to instantiate an item
@@ -120,7 +120,7 @@ public:
Common::List<T *>::push_back(newItem);
// Validate the class end footer
- if (file->IsClassStart())
+ if (file->isClassStart())
error("Unexpected class start");
}
}
diff --git a/engines/titanic/core/project_item.cpp b/engines/titanic/core/project_item.cpp
index b2bd5cd92b..99eec803ac 100644
--- a/engines/titanic/core/project_item.cpp
+++ b/engines/titanic/core/project_item.cpp
@@ -190,16 +190,12 @@ void CProjectItem::loadGame(int slotId) {
// Load the savegame header in
TitanicSavegameHeader header;
readSavegameHeader(&file, header);
- if (header._thumbnail) {
- header._thumbnail->free();
- delete header._thumbnail;
- }
g_vm->_events->setTotalPlayTicks(header._totalFrames);
// Load the contents in
CProjectItem *newProject = loadData(&file);
- file.IsClassStart();
+ file.isClassStart();
getGameManager()->load(&file);
file.close();
@@ -254,7 +250,7 @@ void CProjectItem::clear() {
}
CProjectItem *CProjectItem::loadData(SimpleFile *file) {
- if (!file->IsClassStart())
+ if (!file->isClassStart())
return nullptr;
CProjectItem *root = nullptr;
@@ -295,8 +291,8 @@ CProjectItem *CProjectItem::loadData(SimpleFile *file) {
item->load(file);
}
- file->IsClassStart();
- } while (file->IsClassStart());
+ file->isClassStart();
+ } while (file->isClassStart());
return root;
}
@@ -488,13 +484,9 @@ SaveStateList CProjectItem::getSavegameList(const Common::String &target) {
if (in) {
SimpleFile f;
f.open(in);
- if (!readSavegameHeader(&f, header))
- continue;
-
- saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+ if (readSavegameHeader(&f, header))
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
- header._thumbnail->free();
- delete header._thumbnail;
delete in;
}
}
@@ -503,7 +495,7 @@ SaveStateList CProjectItem::getSavegameList(const Common::String &target) {
return saveList;
}
-bool CProjectItem::readSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header) {
+WARN_UNUSED_RESULT bool CProjectItem::readSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
header._thumbnail = nullptr;
header._totalFrames = 0;
@@ -526,8 +518,7 @@ bool CProjectItem::readSavegameHeader(SimpleFile *file, TitanicSavegameHeader &h
while ((ch = (char)file->readByte()) != '\0') header._saveName += ch;
// Get the thumbnail
- header._thumbnail = Graphics::loadThumbnail(*file);
- if (!header._thumbnail)
+ if (!Graphics::loadThumbnail(*file, header._thumbnail, skipThumbnail))
return false;
// Read in save date/time
diff --git a/engines/titanic/core/project_item.h b/engines/titanic/core/project_item.h
index c9fd6f97cb..1c5923fd0e 100644
--- a/engines/titanic/core/project_item.h
+++ b/engines/titanic/core/project_item.h
@@ -155,7 +155,7 @@ public:
/**
* Read in the header information for a savegame
*/
- static bool readSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header, bool skipThumbnail = true);
public:
CLASSDEF;
CProjectItem();
diff --git a/engines/titanic/debugger.cpp b/engines/titanic/debugger.cpp
index 7438a0053b..01948dd4d3 100644
--- a/engines/titanic/debugger.cpp
+++ b/engines/titanic/debugger.cpp
@@ -357,7 +357,7 @@ bool Debugger::cmdFrame(int argc, const char **argv) {
if (argc == 3) {
CGameObject *obj = dynamic_cast<CGameObject *>(
g_vm->_window->_project->findByName(argv[1]));
-
+
if (obj) {
obj->loadFrame(strToInt(argv[2]));
return false;
diff --git a/engines/titanic/detection.cpp b/engines/titanic/detection.cpp
index b33ac51bed..c98fbbdade 100644
--- a/engines/titanic/detection.cpp
+++ b/engines/titanic/detection.cpp
@@ -128,11 +128,6 @@ SaveStateList TitanicMetaEngine::listSaves(const char *target) const {
if (Titanic::CProjectItem::readSavegameHeader(&cf, header))
saveList.push_back(SaveStateDescriptor(slot, header._saveName));
- if (header._thumbnail) {
- header._thumbnail->free();
- delete header._thumbnail;
- }
-
cf.close();
}
}
@@ -161,7 +156,10 @@ SaveStateDescriptor TitanicMetaEngine::querySaveMetaInfos(const char *target, in
file.open(f);
Titanic::TitanicSavegameHeader header;
- Titanic::CProjectItem::readSavegameHeader(&file, header);
+ if (!Titanic::CProjectItem::readSavegameHeader(&file, header, false)) {
+ file.close();
+ return SaveStateDescriptor();
+ }
file.close();
diff --git a/engines/titanic/game/bomb.cpp b/engines/titanic/game/bomb.cpp
index d9eb737c34..40651c0a88 100644
--- a/engines/titanic/game/bomb.cpp
+++ b/engines/titanic/game/bomb.cpp
@@ -374,7 +374,7 @@ bool CBomb::TimerMsg(CTimerMsg *msg) {
addTimer(0, 100, 0);
return true;
}
-
+
if (msg->_actionVal == 0) {
addTimer(1, 1000, 0);
} else {
@@ -459,7 +459,7 @@ bool CBomb::TimerMsg(CTimerMsg *msg) {
--_countdown;
addTimer(0, 1000, 0);
}
-
+
return true;
}
diff --git a/engines/titanic/game/chicken_dispensor.cpp b/engines/titanic/game/chicken_dispensor.cpp
index 8d16289647..ced0c78ef1 100644
--- a/engines/titanic/game/chicken_dispensor.cpp
+++ b/engines/titanic/game/chicken_dispensor.cpp
@@ -106,7 +106,7 @@ bool CChickenDispensor::StatusChangeMsg(CStatusChangeMsg *msg) {
bool CChickenDispensor::MovieEndMsg(CMovieEndMsg *msg) {
int movieFrame = msg->_endFrame;
-
+
if (movieFrame == 16) {
// Dispensed a chicken
_cursorId = CURSOR_HAND;
diff --git a/engines/titanic/npcs/deskbot.cpp b/engines/titanic/npcs/deskbot.cpp
index ee639c908f..c23fefce91 100644
--- a/engines/titanic/npcs/deskbot.cpp
+++ b/engines/titanic/npcs/deskbot.cpp
@@ -301,7 +301,7 @@ bool CDeskbot::TrueTalkNotifySpeechEndedMsg(CTrueTalkNotifySpeechEndedMsg *msg)
CTurnOff turnOff;
CTrueTalkNPC::TrueTalkNotifySpeechEndedMsg(msg);
-
+
if (g_language == Common::DE_DEU) {
switch (msg->_dialogueId) {
case 41701:
diff --git a/engines/titanic/pet_control/pet_load_save.cpp b/engines/titanic/pet_control/pet_load_save.cpp
index d918478fb1..72770b9eb2 100644
--- a/engines/titanic/pet_control/pet_load_save.cpp
+++ b/engines/titanic/pet_control/pet_load_save.cpp
@@ -135,11 +135,6 @@ void CPetLoadSave::resetSlots() {
_slotNames[idx].setText(header._saveName);
}
- if (header._thumbnail) {
- header._thumbnail->free();
- delete header._thumbnail;
- }
-
file.close();
}
}
diff --git a/engines/titanic/sound/music_room_handler.cpp b/engines/titanic/sound/music_room_handler.cpp
index 2265e46bb2..364023ea3a 100644
--- a/engines/titanic/sound/music_room_handler.cpp
+++ b/engines/titanic/sound/music_room_handler.cpp
@@ -230,7 +230,7 @@ void CMusicRoomHandler::updateAudio() {
}
}
}
-
+
_audioBuffer->push(audioData, size);
delete[] audioData;
}
diff --git a/engines/titanic/sound/music_room_instrument.cpp b/engines/titanic/sound/music_room_instrument.cpp
index 882325c08a..99ead2f8eb 100644
--- a/engines/titanic/sound/music_room_instrument.cpp
+++ b/engines/titanic/sound/music_room_instrument.cpp
@@ -77,7 +77,7 @@ CMusicRoomInstrument::CMusicRoomInstrument(CProjectItem *project, CSoundManager
_gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Tubular Bells"));
_insStartTime = 0.4;
break;
-
+
case MV_SNAKE:
_gameObjects[0] = static_cast<CGameObject *>(_project->findByName("Snake_Hammer"));
_gameObjects[1] = static_cast<CGameObject *>(_project->findByName("Snake_Glass"));
diff --git a/engines/titanic/sound/music_song.cpp b/engines/titanic/sound/music_song.cpp
index ea5f29a536..1645004c0a 100644
--- a/engines/titanic/sound/music_song.cpp
+++ b/engines/titanic/sound/music_song.cpp
@@ -127,7 +127,7 @@ bool CSongParser::parse(CValuePair &r) {
} else if (_currentChar == '^') {
if (_flag)
break;
-
+
_flag = true;
r._data = 0x7FFFFFFF;
r._length = _field10;
@@ -176,7 +176,7 @@ bool CSongParser::parse(CValuePair &r) {
FETCH_CHAR;
}
}
-
+
if (!_flag)
return false;
diff --git a/engines/titanic/star_control/base_stars.cpp b/engines/titanic/star_control/base_stars.cpp
index 0fcf8a964f..00206b1a9d 100644
--- a/engines/titanic/star_control/base_stars.cpp
+++ b/engines/titanic/star_control/base_stars.cpp
@@ -462,7 +462,7 @@ void CBaseStars::draw4(CSurfaceArea *surfaceArea, CStarCamera *camera, CStarClos
+ vector._z * pose._row3._z + pose._vector._z;
if (tempZ <= minVal)
continue;
-
+
tempY = vector._x * pose._row1._y + vector._y * pose._row2._y + vector._z * pose._row3._y + pose._vector._y;
tempX = vector._x * pose._row1._x + vector._y * pose._row2._x + vector._z * pose._row3._x + pose._vector._x;
total2 = tempY * tempY + tempX * tempX + tempZ * tempZ;
diff --git a/engines/titanic/star_control/camera_auto_mover.cpp b/engines/titanic/star_control/camera_auto_mover.cpp
index 71f7de85b2..d8808653eb 100644
--- a/engines/titanic/star_control/camera_auto_mover.cpp
+++ b/engines/titanic/star_control/camera_auto_mover.cpp
@@ -78,7 +78,7 @@ void CCameraAutoMover::calcSpeeds(int val1, int val2, float distance) {
_field40 = nMoverTransitions-1;
_field48 = nMoverTransitions-1;
_field3C = (double)val2 * _field38;
-
+
// Calculate the speeds for a graduated movement between stars
double base = 0.0, total = 0.0, power = 4.0, baseInc = 0.03125;
for (int idx = nMoverTransitions - 1; idx >= 0; --idx) {
@@ -86,7 +86,7 @@ void CCameraAutoMover::calcSpeeds(int val1, int val2, float distance) {
total += _speeds[idx];
base += baseInc;
}
-
+
for (int idx = 0; idx < nMoverTransitions; ++idx) {
_speeds[idx] = _speeds[idx] * _field3C / total;
}
diff --git a/engines/titanic/star_control/camera_auto_mover.h b/engines/titanic/star_control/camera_auto_mover.h
index db57627e33..d9b2888fc8 100644
--- a/engines/titanic/star_control/camera_auto_mover.h
+++ b/engines/titanic/star_control/camera_auto_mover.h
@@ -62,17 +62,17 @@ public:
/**
* Clear src and dest orientation and set some default values for other fields
- */
+ */
void clear();
/**
* Setup a transition to from one position to another
- */
+ */
void setPath(const FVector &srcV, const FVector &destV);
/**
* Applys speeds to the mover. More than one application is usually done for several transitions
- */
+ */
virtual MoverState move(CErrorCode &errorCode, FVector &pos, FMatrix &orientation) { return DONE_MOVING; }
/**
* Given a distance to cover, determines a bunch of speeds for a gradual transition
diff --git a/engines/titanic/star_control/frect.h b/engines/titanic/star_control/frect.h
index 654c578cfd..d792eb69b4 100644
--- a/engines/titanic/star_control/frect.h
+++ b/engines/titanic/star_control/frect.h
@@ -41,7 +41,7 @@ public:
* Returns true if the rects equal
*/
bool operator==(const FRect &p) const;
-
+
/**
* Returns true if the rects are not equal
*/
diff --git a/engines/titanic/star_control/marked_auto_mover.h b/engines/titanic/star_control/marked_auto_mover.h
index ca7fbf3b7f..d5f714b3ae 100644
--- a/engines/titanic/star_control/marked_auto_mover.h
+++ b/engines/titanic/star_control/marked_auto_mover.h
@@ -46,7 +46,7 @@ public:
/**
* Applys speeds to the mover. More than one application is usually done for several transitions
- */
+ */
virtual MoverState move(CErrorCode &errorCode, FVector &pos, FMatrix &orientation);
};
diff --git a/engines/titanic/star_control/star_camera.h b/engines/titanic/star_control/star_camera.h
index f2d27212fe..9d0c954765 100644
--- a/engines/titanic/star_control/star_camera.h
+++ b/engines/titanic/star_control/star_camera.h
@@ -234,7 +234,7 @@ public:
* Lock in the first matched star marker
*/
bool lockMarker1(FVector v1, FVector v2, FVector v3);
-
+
/**
* Lock in the second matched star marker
*/
diff --git a/engines/titanic/star_control/star_closeup.cpp b/engines/titanic/star_control/star_closeup.cpp
index 6ec94bbf38..3bc3623d58 100644
--- a/engines/titanic/star_control/star_closeup.cpp
+++ b/engines/titanic/star_control/star_closeup.cpp
@@ -69,9 +69,9 @@ bool CStarCloseup::setup2(int val1, int val2) {
const int VALUES1[] = { 0x800, 0xC00, 0x1000, 0x1400, 0x1800 };
const int VALUES2[] = {
0xF95BCD, 0xA505A0, 0xFFAD43, 0x98F4EB, 0xF3EFA5, 0,
- 0xFFFFFF, 0x81EEF5, 0x5FFD3, 0x4EE4FA, 0x11C3FF, 0x28F3F4,
- 0x36FCF2, 0x29F1FD, 0x29BCFD, 0x98E3F4, 0xBBF3D9, 0x8198F5,
- 0x5BE4F9, 0x0D6E2, 0x74EEF6, 0x68DEF8
+ 0xFFFFFF, 0x81EEF5, 0x5FFD3, 0x4EE4FA, 0x11C3FF, 0x28F3F4,
+ 0x36FCF2, 0x29F1FD, 0x29BCFD, 0x98E3F4, 0xBBF3D9, 0x8198F5,
+ 0x5BE4F9, 0x0D6E2, 0x74EEF6, 0x68DEF8
};
Entry *e = &_entries[0];
@@ -174,7 +174,7 @@ bool CStarCloseup::setup2(int val1, int val2) {
e->_pixel2 = (val >> 8) & 0xff;
e->_pixel3 = (val >> 16) & 0xff;
e->_field8 = g_vm->getRandomNumber(3) + 3;
-
+
e->_fieldC = g_vm->getRandomNumber(255);
e->_field10 = FACTOR * (float)g_vm->getRandomNumber(15);
e->_field14 = ((float)g_vm->getRandomNumber(0xfffffffe)
@@ -293,7 +293,7 @@ void CStarCloseup::draw(const FPose &pose, const FVector &vector, const FVector
}
switch (starColor) {
- case WHITE:
+ case WHITE:
surfaceArea->setMode(SA_SOLID);
surfaceArea->_pixel = MKTAG_BE(entryP->_pixel1, entryP->_pixel2,
entryP->_pixel3, 0);
@@ -424,7 +424,7 @@ void CStarCloseup::draw(const FPose &pose, const FVector &vector, const FVector
surfaceArea->drawLine(FRect(grid1._position._x, grid1._position._y,
grid2._position._x, grid2._position._y));
}
- }
+ }
break;
case PINK:
surfaceArea->setMode(SA_SOLID);
diff --git a/engines/titanic/star_control/star_control.cpp b/engines/titanic/star_control/star_control.cpp
index 8464262b31..7922a2f7f2 100644
--- a/engines/titanic/star_control/star_control.cpp
+++ b/engines/titanic/star_control/star_control.cpp
@@ -241,7 +241,7 @@ void CStarControl::doAction(StarControlAction action) {
pet->starsSetReference();
break;
}
-
+
case STAR_FADE_IN:
_view.fn3(true);
break;
diff --git a/engines/titanic/star_control/star_crosshairs.h b/engines/titanic/star_control/star_crosshairs.h
index d60541c205..3d060fd91d 100644
--- a/engines/titanic/star_control/star_crosshairs.h
+++ b/engines/titanic/star_control/star_crosshairs.h
@@ -80,12 +80,12 @@ public:
bool fn1(CStarField *starField, CSurfaceArea *surfaceArea, CStarCamera *camera);
void fn2(CVideoSurface *surface, CStarField *starField, CStarMarkers *markers);
-
+
/**
* Increments the index for the number of matches
*/
void incMatches();
-
+
/**
* Draw the crosshairs for a given star
*/
@@ -101,12 +101,12 @@ public:
* Erase crosshairs for the most recently selected star
*/
void eraseCurrent(CSurfaceArea *surfaceArea);
-
+
/**
* Draw crosshairs at the given position
*/
void drawAt(const FPoint &pt, CSurfaceArea *surfaceArea);
-
+
/**
* Returns the position of the most recently selected star
*/
diff --git a/engines/titanic/star_control/star_field.h b/engines/titanic/star_control/star_field.h
index bd3f8aecb6..3b1c3db2b5 100644
--- a/engines/titanic/star_control/star_field.h
+++ b/engines/titanic/star_control/star_field.h
@@ -78,17 +78,17 @@ public:
void set2(int val);
int get54() const;
void set54(int val);
-
+
/**
* Gets the current display mode
*/
StarMode getMode() const;
-
+
/**
* Sets the display mode
*/
void setMode(StarMode mode);
-
+
/**
* Toggles whether the big box is visible
*/
diff --git a/engines/titanic/star_control/star_view.h b/engines/titanic/star_control/star_view.h
index 553195b0c7..241efbcde5 100644
--- a/engines/titanic/star_control/star_view.h
+++ b/engines/titanic/star_control/star_view.h
@@ -148,14 +148,14 @@ public:
* Toggles between starfield and photo modes
*/
void toggleMode();
-
+
void fn11();
/**
* Toggles whether the viewpoint box is visible in the starfield
*/
void toggleBox();
-
+
void fn13();
void fn14();
@@ -163,7 +163,7 @@ public:
* Called when the photograph is used on the navigation computer
*/
void setHasReference();
-
+
/**
* Handles locking in a star
*/
diff --git a/engines/titanic/star_control/unmarked_camera_mover.cpp b/engines/titanic/star_control/unmarked_camera_mover.cpp
index c879dc25e8..401f550bee 100644
--- a/engines/titanic/star_control/unmarked_camera_mover.cpp
+++ b/engines/titanic/star_control/unmarked_camera_mover.cpp
@@ -48,7 +48,7 @@ void CUnmarkedCameraMover::moveTo(const FVector &srcV, const FVector &destV, con
void CUnmarkedCameraMover::transitionBetweenOrientations(const FVector &v1, const FVector &v2, const FVector &v3, const FMatrix &m) {
if (isLocked())
decLockCount();
-
+
FVector vector1 = v1;
FVector vector2 = v2;
FPose matrix1 = vector2.getFrameTransform(vector1);
diff --git a/engines/titanic/star_control/viewport.cpp b/engines/titanic/star_control/viewport.cpp
index e368dfa317..d66ff423c6 100644
--- a/engines/titanic/star_control/viewport.cpp
+++ b/engines/titanic/star_control/viewport.cpp
@@ -178,7 +178,7 @@ void CViewport::randomizeOrientation() {
FPose m1(X_AXIS, ranRotAngleX);
FPose m2(Y_AXIS, ranRotAngleY);
FPose m3(Z_AXIS, ranRotAngleZ);
-
+
FPose s1(m1, m2);
FPose s2(s1, m3);
diff --git a/engines/titanic/star_control/viewport.h b/engines/titanic/star_control/viewport.h
index 082d063233..ae42e84ea4 100644
--- a/engines/titanic/star_control/viewport.h
+++ b/engines/titanic/star_control/viewport.h
@@ -35,7 +35,7 @@ namespace Titanic {
* For starview it should be white
* For skyview it should be pink
*/
-enum StarColor { WHITE = 0, PINK = 2 };
+enum StarColor { WHITE = 0, PINK = 2 };
/**
* Implements the viewport functionality for viewing the star field in
@@ -111,14 +111,14 @@ public:
* The view has changed between starview and skyview
* Change the enum that tracks the color of the stars
* Also change the X coordinate pixel offset used for star drawing
- */
+ */
void changeStarColorPixel(StarMode mode, double pixelOffSet);
void reposition(double factor);
/**
* Applys a rotation matrix to the current
* orientation
- */
+ */
void changeOrientation(const FMatrix &matrix);
FPose getPose();
@@ -148,15 +148,15 @@ public:
/**
* Sets the center vector y angle
* The actual center y value doesn't
- * change untill reset is called
- */
+ * change untill reset is called
+ */
void setCenterYAngle(double angleDegrees);
/**
* Sets the center vector z angle
* The actual center z value doesn't
- * change untill reset is called
- */
+ * change untill reset is called
+ */
void setCenterZAngle(double angleDegrees);
};
diff --git a/engines/titanic/support/avi_surface.cpp b/engines/titanic/support/avi_surface.cpp
index 3b22a4fee2..ff439abe25 100644
--- a/engines/titanic/support/avi_surface.cpp
+++ b/engines/titanic/support/avi_surface.cpp
@@ -489,7 +489,7 @@ Graphics::ManagedSurface *AVISurface::duplicateTransparency() const {
bool AVISurface::playCutscene(const Rect &r, uint startFrame, uint endFrame) {
if (g_vm->shouldQuit())
return false;
-
+
// TODO: Fixes slight "jumping back" when rotating in place in Top Of Well
// balcony between two elevators. Need a more generalized fix at some point
if (_movieName == "z48.avi")
diff --git a/engines/titanic/support/simple_file.cpp b/engines/titanic/support/simple_file.cpp
index 103f062ac6..83d731f7f2 100644
--- a/engines/titanic/support/simple_file.cpp
+++ b/engines/titanic/support/simple_file.cpp
@@ -388,7 +388,7 @@ void SimpleFile::writeIndent(uint indent) const {
write("\t", 1);
}
-bool SimpleFile::IsClassStart() {
+bool SimpleFile::isClassStart() {
char c;
do {
diff --git a/engines/titanic/support/simple_file.h b/engines/titanic/support/simple_file.h
index 01aaa86925..f71ef5b717 100644
--- a/engines/titanic/support/simple_file.h
+++ b/engines/titanic/support/simple_file.h
@@ -238,7 +238,7 @@ public:
* an opening or closing squiggly bracket denoting a class
* definition start or end. Returns true if it's a class start
*/
- bool IsClassStart();
+ bool isClassStart();
/**
* Write the starting header for a class definition
diff --git a/engines/titanic/titanic.cpp b/engines/titanic/titanic.cpp
index e0e4a07ce6..0931d91806 100644
--- a/engines/titanic/titanic.cpp
+++ b/engines/titanic/titanic.cpp
@@ -49,7 +49,6 @@
#include "common/translation.h"
#include "engines/util.h"
#include "graphics/scaler.h"
-#include "graphics/thumbnail.h"
#include "graphics/screen.h"
#include "gui/saveload.h"
@@ -191,7 +190,7 @@ void TitanicEngine::setRoomNames() {
bool TitanicEngine::canLoadGameStateCurrently() {
CGameManager *gameManager = _window->_gameManager;
CScreenManager *screenMan = CScreenManager::_screenManagerPtr;
-
+
if (!gameManager)
// Allow loading from copyright screen and continue dialogs
return true;
@@ -256,11 +255,6 @@ CString TitanicEngine::getSavegameName(int slot) {
TitanicSavegameHeader header;
bool isValid = CProjectItem::readSavegameHeader(&file, header);
- if (header._thumbnail) {
- header._thumbnail->free();
- delete header._thumbnail;
- }
-
file.close();
if (isValid)
diff --git a/engines/titanic/true_talk/doorbot_script.cpp b/engines/titanic/true_talk/doorbot_script.cpp
index d7389d1cb7..0b33704ba5 100644
--- a/engines/titanic/true_talk/doorbot_script.cpp
+++ b/engines/titanic/true_talk/doorbot_script.cpp
@@ -71,6 +71,8 @@ static const RoomDialogueId ROOM_DIALOGUES2_DE[] = {
DoorbotScript::DoorbotScript(int val1, const char *charClass, int v2,
const char *charName, int v3, int val2, int v4, int v5, int v6, int v7) :
TTnpcScript(val1, charClass, v2, charName, v3, val2, v4, v5, v6, v7) {
+ _stateIndex = _doorbotState = 0;
+
loadRanges("Ranges/Doorbot");
loadResponses("Responses/Doorbot");
setupSentences();
@@ -108,7 +110,7 @@ void DoorbotScript::setupSentences() {
int DoorbotScript::chooseResponse(const TTroomScript *roomScript, const TTsentence *sentence, uint tag) {
if (tag == MKTAG('D', 'N', 'A', '1') || tag == MKTAG('H', 'H', 'G', 'Q') ||
tag == MKTAG('A', 'N', 'S', 'W') || tag == MKTAG('S', 'U', 'M', 'S')) {
- if (_stateIndex > 9)
+ if (_stateIndex > 8)
_stateIndex = 0;
addResponse(TRANSLATE(STATE_ARRAY_EN[_stateIndex], STATE_ARRAY_DE[_stateIndex]));
applyResponse();
diff --git a/engines/titanic/true_talk/tt_parser.cpp b/engines/titanic/true_talk/tt_parser.cpp
index 5c48de4182..2caeef45dd 100644
--- a/engines/titanic/true_talk/tt_parser.cpp
+++ b/engines/titanic/true_talk/tt_parser.cpp
@@ -960,7 +960,7 @@ int TTparser::considerRequests(TTword *word) {
case WC_ABSTRACT:
if (word->_id != 300) {
status = processModifiers(3, word);
- } else if (!_conceptP->findByWordClass(WC_THING)) {
+ } else if (!_conceptP || !_conceptP->findByWordClass(WC_THING)) {
status = processModifiers(3, word);
} else {
word->_id = atoi(word->_text.c_str());
@@ -1760,7 +1760,7 @@ void TTparser::preprocessGerman(TTstring &line) {
continue;
const char *wordEndP = p + _replacements4[idx].size();
-
+
for (int sIdx = 0; sIdx < 12; ++sIdx) {
const char *suffixP = SUFFIXES[sIdx];
if (!strncmp(wordEndP, suffixP, strlen(suffixP))) {
diff --git a/engines/titanic/true_talk/tt_talker.h b/engines/titanic/true_talk/tt_talker.h
index 4f0b59c044..68b77d8b75 100644
--- a/engines/titanic/true_talk/tt_talker.h
+++ b/engines/titanic/true_talk/tt_talker.h
@@ -54,7 +54,7 @@ public:
* End the speech
*/
void endSpeech(int val);
-
+
/**
* Called when a speech is finished, to signal to the associated character
* that the speech is over
diff --git a/engines/titanic/true_talk/tt_vocab.cpp b/engines/titanic/true_talk/tt_vocab.cpp
index e9fc098749..0269e71cee 100644
--- a/engines/titanic/true_talk/tt_vocab.cpp
+++ b/engines/titanic/true_talk/tt_vocab.cpp
@@ -1,585 +1,585 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "titanic/true_talk/tt_vocab.h"
-#include "titanic/true_talk/script_handler.h"
-#include "titanic/true_talk/tt_action.h"
-#include "titanic/true_talk/tt_adj.h"
-#include "titanic/true_talk/tt_major_word.h"
-#include "titanic/true_talk/tt_picture.h"
-#include "titanic/true_talk/tt_pronoun.h"
-#include "titanic/titanic.h"
-#include "titanic/translation.h"
-#include "common/file.h"
-
-namespace Titanic {
-
-TTvocab::TTvocab(VocabMode vocabMode): _headP(nullptr), _tailP(nullptr),
- _word(nullptr), _vocabMode(vocabMode) {
- load("STVOCAB");
-}
-
-TTvocab::~TTvocab() {
- if (_headP) {
- _headP->deleteSiblings();
- delete _headP;
- _headP = _tailP = nullptr;
- }
-}
-
-int TTvocab::load(const CString &name) {
- SimpleFile *file = g_vm->_exeResources._owner->openResource(name);
- int result = 0;
- bool skipFlag;
-
- while (!result && !file->eos()) {
- skipFlag = false;
- WordClass wordClass = (WordClass)file->readNumber();
- TTstring space(" ");
-
- switch (wordClass) {
- case WC_UNKNOWN: {
- if (_word)
- result = _word->readSyn(file);
- skipFlag = true;
- break;
- }
-
- case WC_ACTION: {
- TTaction *word = new TTaction(space, WC_UNKNOWN, 0, 0, 0);
- result = word->load(file);
- _word = word;
- break;
- }
-
- case WC_THING: {
- TTpicture *word = new TTpicture(space, WC_UNKNOWN, 0, 0, 0, 0, 0);
- result = word->load(file);
- _word = word;
- break;
- }
-
- case WC_ABSTRACT:
- case WC_ADVERB: {
- TTmajorWord *word = new TTmajorWord(space, WC_UNKNOWN, 0, 0);
- result = word->load(file, wordClass);
- _word = word;
- break;
- }
-
- case WC_ARTICLE:
- case WC_CONJUNCTION:
- case WC_PREPOSITION: {
- TTword *word = new TTword(space, WC_UNKNOWN, 0);
- result = word->load(file, wordClass);
- _word = word;
- break;
- }
-
- case WC_ADJECTIVE: {
- TTadj *word = new TTadj(space, WC_UNKNOWN, 0, 0, 0);
- result = word->load(file);
- _word = word;
- break;
- }
-
- case WC_PRONOUN: {
- TTpronoun *word = new TTpronoun(space, WC_UNKNOWN, 0, 0, 0);
- result = word->load(file);
- _word = word;
- break;
- }
-
- default:
- result = 4;
- break;
- }
-
- if (!skipFlag && _word) {
- if (result) {
- // Something wrong occurred, so delete word
- delete _word;
- _word = nullptr;
- } else {
- // Add the word to the master vocab list
- addWord(_word);
- }
- }
- }
-
- // Close resource and return result
- delete file;
- return result;
-}
-
-void TTvocab::addWord(TTword *word) {
- TTword *existingWord = g_language == Common::DE_DEU ? nullptr :
- findWord(word->_text);
-
- if (existingWord) {
- if (word->_synP) {
- // Move over the synonym
- existingWord->appendNode(word->_synP);
- word->_synP = nullptr;
- }
-
- _word = nullptr;
- if (word)
- delete word;
- } else if (_tailP) {
- _tailP->_nextP = word;
- _tailP = word;
- } else {
- if (!_headP)
- _headP = word;
-
- _tailP = word;
- }
-}
-
-TTword *TTvocab::findWord(const TTstring &str) {
- TTsynonym *tempNode = new TTsynonym();
- bool flag = false;
- TTword *word = _headP;
-
- while (word && !flag) {
- if (_vocabMode != VOCAB_MODE_EN || strcmp(word->c_str(), str)) {
- if (word->findSynByName(str, tempNode, _vocabMode))
- flag = true;
- else
- word = word->_nextP;
- } else {
- flag = true;
- }
- }
-
- delete tempNode;
- return word;
-}
-
-TTword *TTvocab::getWord(TTstring &str, TTword **srcWord) const {
- TTword *word = getPrimeWord(str, srcWord);
-
- if (!word) {
- TTstring tempStr(str);
- if (tempStr.size() > 2) {
- word = getSuffixedWord(tempStr, srcWord);
-
- if (!word)
- word = getPrefixedWord(tempStr, srcWord);
- }
- }
-
- return word;
-}
-
-TTword *TTvocab::getPrimeWord(TTstring &str, TTword **srcWord) const {
- TTsynonym tempSyn;
- char c = str.charAt(0);
- TTword *newWord = nullptr;
- TTword *vocabP;
-
- if (Common::isDigit(c)) {
- // Number
- vocabP = _headP;
- newWord = new TTword(str, WC_ABSTRACT, 300);
- } else {
- // Standard word
- for (vocabP = _headP; vocabP; vocabP = vocabP->_nextP) {
- if (_vocabMode == VOCAB_MODE_EN && !strcmp(str.c_str(), vocabP->c_str())) {
- newWord = vocabP->copy();
- newWord->_nextP = nullptr;
- newWord->setSyn(nullptr);
- break;
- } else if (vocabP->findSynByName(str, &tempSyn, _vocabMode)) {
- // Create a copy of the word and the found synonym
- TTsynonym *newSyn = new TTsynonym(tempSyn);
- newSyn->_nextP = newSyn->_priorP = nullptr;
- newWord = vocabP->copy();
- newWord->_nextP = nullptr;
- newWord->setSyn(newSyn);
- break;
- }
- }
- }
-
- if (srcWord)
- // Pass out the pointer to the original word
- *srcWord = vocabP;
-
- // Return the new copy of the word
- return newWord;
-}
-
-TTword *TTvocab::getSuffixedWord(TTstring &str, TTword **srcWord) const {
- TTstring tempStr(str);
- TTword *word = nullptr;
-
- if (g_language == Common::DE_DEU) {
- static const char *const SUFFIXES[11] = {
- "est", "em", "en", "er", "es", "et", "st",
- "s", "e", "n", "t"
- };
-
- for (int idx = 0; idx < 11; ++idx) {
- if (tempStr.hasSuffix(SUFFIXES[idx])) {
- tempStr.deleteSuffix(strlen(SUFFIXES[idx]));
- word = getPrimeWord(tempStr, srcWord);
- if (word)
- break;
- tempStr = str;
- }
- }
-
- if (word)
- word->setSynStr(str);
- return word;
- }
-
- if (tempStr.hasSuffix("s")) {
- tempStr.deleteSuffix(1);
- word = getPrimeWord(tempStr);
-
- if (!word) {
- if (!tempStr.hasSuffix("e")) {
- tempStr = str;
- } else {
- tempStr.deleteLastChar();
- word = getPrimeWord(tempStr);
- }
- }
-
- } else if (tempStr.hasSuffix("ing")) {
- tempStr.deleteSuffix(3);
- word = getPrimeWord(tempStr);
-
- if (word) {
- if (word->_wordClass == 1) {
- delete word;
- word = nullptr;
- } else {
- delete word;
- word = new TTadj(str, WC_ADJECTIVE, 0, 0, 0);
- }
- } else {
- tempStr += "e";
- word = getPrimeWord(tempStr);
-
- if (word) {
- if (word->_wordClass != 1) {
- delete word;
- word = new TTadj(str, WC_ADJECTIVE, 0, 0, 0);
- }
- } else {
- tempStr.deleteSuffix(2);
- word = getPrimeWord(tempStr);
-
- if (word) {
- if (word->_wordClass != 1) {
- delete word;
- word = new TTadj(str, WC_ADJECTIVE, 0, 0, 0);
- }
- } else {
- tempStr = str;
- }
- }
- }
-
- } else if (tempStr.hasSuffix("ed")) {
- tempStr.deleteSuffix(1);
- word = getPrimeWord(tempStr);
-
- if (!word) {
- tempStr.deleteSuffix(1);
- word = getPrimeWord(tempStr);
- }
-
- if (word) {
- if (word->_wordClass == WC_ACTION) {
- TTaction *action = dynamic_cast<TTaction *>(word);
- assert(action);
- action->setVal(1);
- }
- } else {
- tempStr = str;
- }
-
- } else if (tempStr.hasSuffix("ly")) {
- tempStr.deleteSuffix(2);
- word = getPrimeWord(tempStr);
-
- if (word) {
- delete word;
- word = new TTword(str, WC_ADVERB, 0);
- } else {
- tempStr = str;
- }
-
- } else if (tempStr.hasSuffix("er")) {
- tempStr.deleteSuffix(1);
- word = getPrimeWord(tempStr);
-
- if (word) {
- if (word->_wordClass == WC_ADJECTIVE) {
- TTadj *adj = static_cast<TTadj *>(word);
- int val1 = word->proc15();
- int val2 = word->proc15();
-
- if (val2 < 5) {
- if (--val1 > 0) {
- adj->adjFn1(val1);
- }
- } else {
- if (++val1 < 11) {
- adj->adjFn1(val1);
- }
- }
- }
- } else {
- tempStr.deleteSuffix(1);
- word = getPrimeWord(tempStr);
-
- if (word) {
- if (word->_wordClass == WC_ADJECTIVE) {
- TTadj *adj = dynamic_cast<TTadj *>(word);
- int val1 = word->proc15();
- int val2 = word->proc15();
-
- if (val2 < 5) {
- if (--val1 > 0) {
- adj->adjFn1(val1);
- }
- } else {
- if (++val1 < 11) {
- adj->adjFn1(val1);
- }
- }
- }
- } else {
- tempStr.deleteSuffix(1);
- word = getPrimeWord(tempStr);
-
- if (word && word->_wordClass == WC_ADJECTIVE) {
- TTadj *adj = dynamic_cast<TTadj *>(word);
- int val1 = word->proc15();
- int val2 = word->proc15();
-
- if (val2 < 5) {
- if (--val1 > 0) {
- adj->adjFn1(val1);
- }
- } else {
- if (++val1 < 11) {
- adj->adjFn1(val1);
- }
- }
- }
- }
- }
-
- } else if (tempStr.hasSuffix("est")) {
- tempStr.deleteSuffix(2);
- word = getPrimeWord(tempStr);
-
- if (word) {
- if (word->_wordClass == WC_ADJECTIVE) {
- TTadj *adj = static_cast<TTadj *>(word);
- int val1 = word->proc15();
- int val2 = word->proc15();
-
- if (val2 < 5) {
- if (--val1 > 0) {
- adj->adjFn1(val1);
- }
- } else {
- if (++val1 < 11) {
- adj->adjFn1(val1);
- }
- }
- }
- } else {
- tempStr.deleteSuffix(1);
- word = getPrimeWord(tempStr);
-
- if (word) {
- if (word->_wordClass == WC_ADJECTIVE) {
- TTadj *adj = dynamic_cast<TTadj *>(word);
- int val1 = word->proc15();
- int val2 = word->proc15();
-
- if (val2 < 5) {
- if (--val1 > 0) {
- adj->adjFn1(val1);
- }
- } else {
- if (++val1 < 11) {
- adj->adjFn1(val1);
- }
- }
- }
- } else {
- tempStr.deleteSuffix(1);
- word = getPrimeWord(tempStr);
-
- if (word) {
- TTadj *adj = dynamic_cast<TTadj *>(word);
- int val1 = word->proc15();
- int val2 = word->proc15();
-
- if (val2 < 5) {
- if (--val1 > 0) {
- adj->adjFn1(val1);
- }
- } else {
- if (++val1 < 11) {
- adj->adjFn1(val1);
- }
- }
- }
- }
- }
-
- } else if (tempStr.hasSuffix("s*")) {
- tempStr.deleteSuffix(2);
- word = getPrimeWord(tempStr);
-
- if (word) {
- if (word->_wordClass == WC_PRONOUN || word->_wordClass == WC_ADVERB) {
- delete word;
- TTstring isStr("is");
- word = getPrimeWord(isStr);
- } else {
- switch (word->_id) {
- case 200:
- if (word->proc10() == 2) {
- delete word;
- word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 5);
- } else if (word->proc10() == 1) {
- delete word;
- word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 4);
- }
- break;
-
- case 201:
- delete word;
- word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 5);
- break;
-
- case 202:
- case 203:
- if (word->proc10() == 2) {
- delete word;
- word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 5);
- } else {
- int val = word->proc10() == 1 ? 0 : 4;
- delete word;
- word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, val);
- }
- break;
-
- case 204:
- delete word;
- word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 6);
- break;
-
- default:
- delete word;
- word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 0);
- break;
- }
- }
- }
- }
-
- if (word)
- word->setSynStr(str);
-
- return word;
-}
-
-TTword *TTvocab::getPrefixedWord(TTstring &str, TTword **srcWord) const {
- TTstring tempStr(str);
- TTword *word = nullptr;
- int prefixLen = 0;
-
- if (tempStr.hasPrefix("pre")) {
- prefixLen = 3;
- } else if (tempStr.hasPrefix("re") || tempStr.hasPrefix("co")) {
- prefixLen = 2;
- } else if (tempStr.hasPrefix("inter") || tempStr.hasPrefix("multi")) {
- prefixLen = 5;
- } else if (tempStr.hasPrefix("over") || tempStr.hasPrefix("post") || tempStr.hasPrefix("self")) {
- prefixLen = 4;
- }
-
- if (prefixLen) {
- // Known prefix found, so scan for word without prefix
- tempStr.deletePrefix(prefixLen);
- word = getPrimeWord(tempStr);
- if (word)
- tempStr = str;
-
- } else if (tempStr.hasPrefix("anti") || tempStr.hasPrefix("counter")) {
- prefixLen = tempStr[0] == 'a' ? 4 : 7;
-
- tempStr.deletePrefix(prefixLen);
- word = getPrimeWord(tempStr);
- if (!word)
- tempStr = str;
- else if (word->_wordClass == 8) {
- delete word;
- word = nullptr;
- }
-
- } else if (tempStr.hasPrefix("hyper") || tempStr.hasPrefix("super") ||
- tempStr.hasPrefix("ultra")) {
- tempStr.deletePrefix(5);
- word = getPrimeWord(tempStr);
-
- if (!word)
- tempStr = str;
- else if (word->_wordClass == WC_ADJECTIVE) {
- TTadj *adj = static_cast<TTadj *>(word);
- int val1 = word->proc15();
- int val2 = word->proc15();
-
- if (val2 < 5) {
- if (--val1 > 0)
- adj->adjFn1(val1);
- } else if (++val1 < 11) {
- adj->adjFn1(val1);
- }
- }
- }
-
- if (word) {
- // Set the original word on either the found word or synonym
- if (word->hasSynonyms())
- word->setSynStr(str);
- else
- word->_text = str;
- }
-
- return word;
-}
-
-} // End of namespace Titanic
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "titanic/true_talk/tt_vocab.h"
+#include "titanic/true_talk/script_handler.h"
+#include "titanic/true_talk/tt_action.h"
+#include "titanic/true_talk/tt_adj.h"
+#include "titanic/true_talk/tt_major_word.h"
+#include "titanic/true_talk/tt_picture.h"
+#include "titanic/true_talk/tt_pronoun.h"
+#include "titanic/titanic.h"
+#include "titanic/translation.h"
+#include "common/file.h"
+
+namespace Titanic {
+
+TTvocab::TTvocab(VocabMode vocabMode): _headP(nullptr), _tailP(nullptr),
+ _word(nullptr), _vocabMode(vocabMode) {
+ load("STVOCAB");
+}
+
+TTvocab::~TTvocab() {
+ if (_headP) {
+ _headP->deleteSiblings();
+ delete _headP;
+ _headP = _tailP = nullptr;
+ }
+}
+
+int TTvocab::load(const CString &name) {
+ SimpleFile *file = g_vm->_exeResources._owner->openResource(name);
+ int result = 0;
+ bool skipFlag;
+
+ while (!result && !file->eos()) {
+ skipFlag = false;
+ WordClass wordClass = (WordClass)file->readNumber();
+ TTstring space(" ");
+
+ switch (wordClass) {
+ case WC_UNKNOWN: {
+ if (_word)
+ result = _word->readSyn(file);
+ skipFlag = true;
+ break;
+ }
+
+ case WC_ACTION: {
+ TTaction *word = new TTaction(space, WC_UNKNOWN, 0, 0, 0);
+ result = word->load(file);
+ _word = word;
+ break;
+ }
+
+ case WC_THING: {
+ TTpicture *word = new TTpicture(space, WC_UNKNOWN, 0, 0, 0, 0, 0);
+ result = word->load(file);
+ _word = word;
+ break;
+ }
+
+ case WC_ABSTRACT:
+ case WC_ADVERB: {
+ TTmajorWord *word = new TTmajorWord(space, WC_UNKNOWN, 0, 0);
+ result = word->load(file, wordClass);
+ _word = word;
+ break;
+ }
+
+ case WC_ARTICLE:
+ case WC_CONJUNCTION:
+ case WC_PREPOSITION: {
+ TTword *word = new TTword(space, WC_UNKNOWN, 0);
+ result = word->load(file, wordClass);
+ _word = word;
+ break;
+ }
+
+ case WC_ADJECTIVE: {
+ TTadj *word = new TTadj(space, WC_UNKNOWN, 0, 0, 0);
+ result = word->load(file);
+ _word = word;
+ break;
+ }
+
+ case WC_PRONOUN: {
+ TTpronoun *word = new TTpronoun(space, WC_UNKNOWN, 0, 0, 0);
+ result = word->load(file);
+ _word = word;
+ break;
+ }
+
+ default:
+ result = 4;
+ break;
+ }
+
+ if (!skipFlag && _word) {
+ if (result) {
+ // Something wrong occurred, so delete word
+ delete _word;
+ _word = nullptr;
+ } else {
+ // Add the word to the master vocab list
+ addWord(_word);
+ }
+ }
+ }
+
+ // Close resource and return result
+ delete file;
+ return result;
+}
+
+void TTvocab::addWord(TTword *word) {
+ TTword *existingWord = g_language == Common::DE_DEU ? nullptr :
+ findWord(word->_text);
+
+ if (existingWord) {
+ if (word->_synP) {
+ // Move over the synonym
+ existingWord->appendNode(word->_synP);
+ word->_synP = nullptr;
+ }
+
+ _word = nullptr;
+ if (word)
+ delete word;
+ } else if (_tailP) {
+ _tailP->_nextP = word;
+ _tailP = word;
+ } else {
+ if (!_headP)
+ _headP = word;
+
+ _tailP = word;
+ }
+}
+
+TTword *TTvocab::findWord(const TTstring &str) {
+ TTsynonym *tempNode = new TTsynonym();
+ bool flag = false;
+ TTword *word = _headP;
+
+ while (word && !flag) {
+ if (_vocabMode != VOCAB_MODE_EN || strcmp(word->c_str(), str)) {
+ if (word->findSynByName(str, tempNode, _vocabMode))
+ flag = true;
+ else
+ word = word->_nextP;
+ } else {
+ flag = true;
+ }
+ }
+
+ delete tempNode;
+ return word;
+}
+
+TTword *TTvocab::getWord(TTstring &str, TTword **srcWord) const {
+ TTword *word = getPrimeWord(str, srcWord);
+
+ if (!word) {
+ TTstring tempStr(str);
+ if (tempStr.size() > 2) {
+ word = getSuffixedWord(tempStr, srcWord);
+
+ if (!word)
+ word = getPrefixedWord(tempStr, srcWord);
+ }
+ }
+
+ return word;
+}
+
+TTword *TTvocab::getPrimeWord(TTstring &str, TTword **srcWord) const {
+ TTsynonym tempSyn;
+ char c = str.charAt(0);
+ TTword *newWord = nullptr;
+ TTword *vocabP;
+
+ if (Common::isDigit(c)) {
+ // Number
+ vocabP = _headP;
+ newWord = new TTword(str, WC_ABSTRACT, 300);
+ } else {
+ // Standard word
+ for (vocabP = _headP; vocabP; vocabP = vocabP->_nextP) {
+ if (_vocabMode == VOCAB_MODE_EN && !strcmp(str.c_str(), vocabP->c_str())) {
+ newWord = vocabP->copy();
+ newWord->_nextP = nullptr;
+ newWord->setSyn(nullptr);
+ break;
+ } else if (vocabP->findSynByName(str, &tempSyn, _vocabMode)) {
+ // Create a copy of the word and the found synonym
+ TTsynonym *newSyn = new TTsynonym(tempSyn);
+ newSyn->_nextP = newSyn->_priorP = nullptr;
+ newWord = vocabP->copy();
+ newWord->_nextP = nullptr;
+ newWord->setSyn(newSyn);
+ break;
+ }
+ }
+ }
+
+ if (srcWord)
+ // Pass out the pointer to the original word
+ *srcWord = vocabP;
+
+ // Return the new copy of the word
+ return newWord;
+}
+
+TTword *TTvocab::getSuffixedWord(TTstring &str, TTword **srcWord) const {
+ TTstring tempStr(str);
+ TTword *word = nullptr;
+
+ if (g_language == Common::DE_DEU) {
+ static const char *const SUFFIXES[11] = {
+ "est", "em", "en", "er", "es", "et", "st",
+ "s", "e", "n", "t"
+ };
+
+ for (int idx = 0; idx < 11; ++idx) {
+ if (tempStr.hasSuffix(SUFFIXES[idx])) {
+ tempStr.deleteSuffix(strlen(SUFFIXES[idx]));
+ word = getPrimeWord(tempStr, srcWord);
+ if (word)
+ break;
+ tempStr = str;
+ }
+ }
+
+ if (word)
+ word->setSynStr(str);
+ return word;
+ }
+
+ if (tempStr.hasSuffix("s")) {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (!word) {
+ if (!tempStr.hasSuffix("e")) {
+ tempStr = str;
+ } else {
+ tempStr.deleteLastChar();
+ word = getPrimeWord(tempStr);
+ }
+ }
+
+ } else if (tempStr.hasSuffix("ing")) {
+ tempStr.deleteSuffix(3);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == 1) {
+ delete word;
+ word = nullptr;
+ } else {
+ delete word;
+ word = new TTadj(str, WC_ADJECTIVE, 0, 0, 0);
+ }
+ } else {
+ tempStr += "e";
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass != 1) {
+ delete word;
+ word = new TTadj(str, WC_ADJECTIVE, 0, 0, 0);
+ }
+ } else {
+ tempStr.deleteSuffix(2);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass != 1) {
+ delete word;
+ word = new TTadj(str, WC_ADJECTIVE, 0, 0, 0);
+ }
+ } else {
+ tempStr = str;
+ }
+ }
+ }
+
+ } else if (tempStr.hasSuffix("ed")) {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (!word) {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+ }
+
+ if (word) {
+ if (word->_wordClass == WC_ACTION) {
+ TTaction *action = dynamic_cast<TTaction *>(word);
+ assert(action);
+ action->setVal(1);
+ }
+ } else {
+ tempStr = str;
+ }
+
+ } else if (tempStr.hasSuffix("ly")) {
+ tempStr.deleteSuffix(2);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ delete word;
+ word = new TTword(str, WC_ADVERB, 0);
+ } else {
+ tempStr = str;
+ }
+
+ } else if (tempStr.hasSuffix("er")) {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ } else {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = dynamic_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ } else {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word && word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = dynamic_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ }
+ }
+
+ } else if (tempStr.hasSuffix("est")) {
+ tempStr.deleteSuffix(2);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ } else {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = dynamic_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ } else {
+ tempStr.deleteSuffix(1);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ TTadj *adj = dynamic_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0) {
+ adj->adjFn1(val1);
+ }
+ } else {
+ if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+ }
+ }
+
+ } else if (tempStr.hasSuffix("s*")) {
+ tempStr.deleteSuffix(2);
+ word = getPrimeWord(tempStr);
+
+ if (word) {
+ if (word->_wordClass == WC_PRONOUN || word->_wordClass == WC_ADVERB) {
+ delete word;
+ TTstring isStr("is");
+ word = getPrimeWord(isStr);
+ } else {
+ switch (word->_id) {
+ case 200:
+ if (word->proc10() == 2) {
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 5);
+ } else if (word->proc10() == 1) {
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 4);
+ }
+ break;
+
+ case 201:
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 5);
+ break;
+
+ case 202:
+ case 203:
+ if (word->proc10() == 2) {
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 5);
+ } else {
+ int val = word->proc10() == 1 ? 0 : 4;
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, val);
+ }
+ break;
+
+ case 204:
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 6);
+ break;
+
+ default:
+ delete word;
+ word = new TTpronoun(tempStr, WC_PRONOUN, 601, 0, 0);
+ break;
+ }
+ }
+ }
+ }
+
+ if (word)
+ word->setSynStr(str);
+
+ return word;
+}
+
+TTword *TTvocab::getPrefixedWord(TTstring &str, TTword **srcWord) const {
+ TTstring tempStr(str);
+ TTword *word = nullptr;
+ int prefixLen = 0;
+
+ if (tempStr.hasPrefix("pre")) {
+ prefixLen = 3;
+ } else if (tempStr.hasPrefix("re") || tempStr.hasPrefix("co")) {
+ prefixLen = 2;
+ } else if (tempStr.hasPrefix("inter") || tempStr.hasPrefix("multi")) {
+ prefixLen = 5;
+ } else if (tempStr.hasPrefix("over") || tempStr.hasPrefix("post") || tempStr.hasPrefix("self")) {
+ prefixLen = 4;
+ }
+
+ if (prefixLen) {
+ // Known prefix found, so scan for word without prefix
+ tempStr.deletePrefix(prefixLen);
+ word = getPrimeWord(tempStr);
+ if (word)
+ tempStr = str;
+
+ } else if (tempStr.hasPrefix("anti") || tempStr.hasPrefix("counter")) {
+ prefixLen = tempStr[0] == 'a' ? 4 : 7;
+
+ tempStr.deletePrefix(prefixLen);
+ word = getPrimeWord(tempStr);
+ if (!word)
+ tempStr = str;
+ else if (word->_wordClass == 8) {
+ delete word;
+ word = nullptr;
+ }
+
+ } else if (tempStr.hasPrefix("hyper") || tempStr.hasPrefix("super") ||
+ tempStr.hasPrefix("ultra")) {
+ tempStr.deletePrefix(5);
+ word = getPrimeWord(tempStr);
+
+ if (!word)
+ tempStr = str;
+ else if (word->_wordClass == WC_ADJECTIVE) {
+ TTadj *adj = static_cast<TTadj *>(word);
+ int val1 = word->proc15();
+ int val2 = word->proc15();
+
+ if (val2 < 5) {
+ if (--val1 > 0)
+ adj->adjFn1(val1);
+ } else if (++val1 < 11) {
+ adj->adjFn1(val1);
+ }
+ }
+ }
+
+ if (word) {
+ // Set the original word on either the found word or synonym
+ if (word->hasSynonyms())
+ word->setSynStr(str);
+ else
+ word->_text = str;
+ }
+
+ return word;
+}
+
+} // End of namespace Titanic
diff --git a/engines/toltecs/detection.cpp b/engines/toltecs/detection.cpp
index 9303760057..0cd9596c8c 100644
--- a/engines/toltecs/detection.cpp
+++ b/engines/toltecs/detection.cpp
@@ -276,7 +276,7 @@ SaveStateList ToltecsMetaEngine::listSaves(const char *target) const {
if (slotNum >= 0 && slotNum <= 999) {
Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
if (in) {
- if (Toltecs::ToltecsEngine::readSaveHeader(in, false, header) == Toltecs::ToltecsEngine::kRSHENoError) {
+ if (Toltecs::ToltecsEngine::readSaveHeader(in, header) == Toltecs::ToltecsEngine::kRSHENoError) {
saveList.push_back(SaveStateDescriptor(slotNum, header.description));
}
delete in;
@@ -325,7 +325,7 @@ SaveStateDescriptor ToltecsMetaEngine::querySaveMetaInfos(const char *target, in
Toltecs::ToltecsEngine::SaveHeader header;
Toltecs::ToltecsEngine::kReadSaveHeaderError error;
- error = Toltecs::ToltecsEngine::readSaveHeader(in, true, header);
+ error = Toltecs::ToltecsEngine::readSaveHeader(in, header, false);
delete in;
if (error == Toltecs::ToltecsEngine::kRSHENoError) {
diff --git a/engines/toltecs/menu.cpp b/engines/toltecs/menu.cpp
index 5fc0599c2a..c4373265e6 100644
--- a/engines/toltecs/menu.cpp
+++ b/engines/toltecs/menu.cpp
@@ -525,7 +525,7 @@ int MenuSystem::loadSavegamesList() {
if (slotNum >= 0 && slotNum <= 999) {
Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
if (in) {
- if (Toltecs::ToltecsEngine::readSaveHeader(in, false, header) == Toltecs::ToltecsEngine::kRSHENoError) {
+ if (Toltecs::ToltecsEngine::readSaveHeader(in, header) == Toltecs::ToltecsEngine::kRSHENoError) {
_savegames.push_back(SavegameItem(slotNum, header.description));
//debug("%s -> %s", file->c_str(), header.description.c_str());
}
diff --git a/engines/toltecs/saveload.cpp b/engines/toltecs/saveload.cpp
index 409fc97076..1f2198fc35 100644
--- a/engines/toltecs/saveload.cpp
+++ b/engines/toltecs/saveload.cpp
@@ -41,7 +41,7 @@ namespace Toltecs {
#define TOLTECS_SAVEGAME_VERSION 4
-ToltecsEngine::kReadSaveHeaderError ToltecsEngine::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) {
+WARN_UNUSED_RESULT ToltecsEngine::kReadSaveHeaderError ToltecsEngine::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail) {
header.version = in->readUint32LE();
if (header.version > TOLTECS_SAVEGAME_VERSION)
@@ -52,10 +52,8 @@ ToltecsEngine::kReadSaveHeaderError ToltecsEngine::readSaveHeader(Common::Seekab
while (descriptionLen--)
header.description += (char)in->readByte();
- if (loadThumbnail) {
- header.thumbnail = Graphics::loadThumbnail(*in);
- } else {
- Graphics::skipThumbnail(*in);
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
+ return kRSHEIoError;
}
// Not used yet, reserved for future usage
@@ -147,7 +145,7 @@ void ToltecsEngine::loadgame(const char *filename) {
SaveHeader header;
- kReadSaveHeaderError errorCode = readSaveHeader(in, false, header);
+ kReadSaveHeaderError errorCode = readSaveHeader(in, header);
if (errorCode != kRSHENoError) {
warning("Error loading savegame '%s'", filename);
diff --git a/engines/toltecs/toltecs.h b/engines/toltecs/toltecs.h
index ece82f4a1a..1c9e9366c7 100644
--- a/engines/toltecs/toltecs.h
+++ b/engines/toltecs/toltecs.h
@@ -225,7 +225,7 @@ public:
const char *getSavegameFilename(int num);
static Common::String getSavegameFilename(const Common::String &target, int num);
- static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header);
+ WARN_UNUSED_RESULT static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail = true);
};
diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp
index 27145d7c4b..a59d14d5b6 100644
--- a/engines/tony/gfxcore.cpp
+++ b/engines/tony/gfxcore.cpp
@@ -912,7 +912,7 @@ void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPri
if (prim->isFlipped()) {
// Eliminate horizontal clipping
// width = m_dimx;
-// x1=prim->Dst().x1;
+// x1=prim->getDst()._x1;
// Clipping
u = _dimx - (width + u);
@@ -1699,7 +1699,7 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
}
//width = _dimx;
- //x1 = prim->Dst().x1;
+ //x1 = prim->getDst()._x1;
// Position into the destination buffer
buf = bigBuf;
@@ -1714,7 +1714,7 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
// Loop
buf += bigBuf.getDimx(); // Skip the first line
for (int y = 1; y < height - 1; y++) {
- // if (prim->IsFlipped())
+ // if (prim->isFlipped())
// mybuf=&buf[x1+m_dimx-1];
// else
mybuf = &buf[x1];
@@ -1748,7 +1748,7 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri
// Looppone
buf += bigBuf.getDimx();
for (int y = 1; y < height - 1; y++) {
- // if (prim->IsFlipped())
+ // if (prim->isFlipped())
// mybuf=&buf[x1+m_dimx-1];
// else
mybuf = &buf[x1];
diff --git a/engines/tony/loc.cpp b/engines/tony/loc.cpp
index be2b20294f..fe553b5fab 100644
--- a/engines/tony/loc.cpp
+++ b/engines/tony/loc.cpp
@@ -1005,7 +1005,7 @@ void RMCharacter::goTo(CORO_PARAM, RMPoint destcoord, bool bReversed) {
_walkCount = 0;
if (bReversed) {
- while (0) ;
+ while (0);
}
int nPatt = getCurPattern();
diff --git a/engines/tony/mpal/lzo.cpp b/engines/tony/mpal/lzo.cpp
index b9accb6c89..1bb54af1f0 100644
--- a/engines/tony/mpal/lzo.cpp
+++ b/engines/tony/mpal/lzo.cpp
@@ -94,9 +94,9 @@ int lzo1x_decompress(const byte *in, uint32 in_len, byte *out, uint32 *out_len)
if (t < 4)
goto match_next;
assert(t > 0);
- do
+ do {
*op++ = *ip++;
- while (--t > 0);
+ } while (--t > 0);
goto first_literal_run;
}
@@ -116,9 +116,9 @@ int lzo1x_decompress(const byte *in, uint32 in_len, byte *out, uint32 *out_len)
*op++ = *ip++;
*op++ = *ip++;
*op++ = *ip++;
- do
+ do {
*op++ = *ip++;
- while (--t > 0);
+ } while (--t > 0);
first_literal_run:
t = *ip++;
@@ -186,9 +186,9 @@ match:
copy_match:
*op++ = *m_pos++;
*op++ = *m_pos++;
- do
+ do {
*op++ = *m_pos++;
- while (--t > 0);
+ } while (--t > 0);
}
match_done:
diff --git a/engines/tony/sound.cpp b/engines/tony/sound.cpp
index fed51dacf4..07d15e71c9 100644
--- a/engines/tony/sound.cpp
+++ b/engines/tony/sound.cpp
@@ -412,11 +412,7 @@ void FPSfx::setPause(bool pause) {
*
*/
void FPSfx::setVolume(int volume) {
- if (volume > 63)
- volume = 63;
-
- if (volume < 0)
- volume = 0;
+ volume = CLIP(volume, 0, 63);
_lastVolume = volume;
diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp
index e93d676d87..634d286c7c 100644
--- a/engines/toon/detection.cpp
+++ b/engines/toon/detection.cpp
@@ -132,7 +132,7 @@ public:
_directoryGlobs = directoryGlobs;
}
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override {
return detectGameFilebased(allFiles, fslist, Toon::fileBasedFallback);
}
@@ -232,7 +232,11 @@ SaveStateDescriptor ToonMetaEngine::querySaveMetaInfos(const char *target, int s
SaveStateDescriptor desc(slot, saveName);
- Graphics::Surface *const thumbnail = Graphics::loadThumbnail(*file);
+ Graphics::Surface *thumbnail;
+ if (!Graphics::loadThumbnail(*file, thumbnail)) {
+ delete file;
+ return SaveStateDescriptor();
+ }
desc.setThumbnail(thumbnail);
uint32 saveDate = file->readUint32BE();
diff --git a/engines/toon/flux.cpp b/engines/toon/flux.cpp
index 14218ba4ef..65ad66ffd8 100644
--- a/engines/toon/flux.cpp
+++ b/engines/toon/flux.cpp
@@ -86,8 +86,7 @@ int32 CharacterFlux::fixFacingForAnimation(int32 originalFacing, int32 animation
}
v5 >>= 1;
v6 <<= 1;
- }
- while (!facingMask);
+ } while (!facingMask);
int32 finalFacing = 0;
for (finalFacing = 0; ; ++finalFacing) {
diff --git a/engines/toon/hotspot.cpp b/engines/toon/hotspot.cpp
index 04368df5ca..cdc6dc40d9 100644
--- a/engines/toon/hotspot.cpp
+++ b/engines/toon/hotspot.cpp
@@ -57,8 +57,8 @@ void Hotspots::save(Common::WriteStream *Stream) {
}
}
-int32 Hotspots::FindBasedOnCorner(int16 x, int16 y) {
- debugC(1, kDebugHotspot, "FindBasedOnCorner(%d, %d)", x, y);
+int32 Hotspots::findBasedOnCorner(int16 x, int16 y) {
+ debugC(1, kDebugHotspot, "findBasedOnCorner(%d, %d)", x, y);
for (int32 i = 0; i < _numItems; i++) {
if (x == _items[i].getX1()) {
@@ -73,8 +73,8 @@ int32 Hotspots::FindBasedOnCorner(int16 x, int16 y) {
return -1;
}
-int32 Hotspots::Find(int16 x, int16 y) {
- debugC(6, kDebugHotspot, "Find(%d, %d)", x, y);
+int32 Hotspots::find(int16 x, int16 y) {
+ debugC(6, kDebugHotspot, "find(%d, %d)", x, y);
int32 priority = -1;
int32 foundId = -1;
@@ -96,8 +96,8 @@ int32 Hotspots::Find(int16 x, int16 y) {
return foundId;
}
-bool Hotspots::LoadRif(const Common::String &rifName, const Common::String &additionalRifName) {
- debugC(1, kDebugHotspot, "LoadRif(%s, %s)", rifName.c_str(), additionalRifName.c_str());
+bool Hotspots::loadRif(const Common::String &rifName, const Common::String &additionalRifName) {
+ debugC(1, kDebugHotspot, "loadRif(%s, %s)", rifName.c_str(), additionalRifName.c_str());
uint32 size = 0;
uint8 *rifData = _vm->resources()->getFileData(rifName, &size);
@@ -139,8 +139,8 @@ bool Hotspots::LoadRif(const Common::String &rifName, const Common::String &addi
return true;
}
-HotspotData *Hotspots::Get(int32 id) {
- debugC(5, kDebugHotspot, "Get(%d)", id);
+HotspotData *Hotspots::get(int32 id) {
+ debugC(5, kDebugHotspot, "get(%d)", id);
if (id < 0 || id >= _numItems)
return 0;
diff --git a/engines/toon/hotspot.h b/engines/toon/hotspot.h
index 782d06a9fe..387007cbf6 100644
--- a/engines/toon/hotspot.h
+++ b/engines/toon/hotspot.h
@@ -50,10 +50,10 @@ public:
Hotspots(ToonEngine *vm);
~Hotspots();
- bool LoadRif(const Common::String &rifName, const Common::String &additionalRifName);
- int32 Find(int16 x, int16 y);
- int32 FindBasedOnCorner(int16 x, int16 y);
- HotspotData *Get(int32 id);
+ bool loadRif(const Common::String &rifName, const Common::String &additionalRifName);
+ int32 find(int16 x, int16 y);
+ int32 findBasedOnCorner(int16 x, int16 y);
+ HotspotData *get(int32 id);
int32 getCount() const { return _numItems; }
void load(Common::ReadStream *Stream);
diff --git a/engines/toon/script_func.cpp b/engines/toon/script_func.cpp
index 7a8925b766..d2a9de3c02 100644
--- a/engines/toon/script_func.cpp
+++ b/engines/toon/script_func.cpp
@@ -379,9 +379,9 @@ int32 ScriptFunc::sys_Cmd_Visited_Scene(EMCState *state) {
int32 ScriptFunc::sys_Cmd_Query_Rif_Flag(EMCState *state) {
- int32 hs = _vm->getHotspots()->FindBasedOnCorner(stackPos(0), stackPos(1));
+ int32 hs = _vm->getHotspots()->findBasedOnCorner(stackPos(0), stackPos(1));
if (hs >= 0)
- return _vm->getHotspots()->Get(hs)->getData(stackPos(2));
+ return _vm->getHotspots()->get(hs)->getData(stackPos(2));
return 0;
}
@@ -472,9 +472,9 @@ int32 ScriptFunc::sys_Cmd_Say_Lines(EMCState *state) {
}
int32 ScriptFunc::sys_Cmd_Set_Rif_Flag(EMCState *state) {
- int32 hs = _vm->getHotspots()->FindBasedOnCorner(stackPos(0), stackPos(1));
+ int32 hs = _vm->getHotspots()->findBasedOnCorner(stackPos(0), stackPos(1));
if (hs >= 0)
- _vm->getHotspots()->Get(hs)->setData(stackPos(2), stackPos(3));
+ _vm->getHotspots()->get(hs)->setData(stackPos(2), stackPos(3));
return 0;
}
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 05192ae65e..248057d539 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -1559,9 +1559,9 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
if (state()->_locations[SceneId]._flags & 0x40) {
Common::String cutaway = state()->_locations[SceneId]._cutaway;
- _hotspots->LoadRif(locationName + ".RIC", cutaway + ".RIC");
+ _hotspots->loadRif(locationName + ".RIC", cutaway + ".RIC");
} else {
- _hotspots->LoadRif(locationName + ".RIC", "");
+ _hotspots->loadRif(locationName + ".RIC", "");
}
restoreRifFlags(_gameState->_currentScene);
@@ -1837,10 +1837,10 @@ void ToonEngine::clickEvent() {
}
// find hotspot
- int32 hot = _hotspots->Find(mouseX + state()->_currentScrollValue , _mouseY);
+ int32 hot = _hotspots->find(mouseX + state()->_currentScrollValue , _mouseY);
HotspotData *currentHot = 0;
if (hot > -1) {
- currentHot = _hotspots->Get(hot);
+ currentHot = _hotspots->get(hot);
}
if (_currentHotspotItem == -3) {
@@ -2012,9 +2012,9 @@ void ToonEngine::selectHotspot() {
}
}
- int32 hot = _hotspots->Find(mouseX + state()->_currentScrollValue, _mouseY);
+ int32 hot = _hotspots->find(mouseX + state()->_currentScrollValue, _mouseY);
if (hot != -1) {
- HotspotData *hotspot = _hotspots->Get(hot);
+ HotspotData *hotspot = _hotspots->get(hot);
int32 item = hotspot->getData(14);
if (hotspot->getType() == 3)
item += 2000;
@@ -2271,8 +2271,8 @@ void ToonEngine::storeRifFlags(int32 location) {
}
for (int32 i = 0; i < _hotspots->getCount(); i++) {
- _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0] = _hotspots->Get(i)->getData(4);
- _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1] = _hotspots->Get(i)->getData(7);
+ _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0] = _hotspots->get(i)->getData(4);
+ _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1] = _hotspots->get(i)->getData(7);
}
}
@@ -2280,8 +2280,8 @@ void ToonEngine::restoreRifFlags(int32 location) {
if (_hotspots) {
if (!_gameState->_locations[location]._visited) {
for (int32 i = 0; i < _hotspots->getCount(); i++) {
- _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0] = _hotspots->Get(i)->getData(4);
- _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1] = _hotspots->Get(i)->getData(7);
+ _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0] = _hotspots->get(i)->getData(4);
+ _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1] = _hotspots->get(i)->getData(7);
}
_gameState->_locations[location]._numRifBoxes = _hotspots->getCount();
} else {
@@ -2289,8 +2289,8 @@ void ToonEngine::restoreRifFlags(int32 location) {
return;
for (int32 i = 0; i < _hotspots->getCount(); i++) {
- _hotspots->Get(i)->setData(4, _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0]);
- _hotspots->Get(i)->setData(7, _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1]);
+ _hotspots->get(i)->setData(4, _gameState->_locations[location]._rifBoxesFlags[i * 2 + 0]);
+ _hotspots->get(i)->setData(7, _gameState->_locations[location]._rifBoxesFlags[i * 2 + 1]);
}
}
}
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index dcb58ffae6..51b17b26d9 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -133,15 +133,8 @@ public:
_directoryGlobs = directoryGlobs;
}
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
- ADFilePropertiesMap filesProps;
-
- const ADGameDescription *matchedDesc = detectGameFilebased(allFiles, fslist, Touche::fileBasedFallback, &filesProps);
- if (!matchedDesc)
- return 0;
-
- reportUnknown(fslist.begin()->getParent(), filesProps);
- return matchedDesc;
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override {
+ return detectGameFilebased(allFiles, fslist, Touche::fileBasedFallback);
}
virtual const char *getName() const {
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index 15bcbbc0fc..4414ed1918 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -1370,7 +1370,8 @@ int ToucheEngine::getStringWidth(int num) const {
debug("stringwidth: %s", str);
debugN("raw:");
const char *p = str;
- while (*p) debugN(" %02X", (unsigned char)*p++);
+ while (*p)
+ debugN(" %02X", (unsigned char)*p++);
debugN("\n");
}
return Graphics::getStringWidth16(str);
diff --git a/engines/touche/touche.h b/engines/touche/touche.h
index c76532b302..be636738a8 100644
--- a/engines/touche/touche.h
+++ b/engines/touche/touche.h
@@ -330,6 +330,7 @@ enum {
kScreenHeight = 400,
kRoomHeight = 352,
kStartupEpisode = 90,
+ // TODO: If the following truncation is intentional (it probably is) it should be clearly marked as such
kCycleDelay = 1000 / (1193180 / 32768),
kIconWidth = 58,
kIconHeight = 42,
diff --git a/engines/tsage/blue_force/blueforce_scenes9.cpp b/engines/tsage/blue_force/blueforce_scenes9.cpp
index 5bcc44a2b9..28023cf363 100644
--- a/engines/tsage/blue_force/blueforce_scenes9.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes9.cpp
@@ -3165,7 +3165,7 @@ bool Scene930::Object4::startAction(CursorType action, Event &event) {
if (BF_GLOBALS._bookmark >= bFlashBackTwo) {
_lookLineNum = 71;
NamedObject::startAction(action, event);
- scene->ShowSoleInset();
+ scene->showSoleInset();
remove();
} else
NamedObject::startAction(action, event);
@@ -3304,7 +3304,7 @@ void Scene930::Action2::signal() {
SET_Y, GLOBALS._sceneManager._scene->_sceneBounds.top + UI_INTERFACE_Y + 2,
SET_FONT, 4, SET_BG_COLOR, 1, SET_FG_COLOR, 19, SET_EXT_BGCOLOR, 9,
SET_EXT_FGCOLOR, 13, LIST_END);
- scene->ShowBoxInset();
+ scene->showBoxInset();
BF_GLOBALS._player.enableControl();
remove();
break;
@@ -3460,7 +3460,7 @@ void Scene930::showBootInset() {
_bootsInset.setDetails(930, 69, 70, 93);
}
-void Scene930::ShowBoxInset() {
+void Scene930::showBoxInset() {
_boxInset.postInit();
_boxInset.setVisage(930);
_boxInset.setStrip(1);
@@ -3470,7 +3470,7 @@ void Scene930::ShowBoxInset() {
_boxInset.setDetails(930, 73, 74, 75);
}
-void Scene930::ShowSoleInset() {
+void Scene930::showSoleInset() {
_soleInset.postInit();
_soleInset.setVisage(930);
_soleInset.setStrip(3);
diff --git a/engines/tsage/blue_force/blueforce_scenes9.h b/engines/tsage/blue_force/blueforce_scenes9.h
index 52935debd4..eb6f481edc 100644
--- a/engines/tsage/blue_force/blueforce_scenes9.h
+++ b/engines/tsage/blue_force/blueforce_scenes9.h
@@ -380,8 +380,8 @@ class Scene930: public PalettedScene {
};
void showBootInset();
- void ShowBoxInset();
- void ShowSoleInset();
+ void showBoxInset();
+ void showSoleInset();
public:
SequenceManager _sequenceManager1;
Object1 _box;
diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp
index e476391f71..5d31cca75e 100644
--- a/engines/tsage/detection.cpp
+++ b/engines/tsage/detection.cpp
@@ -131,9 +131,6 @@ public:
if (in) {
if (TsAGE::Saver::readSavegameHeader(in, header)) {
saveList.push_back(SaveStateDescriptor(slot, header._saveName));
-
- header._thumbnail->free();
- delete header._thumbnail;
}
delete in;
@@ -161,7 +158,11 @@ public:
if (f) {
TsAGE::tSageSavegameHeader header;
- TsAGE::Saver::readSavegameHeader(f, header);
+ if (!TsAGE::Saver::readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
+
delete f;
// Create the return descriptor
diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp
index 03f615db21..81bb973d02 100644
--- a/engines/tsage/saveload.cpp
+++ b/engines/tsage/saveload.cpp
@@ -189,10 +189,10 @@ Common::Error Saver::restore(int slot) {
// Read in the savegame header
tSageSavegameHeader header;
- readSavegameHeader(saveFile, header);
- if (header._thumbnail)
- header._thumbnail->free();
- delete header._thumbnail;
+ if (!readSavegameHeader(saveFile, header)) {
+ delete saveFile;
+ return Common::kReadingFailed;
+ }
serializer.setSaveVersion(header._version);
@@ -247,9 +247,8 @@ Common::Error Saver::restore(int slot) {
const char *SAVEGAME_STR = "SCUMMVM_TSAGE";
#define SAVEGAME_STR_SIZE 13
-bool Saver::readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &header) {
+WARN_UNUSED_RESULT bool Saver::readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
- header._thumbnail = NULL;
// Validate the header Id
in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
@@ -266,9 +265,9 @@ bool Saver::readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &head
while ((ch = (char)in->readByte()) != '\0') header._saveName += ch;
// Get the thumbnail
- header._thumbnail = Graphics::loadThumbnail(*in);
- if (!header._thumbnail)
+ if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
header._saveYear = in->readSint16LE();
diff --git a/engines/tsage/saveload.h b/engines/tsage/saveload.h
index 04a1e02b28..3de34489fd 100644
--- a/engines/tsage/saveload.h
+++ b/engines/tsage/saveload.h
@@ -221,7 +221,7 @@ public:
Common::Error save(int slot, const Common::String &saveName);
Common::Error restore(int slot);
- static bool readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, tSageSavegameHeader &header, bool skipThumbnail = true);
static void writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &header);
void addListener(SaveListener *obj);
diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp
index 7d07edabd3..2318947b12 100644
--- a/engines/tucker/detection.cpp
+++ b/engines/tucker/detection.cpp
@@ -149,18 +149,19 @@ public:
return desc != 0;
}
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ virtual ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override {
for (Common::FSList::const_iterator d = fslist.begin(); d != fslist.end(); ++d) {
Common::FSList audiofslist;
if (d->isDirectory() && d->getName().equalsIgnoreCase("audio") && d->getChildren(audiofslist, Common::FSNode::kListFilesOnly)) {
for (Common::FSList::const_iterator f = audiofslist.begin(); f != audiofslist.end(); ++f) {
if (!f->isDirectory() && f->getName().equalsIgnoreCase("demorolc.raw")) {
- return &tuckerDemoGameDescription;
+ return ADDetectedGame(&tuckerDemoGameDescription);
}
}
}
}
- return 0;
+
+ return ADDetectedGame();
}
virtual SaveStateList listSaves(const char *target) const {
@@ -175,7 +176,7 @@ public:
if (ext && (slot = atoi(ext + 1)) >= 0 && slot <= Tucker::kLastSaveSlot) {
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
- if (Tucker::TuckerEngine::readSavegameHeader(in, header, false) == Tucker::TuckerEngine::kSavegameNoError) {
+ if (Tucker::TuckerEngine::readSavegameHeader(in, header) == Tucker::TuckerEngine::kSavegameNoError) {
saveList.push_back(SaveStateDescriptor(slot, header.description));
}
@@ -207,7 +208,7 @@ public:
}
Tucker::TuckerEngine::SavegameHeader header;
- Tucker::TuckerEngine::SavegameError savegameError = Tucker::TuckerEngine::readSavegameHeader(file, header, true);
+ Tucker::TuckerEngine::SavegameError savegameError = Tucker::TuckerEngine::readSavegameHeader(file, header, false);
if (savegameError) {
delete file;
return SaveStateDescriptor();
diff --git a/engines/tucker/locations.cpp b/engines/tucker/locations.cpp
index 28fca114b0..d78eacc55d 100644
--- a/engines/tucker/locations.cpp
+++ b/engines/tucker/locations.cpp
@@ -217,7 +217,7 @@ void TuckerEngine::execData3PreUpdate_locationNum2Helper() {
return;
}
int start, end;
- if (_locationNum == 2) {
+ if (_location == kLocationBackAlley) {
start = 116;
end = 125;
} else {
@@ -2050,8 +2050,8 @@ void TuckerEngine::execData3PreUpdate_locationNum41() {
if (_panelLockedFlag && _yPosCurrent > 130 && _selectedObject._yPos > 135 && _nextAction == 0 && _flagsTable[223] == 0) {
_panelLockedFlag = false;
_csDataLoaded = false;
- _nextLocationNum = 0;
- _selectedObject._locationObjectLocationNum = 0;
+ _nextLocation = kLocationNone;
+ _selectedObject._locationObjectLocation = kLocationNone;
_locationMaskType = 0;
_nextAction = _flagsTable[163] + 32;
++_flagsTable[163];
@@ -2084,7 +2084,7 @@ void TuckerEngine::updateSprite_locationNum42(int i) {
} else if (_flagsTable[223] == 3) {
state = 5;
_spritesTable[i]._updateDelay = 5;
- _spritesTable[i]._state = _spritesTable[i]._firstFrame - 1; // FIXME: bug, fxNum ?
+ _spritesTable[i]._state = _spritesTable[i]._firstFrame - 1;
_updateSpriteFlag1 = true;
} else {
state = 2;
@@ -2482,7 +2482,7 @@ void TuckerEngine::updateSprite_locationNum58(int i) {
void TuckerEngine::execData3PreUpdate_locationNum58() {
// workaround original game glitch #2872348: do not change position on location change
- if (_nextLocationNum == 0 && _flagsTable[190] < 3 && _xPosCurrent > 310) {
+ if (_nextLocation == kLocationNone && _flagsTable[190] < 3 && _xPosCurrent > 310) {
_xPosCurrent = 310;
_panelLockedFlag = false;
}
@@ -2893,13 +2893,25 @@ void TuckerEngine::updateSprite_locationNum66_4(int i) {
}
void TuckerEngine::execData3PreUpdate_locationNum66() {
- // FIXME: shouldn't be executed after using the map
+ // WORKAROUND
+ // If you don't have the appointment card yet and use the map to go to
+ // Seedy Street Bud ends up being teleported back to the mall.
+ // Because of the destination coordinates which warp Bud past x==583 the
+ // below 'if' triggers and automatically makes Violet refuse Bud entrance
+ // to the dentist. On top of that the graphics end up all garbled which
+ // indicates that even worse things happen under the hood.
+ // To work around this we only trigger Violet if Bud actually _walked_ past
+ // the trigger coordinates (as opposed to using the map).
+ // Fixes Trac#10452.
+ if (_nextLocation != kLocationNone)
+ return;
+
_flagsTable[137] = 0;
if (_xPosCurrent > 583 && _flagsTable[191] == 0 && _nextAction == 0 && _locationMaskType == 0) {
_panelLockedFlag = false;
_csDataLoaded = false;
- _nextLocationNum = 0;
- _selectedObject._locationObjectLocationNum = 0;
+ _nextLocation = kLocationNone;
+ _selectedObject._locationObjectLocation = kLocationNone;
if (_flagsTable[131] == 0) {
_nextAction = 13;
} else if (_flagsTable[130] == 0) {
diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp
index 0ea24adf2d..5d7ae2c2d5 100644
--- a/engines/tucker/resource.cpp
+++ b/engines/tucker/resource.cpp
@@ -491,36 +491,36 @@ void TuckerEngine::loadCTable02() {
void TuckerEngine::loadLoc() {
Common::String filename;
- int i = _locationWidthTable[_locationNum];
- _locationHeight = (_locationNum < 73) ? 140 : 200;
- filename = Common::String::format((i == 1) ? "loc%02d.pcx" : "loc%02da.pcx", _locationNum);
+ int i = _locationWidthTable[_location];
+ _locationHeight = (_location < kLocationJesusCutscene1) ? 140 : 200;
+ filename = Common::String::format((i == 1) ? "loc%02d.pcx" : "loc%02da.pcx", _location);
copyLocBitmap(filename.c_str(), 0, false);
Graphics::copyRect(_quadBackgroundGfxBuf, 320, _locationBackgroundGfxBuf, 640, 320, _locationHeight);
if (_locationHeight == 200) {
return;
}
- filename = Common::String::format((i != 2) ? "path%02d.pcx" : "path%02da.pcx", _locationNum);
+ filename = Common::String::format((i != 2) ? "path%02d.pcx" : "path%02da.pcx", _location);
copyLocBitmap(filename.c_str(), 0, true);
if (i > 1) {
- filename = Common::String::format("loc%02db.pcx", _locationNum);
+ filename = Common::String::format("loc%02db.pcx", _location);
copyLocBitmap(filename.c_str(), 320, false);
Graphics::copyRect(_quadBackgroundGfxBuf + 44800, 320, _locationBackgroundGfxBuf + 320, 640, 320, _locationHeight);
if (i == 2) {
- filename = Common::String::format("path%02db.pcx", _locationNum);
+ filename = Common::String::format("path%02db.pcx", _location);
copyLocBitmap(filename.c_str(), 320, true);
}
}
if (i > 2) {
- filename = Common::String::format("loc%02dc.pcx", _locationNum);
+ filename = Common::String::format("loc%02dc.pcx", _location);
copyLocBitmap(filename.c_str(), 0, false);
Graphics::copyRect(_quadBackgroundGfxBuf + 89600, 320, _locationBackgroundGfxBuf, 640, 320, 140);
}
- if (_locationNum == 1) {
+ if (_location == kLocationHotelRoom) {
_loadLocBufPtr = _quadBackgroundGfxBuf + 89600;
loadImage("rochpath.pcx", _loadLocBufPtr, 0);
}
if (i > 3) {
- filename = Common::String::format("loc%02dd.pcx", _locationNum);
+ filename = Common::String::format("loc%02dd.pcx", _location);
copyLocBitmap(filename.c_str(), 0, false);
Graphics::copyRect(_quadBackgroundGfxBuf + 134400, 320, _locationBackgroundGfxBuf + 320, 640, 320, 140);
}
@@ -528,13 +528,15 @@ void TuckerEngine::loadLoc() {
}
void TuckerEngine::loadObj() {
- if (_locationNum == 99) {
+ if (_location == kLocationMap) {
return;
}
- if (_locationNum < 24) {
+ if (_location <= kLocationWarehouseCutscene) {
_part = kPartOne;
_speechSoundBaseNum = 2639;
- } else if (_locationNum < 41 || (_locationNum > 69 && _locationNum < 73) || (_locationNum > 78 && _locationNum < 83)) {
+ } else if (( _location <= kLocationFarDocks)
+ || (_location >= kLocationComputerScreen && _location <= kLocationSeedyStreetCutscene)
+ || (_location >= kLocationElvisCutscene && _location <= kLocationJesusCutscene2)) {
_part = kPartTwo;
_speechSoundBaseNum = 2679;
} else {
@@ -544,7 +546,7 @@ void TuckerEngine::loadObj() {
if (_part == _currentPart) {
return;
}
- debug(2, "loadObj() part %d locationNum %d", _part, _locationNum);
+ debug(2, "loadObj() part %d location %d", _part, _location);
// If a savegame is loaded from the launcher, skip the display chapter
if (_startSlot != -1)
_startSlot = -1;
@@ -631,7 +633,7 @@ void TuckerEngine::loadData3() {
loadFile("data3.c", _loadTempBuf);
DataTokenizer t(_loadTempBuf, _fileLoadSize);
_locationAnimationsCount = 0;
- if (t.findIndex(_locationNum)) {
+ if (t.findIndex(_location)) {
while (t.findNextToken(kDataTokenDw)) {
int num = t.getNextInteger();
if (num < 0) {
@@ -678,7 +680,7 @@ void TuckerEngine::loadData4() {
_displayGameHints = t.getNextInteger() != 0;
}
_locationObjectsCount = 0;
- if (t.findIndex(_locationNum)) {
+ if (t.findIndex(_location)) {
while (t.findNextToken(kDataTokenDw)) {
int i = t.getNextInteger();
if (i < 0)
@@ -694,8 +696,8 @@ void TuckerEngine::loadData4() {
d->_standY = t.getNextInteger();
d->_textNum = t.getNextInteger();
d->_cursorStyle = (CursorStyle)t.getNextInteger();
- d->_locationNum = t.getNextInteger();
- if (d->_locationNum > 0) {
+ d->_location = (Location)t.getNextInteger();
+ if (d->_location != kLocationNone) {
d->_toX = t.getNextInteger();
d->_toY = t.getNextInteger();
d->_toX2 = t.getNextInteger();
@@ -708,29 +710,19 @@ void TuckerEngine::loadData4() {
}
void TuckerEngine::loadActionFile() {
- char filename[40];
- if ((_gameFlags & kGameFlagDemo) != 0) {
- strcpy(filename, "action.c");
+ assert(_part != kPartInit);
+
+ Common::String filename;
+ if (_gameFlags & kGameFlagDemo) {
+ filename = "action.c";
} else {
- switch (_part) {
- case kPartOne:
- strcpy(filename, "action1.c");
- break;
- case kPartTwo:
- strcpy(filename, "action2.c");
- break;
- case kPartThree:
- strcpy(filename, "action3.c");
- break;
- default:
- break;
- }
+ filename = Common::String::format("action%d.c", _part);
}
- loadFile(filename, _loadTempBuf);
+ loadFile(filename.c_str(), _loadTempBuf);
DataTokenizer t(_loadTempBuf, _fileLoadSize);
_actionsCount = 0;
- if (t.findIndex(_locationNum)) {
+ if (t.findIndex(_location)) {
while (t.findNextToken(kDataTokenDw)) {
int keyA = t.getNextInteger();
if (keyA < 0) {
@@ -763,7 +755,7 @@ void TuckerEngine::loadCharPos() {
loadFile("charpos.c", _loadTempBuf);
DataTokenizer t(_loadTempBuf, _fileLoadSize);
_charPosCount = 0;
- if (t.findIndex(_locationNum)) {
+ if (t.findIndex(_location)) {
while (t.findNextToken(kDataTokenDw)) {
const int i = t.getNextInteger();
if (i < 0) {
@@ -823,9 +815,9 @@ void TuckerEngine::loadCharPos() {
void TuckerEngine::loadSprA02_01() {
unloadSprA02_01();
- const int count = _sprA02LookupTable[_locationNum];
+ const int count = _sprA02LookupTable[_location];
for (int i = 1; i < count + 1; ++i) {
- Common::String filename = Common::String::format("sprites/a%02d_%02d.spr", _locationNum, i);
+ Common::String filename = Common::String::format("sprites/a%02d_%02d.spr", _location, i);
_sprA02Table[i] = loadFile(filename.c_str(), 0);
}
_sprA02Table[0] = _sprA02Table[1];
@@ -841,13 +833,13 @@ void TuckerEngine::unloadSprA02_01() {
void TuckerEngine::loadSprC02_01() {
unloadSprC02_01();
- const int count = _sprC02LookupTable[_locationNum];
+ const int count = _sprC02LookupTable[_location];
for (int i = 1; i < count + 1; ++i) {
- Common::String filename = Common::String::format("sprites/c%02d_%02d.spr", _locationNum, i);
+ Common::String filename = Common::String::format("sprites/c%02d_%02d.spr", _location, i);
_sprC02Table[i] = loadFile(filename.c_str(), 0);
}
_sprC02Table[0] = _sprC02Table[1];
- _spritesCount = _sprC02LookupTable2[_locationNum];
+ _spritesCount = _sprC02LookupTable2[_location];
for (int i = 0; i < kMaxCharacters; ++i) {
memset(&_spritesTable[i], 0, sizeof(Sprite));
_spritesTable[i]._state = -1;
@@ -866,7 +858,7 @@ void TuckerEngine::unloadSprC02_01() {
void TuckerEngine::loadFx() {
loadFile("fx.c", _loadTempBuf);
DataTokenizer t(_loadTempBuf, _fileLoadSize);
- if (t.findIndex(_locationNum)) {
+ if (t.findIndex(_location)) {
t.findNextToken(kDataTokenDw);
_locationSoundsCount = t.getNextInteger();
_currentFxSet = 0;
@@ -937,7 +929,7 @@ void TuckerEngine::loadFx() {
}
}
} else {
- error("loadFx() - Index not found for location %d", _locationNum);
+ error("loadFx() - Index not found for location %d", _location);
}
}
@@ -993,7 +985,7 @@ void TuckerEngine::loadActionsTable() {
do {
if (!_csDataLoaded) {
DataTokenizer t(_csDataBuf, _csDataSize);
- bool found = t.findIndex(_locationNum);
+ bool found = t.findIndex(_location);
assert(found);
for (int i = 0; i < _nextAction; ++i) {
found = t.findNextToken(kDataTokenDw);
diff --git a/engines/tucker/saveload.cpp b/engines/tucker/saveload.cpp
index 4e33988ed2..00911b9c44 100644
--- a/engines/tucker/saveload.cpp
+++ b/engines/tucker/saveload.cpp
@@ -50,36 +50,44 @@ Common::String generateGameStateFileName(const char *target, int slot, bool pref
return name;
}
-static void saveOrLoadInt(Common::WriteStream &stream, int &i) {
+static void saveOrLoadVar(Common::WriteStream &stream, int &i) {
stream.writeSint32LE(i);
}
-static void saveOrLoadInt(Common::ReadStream &stream, int &i) {
+static void saveOrLoadVar(Common::ReadStream &stream, int &i) {
i = stream.readSint32LE();
}
+static void saveOrLoadVar(Common::WriteStream &stream, Location &location) {
+ stream.writeSint32LE((int)location);
+}
+
+static void saveOrLoadVar(Common::ReadStream &stream, Location &location) {
+ location = (Location)stream.readSint32LE();
+}
+
template<class S>
TuckerEngine::SavegameError TuckerEngine::saveOrLoadGameStateData(S &s) {
for (int i = 0; i < kFlagsTableSize; ++i) {
- saveOrLoadInt(s, _flagsTable[i]);
+ saveOrLoadVar(s, _flagsTable[i]);
}
for (int i = 0; i < 40; ++i) {
- saveOrLoadInt(s, _inventoryObjectsList[i]);
+ saveOrLoadVar(s, _inventoryObjectsList[i]);
}
for (int i = 0; i < 50; ++i) {
- saveOrLoadInt(s, _inventoryItemsState[i]);
+ saveOrLoadVar(s, _inventoryItemsState[i]);
}
for (int i = 0; i < 50; ++i) {
- saveOrLoadInt(s, _panelObjectsOffsetTable[i]);
+ saveOrLoadVar(s, _panelObjectsOffsetTable[i]);
}
- saveOrLoadInt(s, _mainSpritesBaseOffset);
- saveOrLoadInt(s, _selectedObject._xPos);
- saveOrLoadInt(s, _selectedObject._yPos);
- saveOrLoadInt(s, _locationNum);
- saveOrLoadInt(s, _xPosCurrent);
- saveOrLoadInt(s, _yPosCurrent);
- saveOrLoadInt(s, _inventoryObjectsCount);
- saveOrLoadInt(s, _inventoryObjectsOffset);
+ saveOrLoadVar(s, _mainSpritesBaseOffset);
+ saveOrLoadVar(s, _selectedObject._xPos);
+ saveOrLoadVar(s, _selectedObject._yPos);
+ saveOrLoadVar(s, _location);
+ saveOrLoadVar(s, _xPosCurrent);
+ saveOrLoadVar(s, _yPosCurrent);
+ saveOrLoadVar(s, _inventoryObjectsCount);
+ saveOrLoadVar(s, _inventoryObjectsOffset);
return s.err() ? kSavegameIoError : kSavegameNoError;
}
@@ -101,18 +109,18 @@ Common::Error TuckerEngine::loadGameState(int slot) {
if (savegameError) {
switch (savegameError) {
- case kSavegameInvalidTypeError:
- warning("Invalid savegame '%s' (does not look like a ScummVM Tucker-engine savegame)", fileName.c_str());
- break;
-
- case kSavegameInvalidVersionError:
- warning("Invalid savegame '%s' (expected savegame version v%i-v%i, got v%i)",
- fileName.c_str(), kSavegameVersionMinimum, kSavegameVersionCurrent, header.version);
- break;
-
- default:
- warning("Failed to load savegame '%s'", fileName.c_str());
- break;
+ case kSavegameInvalidTypeError:
+ warning("Invalid savegame '%s' (does not look like a ScummVM Tucker-engine savegame)", fileName.c_str());
+ break;
+
+ case kSavegameInvalidVersionError:
+ warning("Invalid savegame '%s' (expected savegame version v%i-v%i, got v%i)",
+ fileName.c_str(), kSavegameVersionMinimum, kSavegameVersionCurrent, header.version);
+ break;
+
+ default:
+ warning("Failed to load savegame '%s'", fileName.c_str());
+ break;
}
delete file;
@@ -121,17 +129,19 @@ Common::Error TuckerEngine::loadGameState(int slot) {
g_engine->setTotalPlayTime(header.playTime * 1000);
- _nextLocationNum = _locationNum;
+ _nextLocation = _location;
setBlackPalette();
loadBudSpr();
_forceRedrawPanelItems = true;
+ _panelType = kPanelTypeNormal;
+ setCursorState(kCursorStateNormal);
delete file;
return Common::kNoError;
}
-TuckerEngine::SavegameError TuckerEngine::readSavegameHeader(const char *target, int slot, SavegameHeader &header) {
+WARN_UNUSED_RESULT TuckerEngine::SavegameError TuckerEngine::readSavegameHeader(const char *target, int slot, SavegameHeader &header) {
Common::String fileName = generateGameStateFileName(target, slot);
Common::InSaveFile *file = g_system->getSavefileManager()->openForLoading(fileName);
@@ -145,8 +155,8 @@ TuckerEngine::SavegameError TuckerEngine::readSavegameHeader(const char *target,
return savegameError;
}
-TuckerEngine::SavegameError TuckerEngine::readSavegameHeader(Common::InSaveFile *file, SavegameHeader &header, bool loadThumbnail) {
- header.version = -1;
+WARN_UNUSED_RESULT TuckerEngine::SavegameError TuckerEngine::readSavegameHeader(Common::InSaveFile *file, SavegameHeader &header, bool skipThumbnail) {
+ header.version = 0;
header.flags = 0;
header.description.clear();
header.saveDate = 0;
@@ -186,10 +196,8 @@ TuckerEngine::SavegameError TuckerEngine::readSavegameHeader(Common::InSaveFile
header.saveTime = file->readUint32LE();
header.playTime = file->readUint32LE();
- if (loadThumbnail) {
- header.thumbnail = Graphics::loadThumbnail(*file);
- } else {
- Graphics::skipThumbnail(*file);
+ if (!Graphics::loadThumbnail(*file, header.thumbnail, skipThumbnail)) {
+ return kSavegameIoError;
}
}
@@ -278,13 +286,19 @@ bool TuckerEngine::isAutosaveAllowed(const char *target) {
void TuckerEngine::writeAutosave() {
if (canSaveGameStateCurrently()) {
+ // unconditionally reset last autosave timestamp so we don't start
+ // hammering the disk in case we can't/don't actually write the file
+ _lastSaveTime = _system->getMillis();
+
if (!isAutosaveAllowed()) {
warning("Refusing to overwrite non-autosave savegame in slot %i, skipping autosave", kAutoSaveSlot);
return;
}
- writeSavegame(kAutoSaveSlot, "Autosave", true);
- _lastSaveTime = _system->getMillis();
+ if (writeSavegame(kAutoSaveSlot, "Autosave", true).getCode() != Common::kNoError) {
+ warning("Can't create autosave in slot %i, game not saved", kAutoSaveSlot);
+ return;
+ }
}
}
diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp
index cefb9e90e1..fd66c4f49c 100644
--- a/engines/tucker/sequences.cpp
+++ b/engines/tucker/sequences.cpp
@@ -50,13 +50,13 @@ void TuckerEngine::handleCreditsSequence() {
int counter3 = 0;
int num = 0;
int imgNum = 0;
- int prevLocationNum = _locationNum;
+ Location prevLocation = _location;
int counter2 = 0;
int counter1 = 0;
loadCharset2();
showCursor(false);
stopSounds();
- _locationNum = 74;
+ _location = kLocationCredits;
_flagsTable[236] = 74;
uint8 *imgBuf = (uint8 *)malloc(16 * 64000);
loadSprC02_01();
@@ -151,7 +151,7 @@ void TuckerEngine::handleCreditsSequence() {
}
} while (!_quitGame && isSpeechSoundPlaying());
free(imgBuf);
- _locationNum = prevLocationNum;
+ _location = prevLocation;
do {
if (_fadePaletteCounter > 0) {
fadeInPalette();
@@ -185,7 +185,9 @@ void TuckerEngine::handleCongratulationsSequence() {
}
void TuckerEngine::handleNewPartSequence() {
- char filename[40];
+ assert(_part != kPartInit);
+
+ Common::String filename;
showCursor(false);
stopSounds();
@@ -204,40 +206,29 @@ void TuckerEngine::handleNewPartSequence() {
_redrawPanelItemsCounter = 0;
}
_scrollOffset = 0;
- switch (_part) {
- case kPartOne:
- strcpy(filename, "pt1bak.pcx");
- break;
- case kPartTwo:
- strcpy(filename, "pt2bak.pcx");
- break;
- case kPartThree:
- strcpy(filename, "pt3bak.pcx");
- break;
- default:
- break;
- }
- loadImage(filename, _quadBackgroundGfxBuf, 1);
+
+ filename = Common::String::format("pt%dbak.pcx", _part);
+ loadImage(filename.c_str(), _quadBackgroundGfxBuf, 1);
_spritesCount = 1;
clearSprites();
- int currentLocation = _locationNum;
- _locationNum = 98;
+ Location currentLocation = _location;
+ _location = kLocationNewPart;
unloadSprA02_01();
unloadSprC02_01();
switch (_part) {
- case kPartOne:
- strcpy(filename, "sprites/partone.spr");
- break;
- case kPartTwo:
- strcpy(filename, "sprites/parttwo.spr");
- break;
- case kPartThree:
- strcpy(filename, "sprites/partthr.spr");
- break;
- default:
- break;
+ case kPartOne:
+ filename = "sprites/partone.spr";
+ break;
+ case kPartTwo:
+ filename = "sprites/parttwo.spr";
+ break;
+ case kPartThree:
+ filename = "sprites/partthr.spr";
+ break;
+ default:
+ break;
}
- _sprC02Table[1] = loadFile(filename, 0);
+ _sprC02Table[1] = loadFile(filename.c_str(), 0);
startSpeechSound(9000, 60);
_fadePaletteCounter = 0;
do {
@@ -269,31 +260,21 @@ void TuckerEngine::handleNewPartSequence() {
redrawScreen(0);
waitForTimer(3);
} while (_fadePaletteCounter > 0 && !_quitGame);
- _locationNum = currentLocation;
+ _location = currentLocation;
showCursor(true);
}
void TuckerEngine::handleMeanwhileSequence() {
- char filename[40];
+ assert(_part != kPartInit);
+
+ Common::String filename;
uint8 backupPalette[256 * 3];
memcpy(backupPalette, _currentPalette, 256 * 3);
- switch (_part) {
- case kPartOne:
- strcpy(filename, "meanw01.pcx");
- break;
- case kPartTwo:
- strcpy(filename, "meanw02.pcx");
- break;
- case kPartThree:
- strcpy(filename, "meanw03.pcx");
- break;
- default:
- break;
- }
+ filename = Common::String::format("meanw%02d.pcx", _part);
if (_flagsTable[215] == 0 && _flagsTable[231] == 1) {
- strcpy(filename, "loc80.pcx");
+ filename = "loc80.pcx";
}
- loadImage(filename, _quadBackgroundGfxBuf + 89600, 1);
+ loadImage(filename.c_str(), _quadBackgroundGfxBuf + 89600, 1);
showCursor(false);
_fadePaletteCounter = 0;
for (int i = 0; i < 60 && !_quitGame; ++i) {
@@ -328,7 +309,7 @@ void TuckerEngine::handleMeanwhileSequence() {
void TuckerEngine::handleMapSequence() {
loadImage("map2.pcx", _quadBackgroundGfxBuf + 89600, 0);
loadImage("map1.pcx", _loadTempBuf, 1);
- _selectedObject._locationObjectLocationNum = 0;
+ _selectedObject._locationObjectLocation = kLocationNone;
if (_flagsTable[7] > 0) {
copyMapRect(0, 0, 140, 86);
}
@@ -345,53 +326,54 @@ void TuckerEngine::handleMapSequence() {
copyMapRect(220, 0, 100, 180);
}
_fadePaletteCounter = 0;
- int xPos = 0, yPos = 0, textNum = 0;
+ int xPos = 0, yPos = 0;
while (!_quitGame) {
+ int textNum = 0;
waitForTimer(2);
updateMouseState();
Graphics::copyRect(_locationBackgroundGfxBuf + _scrollOffset, 640, _quadBackgroundGfxBuf + 89600, 320, 320, 200);
_fullRedraw = true;
if (_flagsTable[7] > 0 && _mousePosX > 30 && _mousePosX < 86 && _mousePosY > 36 && _mousePosY < 86) {
textNum = 13;
- _nextLocationNum = (_part == kPartOne) ? 3 : 65;
+ _nextLocation = (_part == kPartOne) ? kLocationSeedyStreet : kLocationSeedyStreetPartThree;
xPos = 620;
yPos = 130;
} else if (_flagsTable[7] > 1 && _mousePosX > 60 && _mousePosX < 120 && _mousePosY > 120 && _mousePosY < 170) {
textNum = 14;
- _nextLocationNum = (_part == kPartOne) ? 9 : 66;
+ _nextLocation = (_part == kPartOne) ? kLocationMall : kLocationMallPartThree;
xPos = 344;
yPos = 120;
} else if (_flagsTable[7] > 2 && _mousePosX > 160 && _mousePosX < 210 && _mousePosY > 110 && _mousePosY < 160) {
textNum = 15;
- _nextLocationNum = (_part == kPartOne) ? 16 : 61;
+ _nextLocation = (_part == kPartOne) ? kLocationPark : kLocationParkPartThree;
xPos = 590;
yPos = 130;
} else if ((_flagsTable[7] == 4 || _flagsTable[7] == 6) && _mousePosX > 150 && _mousePosX < 200 && _mousePosY > 20 && _mousePosY < 70) {
textNum = 16;
- _nextLocationNum = (_part == kPartOne) ? 20 : 68;
+ _nextLocation = (_part == kPartOne) ? kLocationOutsideMuseum : kLocationOutsideMuseumPartThree;
xPos = 20;
yPos = 130;
} else if (_flagsTable[120] == 1 && _mousePosX > 240 && _mousePosX < 290 && _mousePosY > 35 && _mousePosY < 90) {
textNum = 17;
- _nextLocationNum = (_part == kPartOne) ? 19 : 62;
+ _nextLocation = (_part == kPartOne) ? kLocationDocks : kLocationDocksPartThree;
xPos = 20;
yPos = 124;
} else if (_mousePosX > 135 && _mousePosX < 185 && _mousePosY > 170 && _mousePosY < 200) {
textNum = 18;
- _nextLocationNum = _locationNum;
+ _nextLocation = _location;
if (!_noPositionChangeAfterMap) {
xPos = _xPosCurrent;
yPos = _yPosCurrent;
- } else if (_locationNum == 3 || _locationNum == 65) {
+ } else if (_location == kLocationSeedyStreet || _location == kLocationSeedyStreetPartThree) {
xPos = 620;
yPos = 130;
- } else if (_locationNum == 9 || _locationNum == 66) {
+ } else if (_location == kLocationMall || _location == kLocationMallPartThree) {
xPos = 344;
yPos = 120;
- } else if (_locationNum == 16 || _locationNum == 61) {
+ } else if (_location == kLocationPark || _location == kLocationParkPartThree) {
xPos = 590;
yPos = 130;
- } else if (_locationNum == 20 || _locationNum == 68) {
+ } else if (_location == kLocationOutsideMuseum || _location == kLocationOutsideMuseumPartThree) {
xPos = 20;
yPos = 130;
} else {
@@ -417,11 +399,11 @@ void TuckerEngine::handleMapSequence() {
--_fadePaletteCounter;
}
_mouseClick = 1;
- if (_nextLocationNum == 9 && _noPositionChangeAfterMap) {
+ if (_nextLocation == kLocationMall && _noPositionChangeAfterMap) {
_backgroundSpriteCurrentAnimation = 2;
_backgroundSpriteCurrentFrame = 0;
setCursorState(kCursorStateDisabledHidden);
- } else if (_nextLocationNum == 66 && _noPositionChangeAfterMap) {
+ } else if (_nextLocation == kLocationMallPartThree && _noPositionChangeAfterMap) {
_backgroundSpriteCurrentAnimation = 1;
_backgroundSpriteCurrentFrame = 0;
setCursorState(kCursorStateDisabledHidden);
@@ -442,21 +424,21 @@ void TuckerEngine::copyMapRect(int x, int y, int w, int h) {
}
bool TuckerEngine::handleSpecialObjectSelectionSequence() {
- char filename[40];
+ Common::String filename;
if (_part == kPartOne && _selectedObjectNum == 6) {
- strcpy(filename, "news1.pcx");
+ filename = "news1.pcx";
_flagsTable[7] = 4;
} else if (_part == kPartThree && _selectedObjectNum == 45) {
- strcpy(filename, "profnote.pcx");
+ filename = "profnote.pcx";
} else if (_part == kPartOne && _selectedObjectNum == 26) {
- strcpy(filename, "photo.pcx");
+ filename = "photo.pcx";
} else if (_part == kPartThree && _selectedObjectNum == 39) {
- strcpy(filename, "news2.pcx");
+ filename = "news2.pcx";
_flagsTable[135] = 1;
} else if (_currentInfoString1SourceType == 0 && _currentActionObj1Num == 259) {
- strcpy(filename, "postit.pcx");
+ filename = "postit.pcx";
} else if (_currentInfoString1SourceType == 1 && _currentActionObj1Num == 91) {
- strcpy(filename, "memo.pcx");
+ filename = "memo.pcx";
} else {
return false;
}
@@ -466,7 +448,7 @@ bool TuckerEngine::handleSpecialObjectSelectionSequence() {
--_fadePaletteCounter;
}
_mouseClick = 1;
- loadImage(filename, _quadBackgroundGfxBuf, 1);
+ loadImage(filename.c_str(), _quadBackgroundGfxBuf, 1);
_fadePaletteCounter = 0;
while (!_quitGame) {
waitForTimer(2);
diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp
index 56247a126d..3a49260ab5 100644
--- a/engines/tucker/tucker.cpp
+++ b/engines/tucker/tucker.cpp
@@ -157,11 +157,11 @@ void TuckerEngine::resetVariables() {
_mainLoopCounter1 = _mainLoopCounter2 = 0;
_timerCounter2 = 0;
_part = _currentPart = kPartInit;
- _locationNum = 0;
- _nextLocationNum = (_gameFlags & kGameFlagDemo) == 0 ? kStartupLocationGame : kStartupLocationDemo;
+ _location = kLocationNone;
+ _nextLocation = (_gameFlags & kGameFlagDemo) ? kLocationInitDemo : kLocationInit;
_gamePaused = false;
_gameDebug = false;
- _displaySpeechText = (_gameFlags & kGameFlagNoSubtitles) == 0 ? ConfMan.getBool("subtitles") : false;
+ _displaySpeechText = (_gameFlags & kGameFlagNoSubtitles) ? false : ConfMan.getBool("subtitles");
memset(_flagsTable, 0, sizeof(_flagsTable));
_gameHintsIndex = 0;
@@ -400,7 +400,7 @@ void TuckerEngine::mainLoop() {
loadGameState(slot);
}
} else if (ConfMan.hasKey("boot_param")) {
- _nextLocationNum = ConfMan.getInt("boot_param");
+ _nextLocation = (Location)ConfMan.getInt("boot_param");
}
do {
@@ -427,7 +427,7 @@ void TuckerEngine::mainLoop() {
if (_nextAction != 0) {
loadActionsTable();
}
- if (_nextLocationNum > 0) {
+ if (_nextLocation != kLocationNone) {
setupNewLocation();
}
updateCharPosition();
@@ -499,13 +499,13 @@ void TuckerEngine::mainLoop() {
}
}
_mainSpritesBaseOffset = 0;
- if (_locationWidthTable[_locationNum] > 3) {
+ if (_locationWidthTable[_location] > 3) {
++_currentGfxBackgroundCounter;
if (_currentGfxBackgroundCounter > 39) {
_currentGfxBackgroundCounter = 0;
}
_currentGfxBackground = _quadBackgroundGfxBuf + (_currentGfxBackgroundCounter / 10) * 44800;
- if (_fadePaletteCounter < 34 && _locationNum == 22) {
+ if (_fadePaletteCounter < 34 && _location == kLocationFishingTrawler) {
int offset = (_currentGfxBackgroundCounter > 29 ? 1 : (_currentGfxBackgroundCounter / 10));
_spritesTable[0]._gfxBackgroundOffset = offset * 640;
_mainSpritesBaseOffset = offset;
@@ -589,7 +589,7 @@ void TuckerEngine::mainLoop() {
}
if (_inputKeys[kInputKeyPause]) {
_inputKeys[kInputKeyPause] = false;
- if (_locationNum != 70) {
+ if (_location != kLocationComputerScreen) {
_gamePaused = true;
}
}
@@ -650,6 +650,12 @@ void TuckerEngine::parseEvents() {
while (_eventMan->pollEvent(ev)) {
switch (ev.type) {
case Common::EVENT_KEYDOWN:
+ switch (ev.kbd.ascii) {
+ // do not use KEYCODE_PERIOD here so that it works with most keyboard layouts
+ case '.':
+ _inputKeys[kInputKeySkipSpeech] = true;
+ break;
+ }
switch (ev.kbd.keycode) {
case Common::KEYCODE_f:
if (ev.kbd.hasFlags(Common::KBD_CTRL)) {
@@ -672,9 +678,6 @@ void TuckerEngine::parseEvents() {
_inputKeys[kInputKeyEscape] = true;
_inputKeys[kInputKeySkipSpeech] = true;
break;
- case Common::KEYCODE_PERIOD:
- _inputKeys[kInputKeySkipSpeech] = true;
- break;
case Common::KEYCODE_d:
if (ev.kbd.hasFlags(Common::KBD_CTRL)) {
this->getDebugger()->attach();
@@ -757,10 +760,10 @@ void TuckerEngine::showCursor(bool visible) {
}
void TuckerEngine::setupNewLocation() {
- debug(2, "setupNewLocation() current %d next %d", _locationNum, _nextLocationNum);
- _locationNum = _nextLocationNum;
+ debug(2, "setupNewLocation() current %d next %d", _location, _nextLocation);
+ _location = _nextLocation;
loadObj();
- _nextLocationNum = 0;
+ _nextLocation = kLocationNone;
_fadePaletteCounter = 0;
_mainLoopCounter2 = 0;
_mainLoopCounter1 = 0;
@@ -772,7 +775,7 @@ void TuckerEngine::setupNewLocation() {
_backgroundSpriteCurrentAnimation = -1;
_backgroundSpriteCurrentFrame = 0;
}
- if (!_panelLockedFlag || (_backgroundSpriteCurrentAnimation > 0 && _locationNum != 25)) {
+ if (!_panelLockedFlag || (_backgroundSpriteCurrentAnimation > 0 && _location != kLocationVentSystem)) {
_locationMaskType = 0;
} else {
_locationMaskType = 3;
@@ -803,7 +806,7 @@ void TuckerEngine::setupNewLocation() {
void TuckerEngine::copyLocBitmap(const char *filename, int offset, bool isMask) {
int type = !isMask ? 1 : 0;
- if (offset > 0 && _locationNum == 16) {
+ if (offset > 0 && _location == kLocationPark) {
type = 0;
}
loadImage(filename, _loadTempBuf, type);
@@ -863,7 +866,7 @@ void TuckerEngine::updateCharPosition() {
if (_currentActionVerb == kVerbWalk || _locationMaskCounter == 0) {
return;
}
- if (_currentActionVerb == kVerbLook && _locationNum != 18) {
+ if (_currentActionVerb == kVerbLook && _location != kLocationRoystonsHomeBoxroom) {
int pos;
_actionPosX = _xPosCurrent;
_actionPosY = _yPosCurrent - 64;
@@ -1066,10 +1069,10 @@ void TuckerEngine::setBlackPalette() {
void TuckerEngine::updateCursor() {
setCursorStyle(kCursorNormal);
- if (_backgroundSpriteCurrentAnimation == -1 && !_panelLockedFlag && _selectedObject._locationObjectLocationNum > 0) {
- _selectedObject._locationObjectLocationNum = 0;
+ if (_backgroundSpriteCurrentAnimation == -1 && !_panelLockedFlag && _selectedObject._locationObjectLocation != kLocationNone) {
+ _selectedObject._locationObjectLocation = kLocationNone;
}
- if (_locationMaskType > 0 || _selectedObject._locationObjectLocationNum > 0 || _pendingActionDelay > 0) {
+ if (_locationMaskType > 0 || _selectedObject._locationObjectLocation != kLocationNone || _pendingActionDelay > 0) {
return;
}
if (_rightMouseButtonPressed) {
@@ -1088,7 +1091,7 @@ void TuckerEngine::updateCursor() {
}
if (!_actionVerbLocked) {
setActionVerbUnderCursor();
- if (_actionVerb == kVerbWalk && _locationNum == 63) {
+ if (_actionVerb == kVerbWalk && _location == kLocationTV) {
_actionVerb = kVerbUse;
}
}
@@ -1201,7 +1204,7 @@ void TuckerEngine::updateCharactersPath() {
if (!_panelLockedFlag) {
return;
}
- if (_backgroundSpriteCurrentAnimation != -1 && _locationNum != 25) {
+ if (_backgroundSpriteCurrentAnimation != -1 && _location != kLocationVentSystem) {
if (_xPosCurrent == _selectedObject._xPos && _yPosCurrent == _selectedObject._yPos) {
_locationMaskCounter = 1;
_panelLockedFlag = false;
@@ -1255,7 +1258,7 @@ void TuckerEngine::updateCharactersPath() {
}
}
}
- if (_locationNum == 25) {
+ if (_location == kLocationVentSystem) {
if ((_backgroundSpriteCurrentAnimation != 3 || _characterBackFrontFacing) && (_backgroundSpriteCurrentAnimation != 6 || !_characterBackFrontFacing)) {
_xPosCurrent = xPos;
_yPosCurrent = yPos;
@@ -1274,7 +1277,7 @@ void TuckerEngine::updateCharactersPath() {
if (_characterPrevFacingDirection <= 0 || _characterPrevFacingDirection >= 5) {
return;
}
- if (_selectedObject._locationObjectLocationNum == 0) {
+ if (_selectedObject._locationObjectLocation == kLocationNone) {
_characterFacingDirection = 5;
while (_spriteAnimationFramesTable[_spriteAnimationFrameIndex] != 999) {
++_spriteAnimationFrameIndex;
@@ -1319,7 +1322,7 @@ void TuckerEngine::updateData3() {
a->_animCurrentCounter = a->_animInitCounter;
a->_drawFlag = false;
}
- if (_locationNum == 24 && i == 0) {
+ if (_location == kLocationStoreRoom && i == 0) {
// workaround bug #2872385: update fish animation sequence for correct
// position in aquarium.
if (a->_animInitCounter == 505 && a->_animCurrentCounter == 513) {
@@ -1390,7 +1393,7 @@ void TuckerEngine::saveOrLoad() {
drawSpeechText(_scrollOffset + 120, 170, _infoBarBuf, 21, 102);
}
if (_mousePosY > 140) {
- if (_mouseWheelUp && _currentSaveLoadGameState < 99) {
+ if (_mouseWheelUp && _currentSaveLoadGameState < kLastSaveSlot) {
++_currentSaveLoadGameState;
_forceRedrawPanelItems = true;
return;
@@ -1403,7 +1406,7 @@ void TuckerEngine::saveOrLoad() {
if (_leftMouseButtonPressed && _mouseClick == 0) {
_mouseClick = 1;
if (_mousePosX > 228 && _mousePosX < 240 && _mousePosY > 154 && _mousePosY < 170) {
- if (_currentSaveLoadGameState < 99) {
+ if (_currentSaveLoadGameState < kLastSaveSlot) {
++_currentSaveLoadGameState;
_forceRedrawPanelItems = true;
}
@@ -1467,23 +1470,23 @@ void TuckerEngine::handleMouseOnPanel() {
void TuckerEngine::togglePanelStyle() {
switch (_panelState) {
- case kPanelStateShrinking:
- if (++_switchPanelCounter == 25) {
- _panelStyle = (_panelStyle == kPanelStyleVerbs) ? kPanelStyleIcons : kPanelStyleVerbs;
- loadPanel();
- _forceRedrawPanelItems = true;
- _panelState = kPanelStateExpanding;
- }
- break;
+ case kPanelStateShrinking:
+ if (++_switchPanelCounter == 25) {
+ _panelStyle = (_panelStyle == kPanelStyleVerbs) ? kPanelStyleIcons : kPanelStyleVerbs;
+ loadPanel();
+ _forceRedrawPanelItems = true;
+ _panelState = kPanelStateExpanding;
+ }
+ break;
- case kPanelStateExpanding:
- if (--_switchPanelCounter == 0) {
- _panelState = kPanelStateNormal;
- }
- break;
+ case kPanelStateExpanding:
+ if (--_switchPanelCounter == 0) {
+ _panelState = kPanelStateNormal;
+ }
+ break;
- default:
- break;
+ default:
+ break;
}
}
@@ -1541,11 +1544,11 @@ void TuckerEngine::drawConversationTexts() {
void TuckerEngine::updateScreenScrolling() {
int scrollPrevOffset = _scrollOffset;
- if (_locationWidthTable[_locationNum] != 2) {
+ if (_locationWidthTable[_location] != 2) {
_scrollOffset = 0;
} else if (_validInstructionId) {
_scrollOffset = _xPosCurrent - 200;
- } else if (_locationNum == 16 && _backgroundSpriteCurrentAnimation == 6 && _scrollOffset + 200 < _xPosCurrent) {
+ } else if (_location == kLocationPark && _backgroundSpriteCurrentAnimation == 6 && _scrollOffset + 200 < _xPosCurrent) {
++_scrollOffset;
if (_scrollOffset > 320) {
_scrollOffset = 320;
@@ -1641,7 +1644,7 @@ void TuckerEngine::drawData3() {
}
void TuckerEngine::execData3PreUpdate() {
- switch (_locationNum) {
+ switch (_location) {
case 1:
execData3PreUpdate_locationNum1();
break;
@@ -1774,11 +1777,13 @@ void TuckerEngine::execData3PreUpdate() {
case 70:
execData3PreUpdate_locationNum70();
break;
+ default:
+ break;
}
}
void TuckerEngine::execData3PostUpdate() {
- switch (_locationNum) {
+ switch (_location) {
case 1:
execData3PostUpdate_locationNum1();
break;
@@ -1815,6 +1820,8 @@ void TuckerEngine::execData3PostUpdate() {
case 66:
execData3PostUpdate_locationNum66();
break;
+ default:
+ break;
}
}
@@ -1825,28 +1832,23 @@ void TuckerEngine::drawBackgroundSprites() {
int srcH = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset + 2);
int srcX = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset + 8);
int srcY = READ_LE_UINT16(_backgroundSpriteDataPtr + frameOffset + 10);
- if (_locationNum == 22 && _backgroundSpriteCurrentAnimation > 1) {
+ if (_location == kLocationFishingTrawler && _backgroundSpriteCurrentAnimation > 1) {
srcY += _mainSpritesBaseOffset;
}
- if (_locationNum == 29 && _backgroundSpriteCurrentAnimation == 3) {
+ if (_location == kLocationSubmarineHangar && _backgroundSpriteCurrentAnimation == 3) {
srcX += 228;
- } else if (_locationNum == 58 && _backgroundSpriteCurrentAnimation == 1) {
+ } else if (_location == kLocationInsideMuseumPartThree && _backgroundSpriteCurrentAnimation == 1) {
srcX += 100;
} else if (_xPosCurrent > 320 && _xPosCurrent < 640) {
srcX += 320;
}
srcX += _backgroundSprOffset;
- Graphics::decodeRLE_248(_locationBackgroundGfxBuf + srcY * 640 + srcX, _backgroundSpriteDataPtr + frameOffset + 12, srcW, srcH, 0, _locationHeightTable[_locationNum], false);
+ Graphics::decodeRLE_248(_locationBackgroundGfxBuf + srcY * 640 + srcX, _backgroundSpriteDataPtr + frameOffset + 12, srcW, srcH, 0, _locationHeightTable[_location], false);
addDirtyRect(srcX, srcY, srcW, srcH);
}
}
void TuckerEngine::drawCurrentSprite() {
- // Workaround original game glitch: skip first bud frame drawing when entering location (tracker item #2597763)
- if ((_locationNum == 17 || _locationNum == 18) && _currentSpriteAnimationFrame == 16) {
- return;
- }
-
// WORKAROUND: original game glitch
// Locations 48 and 61 contain reserved colors from [0xE0-0xF8] in a walkable area which
// results in a number of pixels being falsely drawn in the foreground (on top of Bud).
@@ -1859,15 +1861,18 @@ void TuckerEngine::drawCurrentSprite() {
// [0xE0, ... ..., 0xEF]
static const int whitelistReservedColorsLocation48[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
static const int whitelistReservedColorsLocation61[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 };
- switch (_locationNum) {
- case 48:
- whitelistReservedColors = (const int *)&whitelistReservedColorsLocation48;
- break;
+ switch (_location) {
+ case kLocationCorridor:
+ whitelistReservedColors = (const int *)&whitelistReservedColorsLocation48;
+ break;
- case 61:
- if (_xPosCurrent <= 565)
- whitelistReservedColors = (const int *)&whitelistReservedColorsLocation61;
- break;
+ case kLocationParkPartThree:
+ if (_xPosCurrent <= 565)
+ whitelistReservedColors = (const int *)&whitelistReservedColorsLocation61;
+ break;
+
+ default:
+ break;
}
SpriteFrame *chr = &_spriteFramesTable[_currentSpriteAnimationFrame];
@@ -1879,7 +1884,7 @@ void TuckerEngine::drawCurrentSprite() {
xPos -= chr->_xSize + chr->_xOffset - 14;
}
Graphics::decodeRLE_248(_locationBackgroundGfxBuf + yPos * 640 + xPos, _spritesGfxBuf + chr->_sourceOffset, chr->_xSize, chr->_ySize,
- chr->_yOffset, _locationHeightTable[_locationNum], _mirroredDrawing, whitelistReservedColors);
+ chr->_yOffset, _locationHeightTable[_location], _mirroredDrawing, whitelistReservedColors);
addDirtyRect(xPos, yPos, chr->_xSize, chr->_ySize);
if (_currentSpriteAnimationLength > 1) {
SpriteFrame *chr2 = &_spriteFramesTable[_currentSpriteAnimationFrame2];
@@ -1891,7 +1896,7 @@ void TuckerEngine::drawCurrentSprite() {
xPos -= chr2->_xSize + chr2->_xOffset - 14;
}
Graphics::decodeRLE_248(_locationBackgroundGfxBuf + yPos * 640 + xPos, _spritesGfxBuf + chr2->_sourceOffset, chr2->_xSize, chr2->_ySize,
- chr2->_yOffset, _locationHeightTable[_locationNum], _mirroredDrawing, whitelistReservedColors);
+ chr2->_yOffset, _locationHeightTable[_location], _mirroredDrawing, whitelistReservedColors);
addDirtyRect(xPos, yPos, chr2->_xSize, chr2->_ySize);
}
}
@@ -1963,32 +1968,37 @@ void TuckerEngine::redrawPanelItems() {
int sz = 0;
switch (_panelType) {
- case kPanelTypeNormal:
- src = _panelGfxBuf;
- dst = _itemsGfxBuf + 3200;
- sz = 16000;
- break;
- case kPanelTypeEmpty:
- src = _panelGfxBuf + 16320;
- dst = _itemsGfxBuf;
- sz = 19200;
- break;
- case kPanelTypeLoadSavePlayQuit:
- src = _panelGfxBuf + 16320;
- dst = _itemsGfxBuf;
- sz = 19200;
- memcpy(dst, src, sz);
- src = _panelGfxBuf + 55040;
- dst = _itemsGfxBuf + 6400;
- sz = 5120;
- break;
- case kPanelTypeLoadSaveSavegame:
- src = _panelGfxBuf + 35200;
- dst = _itemsGfxBuf;
- sz = 19200;
- break;
- default:
- break;
+ case kPanelTypeNormal:
+ src = _panelGfxBuf;
+ dst = _itemsGfxBuf + 3200;
+ sz = 16000;
+ break;
+ case kPanelTypeEmpty:
+ src = _panelGfxBuf + 16320;
+ dst = _itemsGfxBuf;
+ sz = 19200;
+ break;
+ case kPanelTypeLoadSavePlayQuit:
+ // The following offset does not match disassembly on purpose to fix a
+ // "glitch" in the original game.
+ // This ensures that the background image ends up in the same place as
+ // in the case of kPanelTypeLoadSaveSavegame.
+ // This fixes Trac#10496.
+ src = _panelGfxBuf + 16000;
+ dst = _itemsGfxBuf;
+ sz = 19200;
+ memcpy(dst, src, sz);
+ src = _panelGfxBuf + 55040;
+ dst = _itemsGfxBuf + 6400;
+ sz = 5120;
+ break;
+ case kPanelTypeLoadSaveSavegame:
+ src = _panelGfxBuf + 35200;
+ dst = _itemsGfxBuf;
+ sz = 19200;
+ break;
+ default:
+ break;
}
memcpy(dst, src, sz);
if (_panelType == kPanelTypeNormal) {
@@ -2176,7 +2186,7 @@ void TuckerEngine::updateCharacterAnimation() {
assert(_backgroundSpriteCurrentAnimation >= 0 && _backgroundSpriteCurrentAnimation < kSprA02TableSize);
_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
- } else if (_locationNum == 25 && !_panelLockedFlag && (_backgroundSpriteCurrentAnimation == 3 || _backgroundSpriteCurrentAnimation == 6)) {
+ } else if (_location == kLocationVentSystem && !_panelLockedFlag && (_backgroundSpriteCurrentAnimation == 3 || _backgroundSpriteCurrentAnimation == 6)) {
_backgroundSpriteCurrentFrame = 0;
_backgroundSpriteCurrentAnimation = -1;
} else {
@@ -2191,10 +2201,10 @@ void TuckerEngine::updateCharacterAnimation() {
}
}
}
- if (_locationNum == 24 && _flagsTable[103] == 0) {
+ if (_location == kLocationStoreRoom && _flagsTable[103] == 0) {
if (_panelLockedFlag) {
_panelLockedFlag = false;
- _selectedObject._locationObjectLocationNum = 0;
+ _selectedObject._locationObjectLocation = kLocationNone;
if (_actionVerb != kVerbTalk) {
_speechSoundNum = 2236;
startSpeechSound(_speechSoundNum, _speechVolume);
@@ -2227,7 +2237,7 @@ void TuckerEngine::updateCharacterAnimation() {
_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
}
- } else if (_locationNum == 25) {
+ } else if (_location == kLocationVentSystem) {
if (_backgroundSpriteCurrentFrame == 0) {
if (!_characterBackFrontFacing) {
if (_characterBackFrontFacing != _characterPrevBackFrontFacing) {
@@ -2256,7 +2266,7 @@ void TuckerEngine::updateCharacterAnimation() {
_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
}
_backgroundSprOffset = _xPosCurrent - 160;
- } else if (_locationNum == 63 && _backgroundSpriteCurrentFrame == 0) {
+ } else if (_location == kLocationTV && _backgroundSpriteCurrentFrame == 0) {
if (_charSpeechSoundCounter > 0 && _actionCharacterNum == 99) {
_backgroundSpriteCurrentAnimation = 1;
} else {
@@ -2267,7 +2277,7 @@ void TuckerEngine::updateCharacterAnimation() {
_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
}
int frame = _spriteAnimationFramesTable[_spriteAnimationFrameIndex];
- if (!_panelLockedFlag && _characterFacingDirection < 5 && _selectedObject._locationObjectLocationNum == 0) {
+ if (!_panelLockedFlag && _characterFacingDirection < 5 && _selectedObject._locationObjectLocation == kLocationNone) {
_characterFacingDirection = 0;
}
if (_charSpeechSoundCounter > 0 && _characterFacingDirection != 6 && _actionCharacterNum == 99) {
@@ -2326,7 +2336,7 @@ void TuckerEngine::updateCharacterAnimation() {
num = 13;
} else if (getRandomNumber() < 3000) {
num = 14;
- if (_locationNum == 57) {
+ if (_location == kLocationFishShopPartThree) {
num = 18;
}
} else {
@@ -2414,7 +2424,7 @@ void TuckerEngine::handleMap() {
_panelLockedFlag = false;
}
}
- if (!_panelLockedFlag && (_backgroundSpriteCurrentAnimation == -1 || _locationNum == 25) && _locationMaskType == 3) {
+ if (!_panelLockedFlag && (_backgroundSpriteCurrentAnimation == -1 || _location == kLocationVentSystem) && _locationMaskType == 3) {
setCursorState(kCursorStateNormal);
if (_locationMaskCounter == 1) {
_characterFacingDirection = 0;
@@ -2422,10 +2432,10 @@ void TuckerEngine::handleMap() {
}
return;
}
- if (_selectedObject._locationObjectLocationNum != 0 && _locationMaskCounter != 0 && (_backgroundSpriteCurrentAnimation <= -1 || _locationNum == 25)) {
+ if (_selectedObject._locationObjectLocation != kLocationNone && _locationMaskCounter != 0 && (_backgroundSpriteCurrentAnimation <= -1 || _location == kLocationVentSystem)) {
// TODO
// This is actually "_locationNum != 25" in disassembly. Is this a typo?
- if (_locationNum == 25 || _backgroundSpriteCurrentAnimation != 4) {
+ if (_location == kLocationVentSystem || _backgroundSpriteCurrentAnimation != 4) {
if (_locationMaskType == 0) {
_locationMaskType = 1;
setCursorState(kCursorStateDisabledHidden);
@@ -2440,7 +2450,7 @@ void TuckerEngine::handleMap() {
}
_backgroundSpriteCurrentFrame = 0;
_mirroredDrawing = false;
- if (_locationNum == 25) {
+ if (_location == kLocationVentSystem) {
_backgroundSpriteDataPtr = _sprA02Table[_backgroundSpriteCurrentAnimation];
_backgroundSpriteLastFrame = READ_LE_UINT16(_backgroundSpriteDataPtr);
_backgroundSpriteCurrentFrame = 1;
@@ -2457,7 +2467,7 @@ void TuckerEngine::handleMap() {
_locationMaskType = 2;
_panelType = kPanelTypeNormal;
setCursorState(kCursorStateNormal);
- if (_selectedObject._locationObjectLocationNum == 99) {
+ if (_selectedObject._locationObjectLocation == kLocationMap) {
_noPositionChangeAfterMap = true;
handleMapSequence();
return;
@@ -2467,7 +2477,7 @@ void TuckerEngine::handleMap() {
redrawScreen(_scrollOffset);
_fadePaletteCounter = 34;
}
- _nextLocationNum = _selectedObject._locationObjectLocationNum;
+ _nextLocation = _selectedObject._locationObjectLocation;
_xPosCurrent = _selectedObject._locationObjectToX;
_yPosCurrent = _selectedObject._locationObjectToY;
if (_selectedObject._locationObjectToX2 > 800) {
@@ -2488,7 +2498,7 @@ void TuckerEngine::handleMap() {
_scrollOffset = 0;
_handleMapCounter = 0;
_locationMaskCounter = 0;
- _selectedObject._locationObjectLocationNum = 0;
+ _selectedObject._locationObjectLocation = kLocationNone;
}
}
}
@@ -2502,7 +2512,7 @@ void TuckerEngine::clearSprites() {
}
void TuckerEngine::updateSprites() {
- const int count = (_locationNum == 9) ? 3 : _spritesCount;
+ const int count = (_location == kLocationMall) ? 3 : _spritesCount;
for (int i = 0; i < count; ++i) {
if (_spritesTable[i]._stateIndex > -1) {
++_spritesTable[i]._stateIndex;
@@ -2569,7 +2579,7 @@ void TuckerEngine::updateSprite(int i) {
_updateSpriteFlag2 = false;
_spritesTable[i]._defaultUpdateDelay = 0;
_spritesTable[i]._updateDelay = 0;
- switch (_locationNum) {
+ switch (_location) {
case 2:
updateSprite_locationNum2();
break;
@@ -2942,13 +2952,23 @@ void TuckerEngine::updateSprite(int i) {
case 98:
_spritesTable[0]._state = 1;
break;
+ default:
+ break;
}
if (_spritesTable[i]._stateIndex <= -1) {
if (!_updateSpriteFlag1) {
_spritesTable[i]._animationFrame = 1;
}
if (_spritesTable[i]._state < 0 || !_sprC02Table[_spritesTable[i]._state]) {
-// warning("Invalid state %d for sprite %d location %d", _spritesTable[i].state, i, _locationNum);
+ // WORKAROUND
+ // The original game unconditionally reads into _sprC02Table[] below which
+ // results in out-of-bounds reads when _spritesTable[i]._state == -1.
+ // We reset the sprite's animation data in this case so sprite updates
+ // are triggered correctly. This most prominently fixes a bug where Lola's
+ // transition from dancing -> sitting happens too late.
+ // This fixes Trac#6644.
+ _spritesTable[i]._animationData = nullptr;
+ _spritesTable[i]._firstFrame = 0;
return;
}
_spritesTable[i]._animationData = _sprC02Table[_spritesTable[i]._state];
@@ -3046,7 +3066,7 @@ bool TuckerEngine::testLocationMask(int x, int y) {
if (_locationMaskType > 0 || _locationMaskIgnore) {
return true;
}
- if (_locationNum == 26 || _locationNum == 32) {
+ if (_location == kLocationSubwayTunnel || _location == kLocationKitchen) {
y -= 3;
}
const int offset = y * 640 + x;
@@ -3138,7 +3158,8 @@ enum TableInstructionCode {
kCode_was,
kCode_wfx,
kCode_xhr,
- kCode_xhm
+ kCode_xhm,
+ kCode_no3 // NOOP, throw away 3-byte parameter
};
static const struct {
@@ -3158,12 +3179,14 @@ static const struct {
{ "bso", kCode_bso },
{ "bus", kCode_bus },
{ "b0s", kCode_bus }, // only ref 65.25
+ { "buv", kCode_no3 },
{ "buw", kCode_buw },
{ "bdx", kCode_bux },
{ "bux", kCode_bux },
{ "c0a", kCode_c0a },
{ "c0c", kCode_c0c },
{ "c0s", kCode_c0s },
+ { "c0v", kCode_no3 },
{ "end", kCode_end },
{ "fad", kCode_fad },
{ "fw", kCode_fw },
@@ -3302,7 +3325,7 @@ int TuckerEngine::executeTableInstruction() {
// As a workaround, do not ignore the location mask during this specific
// action when entering the club.
// This fixes Trac#5838.
- if (!(_locationNum == 6 && _nextAction == 59)) {
+ if (!(_location == kLocationStripJoint && _nextAction == 59)) {
_locationMaskIgnore = true;
}
_panelLockedFlag = true;
@@ -3377,10 +3400,10 @@ int TuckerEngine::executeTableInstruction() {
_characterAnimationNum = readTableInstructionParam(2);
return 0;
case kCode_loc:
- _nextLocationNum = readTableInstructionParam(2);
+ _nextLocation = (Location)readTableInstructionParam(2);
return 1;
case kCode_mof:
- // TODO: Unknown opcode in Spanish version. Identify if this has any function.
+ setCursorState(kCursorStateDisabledHidden);
return 0;
case kCode_opt:
_conversationOptionsCount = readTableInstructionParam(2);
@@ -3449,6 +3472,27 @@ int TuckerEngine::executeTableInstruction() {
return 1;
case kCode_wsm:
_stopActionOnPanelLock = true;
+
+ // WORKAROUND
+ // Some versions have a script bug which allows you to freely click around
+ // during the sequence of Bud freeing the professor in part two which even
+ // allows Bud to leave the room while talking to the professor resulting in
+ // general glitchiness. The Spanish and Polish versions (and possibly others)
+ // fixed this by introducing the 'mof' opcode to disable the mouse during the
+ // sequence.
+ //
+ // The difference is as follows:
+ // Buggy: 61dw buw,148,125,wsm,buw,148,132,wsm,wat,050[...]
+ // Fixed: 61dw buw,148,125,wsm,buw,148,132,wsm,mof,pan,01,wat,050[...]
+ // ^^^^^^^^^^
+ // To work around the issue in the problematic versions we inject these two
+ // instructions after the first occurence of the 'wsm' instruction (which
+ // proves good enough).
+ if (_location == kLocationStoreRoom && _nextAction == 61) {
+ setCursorState(kCursorStateDisabledHidden);
+ _panelType = kPanelTypeEmpty;
+ }
+
return 1;
case kCode_wat:
_stopActionCounter = readTableInstructionParam(3);
@@ -3465,6 +3509,10 @@ int TuckerEngine::executeTableInstruction() {
case kCode_xhm:
_validInstructionId = false;
return 0;
+ case kCode_no3:
+ // opcodes mapped here are treated as NOOPs
+ readTableInstructionParam(3);
+ return 0;
}
return 2;
}
@@ -3552,7 +3600,7 @@ void TuckerEngine::setSelectedObjectKey() {
_locationMaskCounter = 0;
_actionRequiresTwoObjects = false;
_selectedObject._yPos = 0;
- _selectedObject._locationObjectLocationNum = 0;
+ _selectedObject._locationObjectLocation = kLocationNone;
_pendingActionIndex = 0;
if (_selectedObjectType == 0) {
if (_selectedObjectNum == 0) {
@@ -3562,7 +3610,7 @@ void TuckerEngine::setSelectedObjectKey() {
_selectedObject._xPos = _locationObjectsTable[_selectedCharacterNum]._standX;
_selectedObject._yPos = _locationObjectsTable[_selectedCharacterNum]._standY;
if (_actionVerb == kVerbWalk || _actionVerb == kVerbUse) {
- _selectedObject._locationObjectLocationNum = _locationObjectsTable[_selectedCharacterNum]._locationNum;
+ _selectedObject._locationObjectLocation = _locationObjectsTable[_selectedCharacterNum]._location;
_selectedObject._locationObjectToX = _locationObjectsTable[_selectedCharacterNum]._toX;
_selectedObject._locationObjectToY = _locationObjectsTable[_selectedCharacterNum]._toY;
_selectedObject._locationObjectToX2 = _locationObjectsTable[_selectedCharacterNum]._toX2;
@@ -3592,14 +3640,14 @@ void TuckerEngine::setSelectedObjectKey() {
_selectedObject._yPos = _mousePosY;
}
_selectedObjectLocationMask = testLocationMask(_selectedObject._xPos, _selectedObject._yPos);
- if (!_selectedObjectLocationMask && _objectKeysLocationTable[_locationNum] == 1) {
- if (_selectedObject._yPos < _objectKeysPosYTable[_locationNum]) {
- while (!_selectedObjectLocationMask && _selectedObject._yPos < _objectKeysPosYTable[_locationNum]) {
+ if (!_selectedObjectLocationMask && _objectKeysLocationTable[_location] == 1) {
+ if (_selectedObject._yPos < _objectKeysPosYTable[_location]) {
+ while (!_selectedObjectLocationMask && _selectedObject._yPos < _objectKeysPosYTable[_location]) {
++_selectedObject._yPos;
_selectedObjectLocationMask = testLocationMask(_selectedObject._xPos, _selectedObject._yPos);
}
} else {
- while (!_selectedObjectLocationMask && _selectedObject._yPos < _objectKeysPosYTable[_locationNum]) {
+ while (!_selectedObjectLocationMask && _selectedObject._yPos < _objectKeysPosYTable[_location]) {
--_selectedObject._yPos;
_selectedObjectLocationMask = testLocationMask(_selectedObject._xPos, _selectedObject._yPos);
}
@@ -3607,12 +3655,12 @@ void TuckerEngine::setSelectedObjectKey() {
}
if (_selectedObjectLocationMask) {
_selectedObjectLocationMask = testLocationMaskArea(_xPosCurrent, _yPosCurrent, _selectedObject._xPos, _selectedObject._yPos);
- if (_selectedObjectLocationMask && _objectKeysPosXTable[_locationNum] > 0) {
+ if (_selectedObjectLocationMask && _objectKeysPosXTable[_location] > 0) {
_selectedObject._xDefaultPos = _selectedObject._xPos;
_selectedObject._yDefaultPos = _selectedObject._yPos;
- _selectedObject._xPos = _objectKeysPosXTable[_locationNum];
- _selectedObject._yPos = _objectKeysPosYTable[_locationNum];
- if (_objectKeysLocationTable[_locationNum] == 1) {
+ _selectedObject._xPos = _objectKeysPosXTable[_location];
+ _selectedObject._yPos = _objectKeysPosYTable[_location];
+ if (_objectKeysLocationTable[_location] == 1) {
_selectedObject._xPos = _selectedObject._xDefaultPos;
}
}
@@ -3699,7 +3747,7 @@ void TuckerEngine::handleMouseClickOnInventoryObject() {
break;
case 1:
if (_actionVerb == kVerbUse && _leftMouseButtonPressed) {
- if (_mapSequenceFlagsLocationTable[_locationNum - 1] == 1) {
+ if (_mapSequenceFlagsLocationTable[_location - 1] == 1) {
handleMapSequence();
} else {
_actionPosX = _xPosCurrent;
@@ -3772,6 +3820,11 @@ int TuckerEngine::setLocationAnimationUnderCursor() {
continue;
}
if (_locationAnimationsTable[i]._selectable == 0) {
+ // WORKAROUND
+ // The original game does a "return -1" here which is not correct in
+ // case of overlapping hotspots.
+ // This most prominently fixes Trac#6645, a bug where the cellar in part three
+ // could be entered without having done the cellar door puzzle first.
continue;
}
_selectedObjectType = 1;
diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h
index cd12939443..e3748680fe 100644
--- a/engines/tucker/tucker.h
+++ b/engines/tucker/tucker.h
@@ -110,10 +110,103 @@ enum VerbPreposition {
};
enum Part {
- kPartInit = 0,
- kPartOne = 1,
- kPartTwo = 2,
- kPartThree = 3
+ kPartInit = 0,
+ kPartOne = 1,
+ kPartTwo = 2,
+ kPartThree = 3
+};
+
+enum Location {
+ kLocationNone = 0,
+
+ kLocationHotelRoom = 1,
+ kLocationBackAlley = 2,
+ kLocationSeedyStreet = 3,
+ kLocationBakersShop = 4,
+ kLocationBakersKitchen = 5,
+ kLocationStripJoint = 6,
+ kLocationPoliceHQ = 7,
+ kLocationPoliceCell = 8,
+ kLocationMall = 9,
+ kLocationFishShop = 10,
+ kLocationBurgerJoint = 11,
+ kLocationRecordShop = 12,
+ kLocationDentist = 13,
+ kLocationPlugShop = 14,
+ kLocationTouristInfo = 15,
+ kLocationPark = 16,
+ kLocationRoystonsHomeHallway = 17,
+ kLocationRoystonsHomeBoxroom = 18,
+ kLocationDocks = 19,
+ kLocationOutsideMuseum = 20,
+ kLocationInsideMuseum = 21,
+ kLocationFishingTrawler = 22,
+ kLocationWarehouseCutscene = 23,
+ kLocationStoreRoom = 24,
+ kLocationVentSystem = 25,
+ kLocationSubwayTunnel = 26,
+ kLocationStrangeRoom = 27,
+ kLocationTopCorridor = 28,
+ kLocationSubmarineHangar = 29,
+ kLocationBunkRoom = 30,
+ kLocationBottomCorridor = 31,
+ kLocationKitchen = 32,
+ kLocationCommandCentre = 33,
+ kLocationSubmarineHatch = 34,
+ kLocationSubmarineWalkway = 35,
+ kLocationSubmarineBridge = 36,
+ kLocationSubmarineOffice = 37,
+ kLocationSubmarineEngineRoom = 38,
+ kLocationLuxuryApartment = 39,
+ kLocationFarDocks = 40,
+ kLocationAlleyway = 41,
+ kLocationBasement = 42,
+ kLocationTateTowerEntrance = 43,
+ kLocationRooftop = 44,
+ kLocationConferenceRoom = 45,
+ kLocationAnteChamber = 46,
+ kLocationHelipad = 47,
+ kLocationCorridor = 48,
+ kLocationWaitingRoom = 49,
+ kLocationkLocationCorridorCutscene = 50,
+ kLocationCells = 51,
+ kLocationMachineRoom = 52,
+ kLocationRecordShopPartThree = 53,
+ kLocationPlugShopPartThree = 54,
+ kLocationTouristInfoPartThree = 55,
+ kLocationDentistPartThree = 56,
+ kLocationFishShopPartThree = 57,
+ kLocationInsideMuseumPartThree = 58,
+ kLocationBakersShopPartThree = 59,
+ kLocationStripJointPartThree = 60,
+ kLocationParkPartThree = 61,
+ kLocationDocksPartThree = 62,
+ kLocationTV = 63,
+ kLocationSewer = 64,
+ kLocationSeedyStreetPartThree = 65,
+ kLocationMallPartThree = 66,
+ kLocationBurgerJointPartThree = 67,
+ kLocationOutsideMuseumPartThree = 68,
+ kLocation69Cutscene = 69,
+ kLocationComputerScreen = 70,
+ kLocationParkCutscene = 71,
+ kLocationSeedyStreetCutscene = 72,
+ kLocationJesusCutscene1 = 73,
+ kLocationCredits = 74,
+ kLocation75Cutscene = 75,
+ kLocationBeachCutscene = 76,
+ kLocationHospitalCutscene = 77,
+ kLocation78Cutscene = 78,
+ kLocationElvisCutscene = 79,
+ kLocationPyramidCutscene = 80,
+ kLocationCleopatraCutscene = 81,
+ kLocationJesusCutscene2 = 82,
+
+ kLocationNewPart = 98,
+ kLocationMap = 99,
+
+ kLocationInit = 1,
+ kLocationInitDemo = 9
};
struct Action {
@@ -212,7 +305,7 @@ struct LocationObject {
int _xSize;
int _ySize;
int _textNum;
- int _locationNum;
+ Location _location;
int _toX;
int _toY;
int _toX2;
@@ -251,8 +344,6 @@ enum {
kScreenHeight = 200,
kScreenPitch = 640,
kFadePaletteStep = 5,
- kStartupLocationDemo = 9,
- kStartupLocationGame = 1,
kDefaultCharSpeechSoundCounter = 1,
kMaxSoundVolume = 127,
kLastSaveSlot = 99,
@@ -361,8 +452,8 @@ public:
virtual bool hasFeature(EngineFeature f) const;
GUI::Debugger *getDebugger() { return _console; }
- static SavegameError readSavegameHeader(Common::InSaveFile *file, SavegameHeader &header, bool loadThumbnail = false);
- static SavegameError readSavegameHeader(const char *target, int slot, SavegameHeader &header);
+ WARN_UNUSED_RESULT static SavegameError readSavegameHeader(Common::InSaveFile *file, SavegameHeader &header, bool skipThumbnail = true);
+ WARN_UNUSED_RESULT static SavegameError readSavegameHeader(const char *target, int slot, SavegameHeader &header);
bool isAutosaveAllowed();
static bool isAutosaveAllowed(const char *target);
protected:
@@ -719,8 +810,8 @@ protected:
int _flagsTable[kFlagsTableSize];
Part _part;
Part _currentPart;
- int _locationNum;
- int _nextLocationNum;
+ Location _location;
+ Location _nextLocation;
bool _gamePaused;
bool _gameDebug;
bool _displayGameHints;
@@ -850,7 +941,7 @@ protected:
int _yDefaultPos;
int _xPos;
int _yPos;
- int _locationObjectLocationNum;
+ Location _locationObjectLocation;
int _locationObjectToX;
int _locationObjectToY;
int _locationObjectToX2;
diff --git a/engines/voyeur/detection.cpp b/engines/voyeur/detection.cpp
index eefe174e94..6452e5741f 100644
--- a/engines/voyeur/detection.cpp
+++ b/engines/voyeur/detection.cpp
@@ -132,7 +132,6 @@ SaveStateList VoyeurMetaEngine::listSaves(const char *target) const {
if (in) {
if (header.read(in)) {
saveList.push_back(SaveStateDescriptor(slot, header._saveName));
- header._thumbnail->free();
}
delete in;
}
@@ -159,7 +158,7 @@ SaveStateDescriptor VoyeurMetaEngine::querySaveMetaInfos(const char *target, int
if (f) {
Voyeur::VoyeurSavegameHeader header;
- header.read(f);
+ header.read(f, false);
delete f;
// Create the return descriptor
diff --git a/engines/voyeur/files_threads.cpp b/engines/voyeur/files_threads.cpp
index 1b4e30665c..af8753c488 100644
--- a/engines/voyeur/files_threads.cpp
+++ b/engines/voyeur/files_threads.cpp
@@ -864,7 +864,7 @@ const byte *ThreadResource::cardPerform(const byte *card) {
if (cardPerform2(card, id)) {
card += subId;
card = cardPerform(card);
- while (*card++ != 61) ;
+ while (*card++ != 61) {}
} else {
card += subId;
while (*card != 61 && *card != 29)
diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp
index 7f2f0e312e..b7769c1fd4 100644
--- a/engines/voyeur/voyeur.cpp
+++ b/engines/voyeur/voyeur.cpp
@@ -789,9 +789,6 @@ void VoyeurEngine::loadGame(int slot) {
VoyeurSavegameHeader header;
if (!header.read(saveFile))
return;
- if (header._thumbnail)
- header._thumbnail->free();
- delete header._thumbnail;
serializer.setVersion(header._version);
synchronize(serializer);
@@ -856,9 +853,7 @@ void VoyeurEngine::synchronize(Common::Serializer &s) {
/*------------------------------------------------------------------------*/
-bool VoyeurSavegameHeader::read(Common::InSaveFile *f) {
- _thumbnail = NULL;
-
+bool VoyeurSavegameHeader::read(Common::InSaveFile *f, bool skipThumbnail) {
uint32 signature = f->readUint32BE();
if (signature != MKTAG('V', 'O', 'Y', 'R')) {
warning("Invalid savegame");
@@ -875,9 +870,9 @@ bool VoyeurSavegameHeader::read(Common::InSaveFile *f) {
_saveName += c;
// Get the thumbnail
- _thumbnail = Graphics::loadThumbnail(*f);
- if (!_thumbnail)
+ if (!Graphics::loadThumbnail(*f, _thumbnail, skipThumbnail)) {
return false;
+ }
// Read in the save datet/ime
_saveYear = f->readSint16LE();
diff --git a/engines/voyeur/voyeur.h b/engines/voyeur/voyeur.h
index dcd82b24a9..a098ba9e62 100644
--- a/engines/voyeur/voyeur.h
+++ b/engines/voyeur/voyeur.h
@@ -312,7 +312,7 @@ struct VoyeurSavegameHeader {
/**
* Read in the header from the specified file
*/
- bool read(Common::InSaveFile *f);
+ bool read(Common::InSaveFile *f, bool skipThumbnail = true);
/**
* Write out header information to the specified file
diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h
index cbf5d92d00..905d227d3c 100644
--- a/engines/wintermute/base/base_engine.h
+++ b/engines/wintermute/base/base_engine.h
@@ -34,10 +34,24 @@
#include "common/random.h"
#include "common/language.h"
-#include "engines/wintermute/game_description.h"
-
namespace Wintermute {
+enum WMETargetExecutable {
+ OLDEST_VERSION,
+ WME_1_0_0,
+ WME_1_1_0,
+ WME_1_2_0,
+ WME_1_3_0,
+ WME_1_4_0,
+ WME_1_5_0,
+ WME_1_6_0,
+ WME_1_7_0,
+ WME_1_8_0,
+ WME_1_8_6,
+ WME_1_9_0,
+ LATEST_VERSION
+};
+
class BaseFileManager;
class BaseRegistry;
class BaseGame;
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
index 0f6a184cb3..15cd33d28c 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -125,7 +125,7 @@ bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) {
Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
g_system->beginGFXTransaction();
- g_system->initSize(_width, _height, &format);
+ g_system->initSize(_width, _height, &format);
OSystem::TransactionError gfxError = g_system->endGFXTransaction();
if (gfxError != OSystem::kTransactionSuccess) {
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
index bc267fd656..47099046e9 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
@@ -96,7 +96,7 @@ public:
bool setViewport(Rect32 *rect) override { return BaseRenderer::setViewport(rect); }
Rect32 getViewPort() override;
void modTargetRect(Common::Rect *rect);
- void pointFromScreen(Point32 *point) ;
+ void pointFromScreen(Point32 *point);
void pointToScreen(Point32 *point);
void dumpData(const char *filename) override;
diff --git a/engines/wintermute/base/particles/part_emitter.cpp b/engines/wintermute/base/particles/part_emitter.cpp
index c64a099cee..1c102d17ee 100644
--- a/engines/wintermute/base/particles/part_emitter.cpp
+++ b/engines/wintermute/base/particles/part_emitter.cpp
@@ -214,7 +214,8 @@ bool PartEmitter::initParticle(PartParticle *particle, uint32 currentTime, uint3
Vector2 vecVel(0, velocity);
Matrix4 matRot;
- matRot.rotationZ(Common::deg2rad(BaseUtils::normalizeAngle(angle - 180)));
+ float radZrot = Common::deg2rad<float>(BaseUtils::normalizeAngle(angle - 180.0));
+ matRot.rotationZ(radZrot);
matRot.transformVector2(vecVel);
if (_alphaTimeBased) {
@@ -433,7 +434,8 @@ bool PartEmitter::addForce(const Common::String &name, PartForce::TForceType typ
force->_direction = Vector2(0, strength);
Matrix4 matRot;
- matRot.rotationZ(Common::deg2rad(BaseUtils::normalizeAngle(angle - 180)));
+ float radZrot = Common::deg2rad<float>(BaseUtils::normalizeAngle(angle - 180.0));
+ matRot.rotationZ(radZrot);
matRot.transformVector2(force->_direction);
return STATUS_OK;
diff --git a/engines/wintermute/base/sound/base_sound_buffer.cpp b/engines/wintermute/base/sound/base_sound_buffer.cpp
index 5fdac12cef..0c8103339f 100644
--- a/engines/wintermute/base/sound/base_sound_buffer.cpp
+++ b/engines/wintermute/base/sound/base_sound_buffer.cpp
@@ -33,7 +33,9 @@
#include "engines/wintermute/wintermute.h"
#include "audio/audiostream.h"
#include "audio/mixer.h"
+#ifdef USE_VORBIS
#include "audio/decoders/vorbis.h"
+#endif
#include "audio/decoders/wave.h"
#include "audio/decoders/raw.h"
#include "common/system.h"
@@ -103,7 +105,11 @@ bool BaseSoundBuffer::loadFromFile(const Common::String &filename, bool forceRel
Common::String strFilename(filename);
strFilename.toLowercase();
if (strFilename.hasSuffix(".ogg")) {
+#ifdef USE_VORBIS
_stream = Audio::makeVorbisStream(_file, DisposeAfterUse::YES);
+#else
+ error("BSoundBuffer::LoadFromFile - Ogg Vorbis not supported by this version of ScummVM (please report as this shouldn't trigger)");
+#endif
} else if (strFilename.hasSuffix(".wav")) {
int waveSize, waveRate;
byte waveFlags;
diff --git a/engines/wintermute/configure.engine b/engines/wintermute/configure.engine
index 55385776de..29af5601aa 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 highres"
+add_engine wintermute "Wintermute" yes "" "" "zlib 16bit highres"
diff --git a/engines/wintermute/debugger/error.h b/engines/wintermute/debugger/error.h
index 4e5b973445..0798fe7cb3 100644
--- a/engines/wintermute/debugger/error.h
+++ b/engines/wintermute/debugger/error.h
@@ -28,27 +28,27 @@
namespace Wintermute {
enum ErrorLevel {
- SUCCESS,
- NOTICE,
- WARNING,
- ERROR
+ SUCCESS,
+ NOTICE,
+ WARNING,
+ ERROR
};
enum ErrorCode {
- OK,
- NO_SUCH_SOURCE,
- COULD_NOT_OPEN,
- NO_SUCH_LINE,
- NOT_ALLOWED,
- NO_SUCH_BYTECODE,
- DUPLICATE_BREAKPOINT,
- NO_SUCH_BREAKPOINT,
- WRONG_TYPE,
- PARSE_ERROR,
- NOT_YET_IMPLEMENTED,
- SOURCE_PATH_NOT_SET,
- ILLEGAL_PATH,
- UNKNOWN_ERROR
+ OK,
+ NO_SUCH_SOURCE,
+ COULD_NOT_OPEN,
+ NO_SUCH_LINE,
+ NOT_ALLOWED,
+ NO_SUCH_BYTECODE,
+ DUPLICATE_BREAKPOINT,
+ NO_SUCH_BREAKPOINT,
+ WRONG_TYPE,
+ PARSE_ERROR,
+ NOT_YET_IMPLEMENTED,
+ SOURCE_PATH_NOT_SET,
+ ILLEGAL_PATH,
+ UNKNOWN_ERROR
};
diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp
index 9ccb75d62f..6208d775a6 100644
--- a/engines/wintermute/detection.cpp
+++ b/engines/wintermute/detection.cpp
@@ -22,6 +22,7 @@
#include "engines/advancedDetector.h"
#include "engines/wintermute/wintermute.h"
+#include "engines/wintermute/game_description.h"
#include "engines/wintermute/base/base_persistence_manager.h"
#include "common/config-manager.h"
@@ -99,7 +100,7 @@ public:
return "Copyright (C) 2011 Jan Nedoma";
}
- virtual const ADGameDescription *fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const {
+ ADDetectedGame fallbackDetect(const FileMap &allFiles, const Common::FSList &fslist) const override {
// Set some defaults
s_fallbackDesc.extra = "";
s_fallbackDesc.language = Common::UNK_LANG;
@@ -129,10 +130,12 @@ public:
s_fallbackDesc.extra = offset;
s_fallbackDesc.flags |= ADGF_USEEXTRAASTITLE;
}
- return &s_fallbackDesc;
+
+ return ADDetectedGame(&s_fallbackDesc);
} // Fall through to return 0;
}
- return 0;
+
+ return ADDetectedGame();
}
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index 5b87dd439c..68ad9c1751 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -43,7 +43,7 @@ static const PlainGameDescriptor wintermuteGames[] = {
{"conspiracao", "Conspiracao Dumont"},
{"corrosion", "Corrosion: Cold Winter Waiting"},
{"deadcity", "Dead City"},
- {"dfafadventure", "DFAF Adventure"},
+ {"dfafadventure", "DFAF Adventure"},
{"dreamcat", "Dreamcat"},
{"dreaming", "Des Reves Elastiques Avec Mille Insectes Nommes Georges"},
{"dirtysplit", "Dirty Split"},
@@ -243,7 +243,7 @@ static const WMEGameDescription gameDescriptions[] = {
"data.dcp", "7ebfd50d1a22370ed7b079bcaa631d62", 9070205), Common::RU_RUS, ADGF_UNSTABLE, LATEST_VERSION),
// DFAF Adventure
WME_WINENTRY("dfafadventure", "",
- WME_ENTRY1s("data.dcp","5704ebef961176f647742aa66bd09352", 10083417), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
+ WME_ENTRY1s("data.dcp","5704ebef961176f647742aa66bd09352", 10083417), Common::EN_ANY, ADGF_UNSTABLE | GF_LOWSPEC_ASSETS, LATEST_VERSION),
// Dirty Split (Czech)
WME_WINENTRY("dirtysplit", "",
WME_ENTRY2s("czech.dcp", "08a71446467cf8f9444cfea446b46ad6", 127697934,
@@ -271,7 +271,7 @@ static const WMEGameDescription gameDescriptions[] = {
WME_ENTRY1s("data.dcp", "4af26d97ea063fc1277ce30ae431de90", 8804073), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
// Dreamcat
WME_WINENTRY("dreamcat", "",
- WME_ENTRY1s("data.dcp","189bd4eef29034f4ff4ed30120eaac4e", 7758040), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
+ WME_ENTRY1s("data.dcp","189bd4eef29034f4ff4ed30120eaac4e", 7758040), Common::EN_ANY, ADGF_UNSTABLE | GF_LOWSPEC_ASSETS, LATEST_VERSION),
// Dreamscape
WME_WINENTRY("dreamscape", "",
WME_ENTRY1s("data.dcp", "7a5752ed4446c862be9f02d7932acf54", 17034377), Common::EN_ANY, ADGF_UNSTABLE, LATEST_VERSION),
@@ -378,7 +378,7 @@ static const WMEGameDescription gameDescriptions[] = {
"d_sounds.dcp", "7d04dff8ca11174486bd4b7a80fdcabb", 154943401), Common::ES_ESP, ADGF_UNSTABLE, LATEST_VERSION),
// Open Quest
WME_WINENTRY("openquest", "",
- WME_ENTRY1s("data.dcp", "16893e3fc15a211a49654ae66f684f28", 82281736), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
+ WME_ENTRY1s("data.dcp", "16893e3fc15a211a49654ae66f684f28", 82281736), Common::EN_ANY, ADGF_UNSTABLE | GF_LOWSPEC_ASSETS, LATEST_VERSION),
// Night Train Demo
WME_WINENTRY("nighttrain", "",
WME_ENTRY1s("data.dcp", "5a027ef84b083a730c9a4c85ec1d3a32", 131760816), Common::EN_ANY, ADGF_UNSTABLE | ADGF_DEMO, LATEST_VERSION),
@@ -589,4 +589,3 @@ static const WMEGameDescription gameDescriptions[] = {
#undef WEM_ENTRY3s
#undef WME_WINENTRY
#undef WME_PLATENTRY
-
diff --git a/engines/wintermute/game_description.h b/engines/wintermute/game_description.h
index 313fff8bbf..92f62dd7f6 100644
--- a/engines/wintermute/game_description.h
+++ b/engines/wintermute/game_description.h
@@ -24,25 +24,10 @@
#define WINTERMUTE_GAME_DESCRIPTION_H
#include "engines/advancedDetector.h"
+#include "engines/wintermute/base/base_engine.h"
namespace Wintermute {
-enum WMETargetExecutable {
- OLDEST_VERSION,
- WME_1_0_0,
- WME_1_1_0,
- WME_1_2_0,
- WME_1_3_0,
- WME_1_4_0,
- WME_1_5_0,
- WME_1_6_0,
- WME_1_7_0,
- WME_1_8_0,
- WME_1_8_6,
- WME_1_9_0,
- LATEST_VERSION
-};
-
struct WMEGameDescription {
ADGameDescription adDesc;
WMETargetExecutable targetExecutable;
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index e68004d1e5..77df30a54a 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -34,6 +34,7 @@
#include "engines/wintermute/ad/ad_game.h"
#include "engines/wintermute/wintermute.h"
#include "engines/wintermute/debugger.h"
+#include "engines/wintermute/game_description.h"
#include "engines/wintermute/platform_osystem.h"
#include "engines/wintermute/base/base_engine.h"
@@ -43,6 +44,8 @@
#include "engines/wintermute/base/scriptables/script_engine.h"
#include "engines/wintermute/debugger/debugger_controller.h"
+#include "gui/message.h"
+
namespace Wintermute {
// Simple constructor for detection - we need to setup the persistence to avoid special-casing in-engine
@@ -109,7 +112,11 @@ bool WintermuteEngine::hasFeature(EngineFeature f) const {
Common::Error WintermuteEngine::run() {
// Initialize graphics using following:
Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
- initGraphics(800, 600, &format);
+ if (_gameDescription->adDesc.flags & GF_LOWSPEC_ASSETS) {
+ initGraphics(320, 240, &format);
+ } else {
+ initGraphics(800, 600, &format);
+ }
if (g_system->getScreenFormat() != format) {
error("Wintermute currently REQUIRES 32bpp");
}
@@ -138,6 +145,18 @@ Common::Error WintermuteEngine::run() {
int WintermuteEngine::init() {
BaseEngine::createInstance(_targetName, _gameDescription->adDesc.gameId, _gameDescription->adDesc.language, _gameDescription->targetExecutable);
+
+ // check dependencies for games with high resolution assets
+ #if not defined(USE_PNG) || not defined(USE_JPEG) || not defined(USE_VORBIS)
+ if (!(_gameDescription->adDesc.flags & GF_LOWSPEC_ASSETS)) {
+ GUI::MessageDialog dialog("This game requires PNG, JPEG and Vorbis support.");
+ dialog.runModal();
+ delete _game;
+ _game = nullptr;
+ return false;
+ }
+ #endif
+
_game = new AdGame(_targetName);
if (!_game) {
return 1;
diff --git a/engines/wintermute/wintermute.h b/engines/wintermute/wintermute.h
index a8f9a18530..fe999df082 100644
--- a/engines/wintermute/wintermute.h
+++ b/engines/wintermute/wintermute.h
@@ -24,9 +24,8 @@
#define WINTERMUTE_WINTERMUTE_H
#include "engines/engine.h"
-#include "engines/advancedDetector.h"
#include "gui/debugger.h"
-#include "engines/wintermute/game_description.h"
+#include "common/fs.h"
namespace Wintermute {
@@ -34,6 +33,7 @@ class Console;
class BaseGame;
class SystemClassRegistry;
class DebuggerController;
+struct WMEGameDescription;
// our engine debug channels
enum {
@@ -45,6 +45,11 @@ enum {
kWintermuteDebugGeneral = 1 << 5
};
+enum WintermuteGameFeatures {
+ /** A game with low-spec resources. */
+ GF_LOWSPEC_ASSETS = 1 << 0
+};
+
class WintermuteEngine : public Engine {
public:
WintermuteEngine(OSystem *syst, const WMEGameDescription *desc);
diff --git a/engines/xeen/POTFILES b/engines/xeen/POTFILES
new file mode 100644
index 0000000000..27314a435e
--- /dev/null
+++ b/engines/xeen/POTFILES
@@ -0,0 +1 @@
+engines/xeen/detection.cpp
diff --git a/engines/xeen/character.cpp b/engines/xeen/character.cpp
index 248d432a82..afc013ba89 100644
--- a/engines/xeen/character.cpp
+++ b/engines/xeen/character.cpp
@@ -37,14 +37,27 @@ void AttributePair::synchronize(Common::Serializer &s) {
/*------------------------------------------------------------------------*/
-Character::Character():
- _weapons(this), _armor(this), _accessories(this), _misc(this),
- _items(_weapons, _armor, _accessories, _misc) {
+int CharacterArray::indexOf(const Character &c) {
+ for (uint idx = 0; idx < size(); ++idx) {
+ if ((*this)[idx] == c)
+ return idx;
+ }
+
+ return -1;
+}
+
+/*------------------------------------------------------------------------*/
+
+Character::Character(): _weapons(this), _armor(this), _accessories(this), _misc(this), _items(this) {
clear();
_faceSprites = nullptr;
_rosterId = -1;
}
+Character::Character(const Character &src) : _weapons(this), _armor(this), _accessories(this), _misc(this), _items(this) {
+ operator=(src);
+}
+
void Character::clear() {
_sex = MALE;
_race = HUMAN;
@@ -90,6 +103,65 @@ void Character::clear() {
_misc.clear();
}
+Character &Character::operator=(const Character &src) {
+ clear();
+
+ _faceSprites = src._faceSprites;
+ _rosterId = src._rosterId;
+ _name = src._name;
+ _sex = src._sex;
+ _race = src._race;
+ _xeenSide = src._xeenSide;
+ _class = src._class;
+ _might = src._might;
+ _intellect = src._intellect;
+ _personality = src._personality;
+ _endurance = src._endurance;
+ _speed = src._speed;
+ _accuracy = src._accuracy;
+ _luck = src._luck;
+ _ACTemp = src._ACTemp;
+ _level = src._level;
+ _birthDay = src._birthDay;
+ _tempAge = src._tempAge;
+ Common::copy(&src._skills[0], &src._skills[18], &_skills[0]);
+ Common::copy(&src._awards[0], &src._awards[128], &_awards[0]);
+ Common::copy(&src._spells[0], &src._spells[SPELLS_PER_CLASS], &_spells[0]);
+ _lloydMap = src._lloydMap;
+ _lloydPosition = src._lloydPosition;
+ _hasSpells = src._hasSpells;
+ _currentSpell = src._currentSpell;
+ _quickOption = src._quickOption;
+ _weapons = src._weapons;
+ _armor = src._armor;
+ _accessories = src._accessories;
+ _misc = src._misc;
+ _lloydSide = src._lloydSide;
+ _fireResistence = src._fireResistence;
+ _coldResistence = src._coldResistence;
+ _electricityResistence = src._electricityResistence;
+ _poisonResistence = src._poisonResistence;
+ _energyResistence = src._energyResistence;
+ _magicResistence = src._magicResistence;
+ Common::copy(&src._conditions[0], &src._conditions[16], &_conditions[0]);
+ _townUnknown = src._townUnknown;
+ _savedMazeId = src._savedMazeId;
+ _currentHp = src._currentHp;
+ _currentSp = src._currentSp;
+ _birthYear = src._birthYear;
+ _experience = src._experience;
+ _currentAdventuringSpell = src._currentAdventuringSpell;
+ _currentCombatSpell = src._currentCombatSpell;
+
+ for (ItemCategory category = CATEGORY_WEAPON; category <= CATEGORY_MISC; category = (ItemCategory)((int)category + 1)) {
+ const InventoryItems &srcItems = src._items[category];
+ InventoryItems &destItems = _items[category];
+ destItems = srcItems;
+ }
+
+ return *this;
+}
+
void Character::synchronize(Common::Serializer &s) {
char name[16];
Common::fill(&name[0], &name[16], '\0');
@@ -124,7 +196,7 @@ void Character::synchronize(Common::Serializer &s) {
// upper nibble of the first 64 bytes. Except for award 9, which was a full
// byte counter counting the number of times the warzone was awarded
for (int idx = 0; idx < 64; ++idx) {
- byte b = (idx == WARZONE_AWARD) ? _awards[idx] :
+ byte b = (idx == WARZONE_AWARD) ? _awards[idx] :
(_awards[idx] ? 0x1 : 0) | (_awards[idx + 64] ? 0x10 : 0);
s.syncAsByte(b);
if (s.isLoading()) {
@@ -134,7 +206,7 @@ void Character::synchronize(Common::Serializer &s) {
}
// Synchronize spell list
- for (int i = 0; i < MAX_SPELLS_PER_CLASS; ++i)
+ for (int i = 0; i < SPELLS_PER_CLASS; ++i)
s.syncAsByte(_spells[i]);
s.syncAsByte(_lloydMap);
s.syncAsByte(_lloydPosition.x);
@@ -165,8 +237,8 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsUint16LE(_townUnknown);
s.syncAsByte(_savedMazeId);
- s.syncAsUint16LE(_currentHp);
- s.syncAsUint16LE(_currentSp);
+ s.syncAsSint16LE(_currentHp);
+ s.syncAsSint16LE(_currentSp);
s.syncAsUint16LE(_birthYear);
s.syncAsUint32LE(_experience);
s.syncAsByte(_currentAdventuringSpell);
@@ -338,7 +410,7 @@ int Character::statColor(int amount, int threshold) {
return 2;
else if (amount == threshold)
return 15;
- else if (amount <= (threshold / 4))
+ else if (amount >= (threshold / 4))
return 9;
else
return 32;
@@ -393,12 +465,12 @@ bool Character::noActions() {
Condition condition = worstCondition();
switch (condition) {
- case CURSED:
- case POISONED:
- case DISEASED:
- case INSANE:
- case IN_LOVE:
- case DRUNK: {
+ case ASLEEP:
+ case PARALYZED:
+ case UNCONSCIOUS:
+ case DEAD:
+ case STONED:
+ case ERADICATED: {
Common::String msg = Common::String::format(Res.IN_NO_CONDITION, _name.c_str());
ErrorScroll::show(Party::_vm, msg,
Party::_vm->_mode == 17 ? WT_LOC_WAIT : WT_NONFREEZED_WAIT);
@@ -482,7 +554,7 @@ int Character::itemScan(int itemId) const {
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
const XeenItem &item = _weapons[idx];
- if (item._frame && !(item._bonusFlags & 0xC0) && itemId < 11
+ if (item._frame && !item.isBad() && itemId < 11
&& itemId != 3 && item._material >= 59 && item._material <= 130) {
int mIndex = (int)item.getAttributeCategory();
if (mIndex > PERSONALITY)
@@ -497,7 +569,7 @@ int Character::itemScan(int itemId) const {
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
const XeenItem &item = _armor[idx];
- if (item._frame && !(item._bonusFlags & 0xC0)) {
+ if (item._frame && !item.isBad()) {
if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
int mIndex = (int)item.getAttributeCategory();
if (mIndex > PERSONALITY)
@@ -528,7 +600,7 @@ int Character::itemScan(int itemId) const {
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
const XeenItem &item = _accessories[idx];
- if (item._frame && !(item._bonusFlags & 0xC0)) {
+ if (item._frame && !item.isBad()) {
if (itemId < 11 && itemId != 3 && item._material >= 59 && item._material <= 130) {
int mIndex = (int)item.getAttributeCategory();
if (mIndex > PERSONALITY)
@@ -800,21 +872,36 @@ bool Character::guildMember() const {
FileManager &files = *g_vm->_files;
Party &party = *g_vm->_party;
- if (party._mazeId == 49 && !files._isDarkCc) {
+ if (g_vm->getGameID() == GType_Swords) {
+ switch (party._mazeId) {
+ case 49:
+ return true;
+ case 53:
+ return hasAward(83);
+ case 63:
+ return hasAward(85);
+ case 92:
+ return hasAward(84);
+ default:
+ return hasAward(87);
+ }
+ } else if (files._ccNum) {
+ switch (party._mazeId) {
+ case 29:
+ return hasAward(CASTLEVIEW_GUILD_MEMBER);
+ case 31:
+ return hasAward(SANDCASTER_GUILD_MEMBER);
+ case 33:
+ return hasAward(LAKESIDE_GUILD_MEMBER);
+ case 35:
+ return hasAward(NECROPOLIS_GUILD_MEMBER);
+ default:
+ return hasAward(OLYMPUS_GUILD_MEMBER);
+ }
+ } else if (party._mazeId == 49) {
return hasAward(SHANGRILA_GUILD_MEMBER);
- }
-
- switch (party._mazeId) {
- case 29:
- return hasAward(CASTLEVIEW_GUILD_MEMBER);
- case 31:
- return hasAward(SANDCASTER_GUILD_MEMBER);
- case 33:
- return hasAward(LAKESIDE_GUILD_MEMBER);
- case 35:
- return hasAward(NECROPOLIS_GUILD_MEMBER);
- default:
- return hasAward(OLYMPUS_GUILD_MEMBER);
+ } else {
+ return hasAward(party._mazeId - 28);
}
}
@@ -881,6 +968,7 @@ int Character::getNumAwards() const {
ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
XeenEngine *vm = Party::_vm;
Scripts &scripts = *vm->_scripts;
+ int itemOffset = vm->getGameID() == GType_Swords ? 6 : 0;
if (!p1)
return CATEGORY_WEAPON;
@@ -889,22 +977,22 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
int v4 = vm->getRandomNumber(100);
int v6 = vm->getRandomNumber(p1 < 6 ? 100 : 80);
ItemCategory category;
- int v16 = 0, v14 = 0, miscBonus = 0, miscId = 0, v8 = 0, v12 = 0;
+ int v16 = 0, v14 = 0, miscCharges = 0, miscId = 0, v8 = 0, v12 = 0;
// Randomly pick a category and item Id
if (p3 == 12) {
- if (scripts._itemType < 35) {
+ if (scripts._itemType < (35 + itemOffset)) {
category = CATEGORY_WEAPON;
itemId = scripts._itemType;
- } else if (scripts._itemType < 49) {
+ } else if (scripts._itemType < (49 + itemOffset)) {
category = CATEGORY_ARMOR;
- itemId = scripts._itemType - 35;
- } else if (scripts._itemType < 60) {
+ itemId = scripts._itemType - (35 + itemOffset);
+ } else if (scripts._itemType < (60 + itemOffset)) {
category = CATEGORY_ACCESSORY;
- itemId = scripts._itemType - 49;
+ itemId = scripts._itemType - (49 + itemOffset);
} else {
category = CATEGORY_MISC;
- itemId = scripts._itemType - 60;
+ itemId = scripts._itemType - (60 + itemOffset);
}
} else {
switch (p3) {
@@ -1081,7 +1169,7 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
break;
case 4:
- miscBonus = vm->getRandomNumber(Res.MAKE_ITEM_ARR5[p1][0], Res.MAKE_ITEM_ARR5[p1][1]);
+ miscCharges = vm->getRandomNumber(Res.MAKE_ITEM_ARR5[p1][0], Res.MAKE_ITEM_ARR5[p1][1]);
break;
default:
@@ -1094,7 +1182,7 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
if (p1 != 1) {
newItem._material = (v14 ? v14 + 58 : 0) + (v16 ? v16 + 36 : 0) + v12;
if (vm->getRandomNumber(20) == 10)
- newItem._bonusFlags = vm->getRandomNumber(1, 6);
+ newItem._state._counter = vm->getRandomNumber(1, 6);
}
break;
@@ -1107,7 +1195,7 @@ ItemCategory Character::makeItem(int p1, int itemIndex, int p3) {
case CATEGORY_MISC:
newItem._id = miscId;
- newItem._bonusFlags = miscBonus;
+ newItem._state._counter = miscCharges;
break;
default:
@@ -1134,6 +1222,7 @@ void Character::addHitPoints(int amount) {
intf.drawParty(true);
}
+ assert(_currentHp < 65000);
Common::fill(&intf._charFX[0], &intf._charFX[MAX_ACTIVE_PARTY], 0);
}
@@ -1147,7 +1236,8 @@ void Character::subtractHitPoints(int amount) {
// Subtract the given HP amount
_currentHp -= amount;
- bool flag = _currentHp <= 10;
+ bool breakFlag = _currentHp <= (g_vm->_extOptions._durableArmor ? -80 : -10);
+ assert(_currentHp < 65000);
if (_currentHp < 1) {
int v = getMaxHP() + _currentHp;
@@ -1156,17 +1246,17 @@ void Character::subtractHitPoints(int amount) {
sound.playFX(38);
} else {
_conditions[DEAD] = 1;
- flag = true;
+ breakFlag = true;
if (_currentHp > 0)
_currentHp = 0;
}
- if (flag) {
- // Check for breaking equipped armor
+ if (breakFlag) {
+ // Break any equipped armor the character has
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
XeenItem &item = _armor[idx];
if (item._id && item._frame)
- item._bonusFlags |= ITEMFLAG_BROKEN;
+ item._state._broken = true;
}
}
}
@@ -1174,7 +1264,7 @@ void Character::subtractHitPoints(int amount) {
bool Character::hasSlayerSword() const {
for (uint idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
- if (_weapons[idx]._id == 34)
+ if (_weapons[idx]._id == XEEN_SLAYER_SWORD)
// Character has Xeen Slayer sword
return true;
}
@@ -1192,18 +1282,22 @@ bool Character::hasMissileWeapon() const {
return false;
}
-int Character::getClassCategory() const {
+SpellsCategory Character::getSpellsCategory() const {
switch (_class) {
+ case CLASS_PALADIN:
+ case CLASS_CLERIC:
+ return SPELLCAT_CLERICAL;
+
case CLASS_ARCHER:
case CLASS_SORCERER:
- return 1;
+ return SPELLCAT_WIZARDRY;
case CLASS_DRUID:
case CLASS_RANGER:
- return 2;
+ return SPELLCAT_DRUIDIC;
default:
- return 0;
+ return SPELLCAT_INVALID;
}
}
diff --git a/engines/xeen/character.h b/engines/xeen/character.h
index 05a61c3f2e..47312efe66 100644
--- a/engines/xeen/character.h
+++ b/engines/xeen/character.h
@@ -34,7 +34,7 @@
namespace Xeen {
#define INV_ITEMS_TOTAL 9
-#define MAX_SPELLS_PER_CLASS 39
+#define SPELLS_PER_CLASS 39
#define AWARDS_TOTAL 88
#define WARZONE_AWARD 9
@@ -44,10 +44,6 @@ enum Award {
LAKESIDE_GUILD_MEMBER = 85, NECROPOLIS_GUILD_MEMBER = 86, OLYMPUS_GUILD_MEMBER = 87
};
-enum BonusFlags {
- ITEMFLAG_BONUS_MASK = 0xBF, ITEMFLAG_CURSED = 0x40, ITEMFLAG_BROKEN = 0x80
-};
-
enum Sex { MALE = 0, FEMALE = 1, YES_PLEASE = 2 };
enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
@@ -55,7 +51,11 @@ enum Race { HUMAN = 0, ELF = 1, DWARF = 2, GNOME = 3, HALF_ORC = 4 };
enum CharacterClass {
CLASS_KNIGHT = 0, CLASS_PALADIN = 1, CLASS_ARCHER = 2, CLASS_CLERIC = 3,
CLASS_SORCERER = 4, CLASS_ROBBER = 5, CLASS_NINJA = 6, CLASS_BARBARIAN = 7,
- CLASS_DRUID = 8, CLASS_RANGER = 9, TOTAL_CLASSES = 10, CLASS_12 = 12, CLASS_15 = 15, CLASS_16 = 16
+ CLASS_DRUID = 8, CLASS_RANGER = 9, TOTAL_CLASSES = 10
+};
+
+enum HatesClass {
+ HATES_DWARF = 12, HATES_PARTY = 15, HATES_NOBODY = 16
};
enum Attribute {
@@ -83,6 +83,11 @@ enum QuickAction {
QUICK_ATTACK = 0, QUICK_SPELL = 1, QUICK_BLOCK = 2, QUICK_RUN = 3
};
+enum SpellsCategory {
+ SPELLCAT_INVALID = -1, SPELLCAT_CLERICAL = 0, SPELLCAT_WIZARDRY = 1, SPELLCAT_DRUIDIC = 2
+};
+
+
class XeenEngine;
class AttributePair {
@@ -119,17 +124,17 @@ public:
int _tempAge;
int _skills[18];
int _awards[128];
- bool _spells[MAX_SPELLS_PER_CLASS];
+ bool _spells[SPELLS_PER_CLASS];
int _lloydMap;
Common::Point _lloydPosition;
bool _hasSpells;
int8 _currentSpell;
QuickAction _quickOption;
- InventoryItemsGroup _items;
WeaponItems _weapons;
ArmorItems _armor;
AccessoryItems _accessories;
MiscItems _misc;
+ InventoryItemsGroup _items;
int _lloydSide;
AttributePair _fireResistence;
AttributePair _coldResistence;
@@ -150,14 +155,37 @@ public:
SpriteResource *_faceSprites;
int _rosterId;
public:
+ /**
+ * Constructor
+ */
Character();
/**
+ * Constructor
+ */
+ Character(const Character &src);
+
+ /**
+ * Equality operator
+ */
+ bool operator==(const Character &src) const { return src._rosterId == _rosterId; }
+
+ /**
+ * Inequality operator
+ */
+ bool operator!=(const Character &src) const { return src._rosterId != _rosterId; }
+
+ /**
* Clears the data for a character
*/
void clear();
/**
+ * Assignment operator
+ */
+ Character &operator=(const Character &src);
+
+ /**
* Synchronizes data for the character
*/
void synchronize(Common::Serializer &s);
@@ -311,9 +339,16 @@ public:
bool hasMissileWeapon() const;
/**
- * Returns a category index for a character, used such for indexing into spell data
+ * Returns the spells category for the character's class
*/
- int getClassCategory() const;
+ SpellsCategory getSpellsCategory() const;
+
+ /**
+ * Returns an expense factor for purchasing spells by certain character classes
+ */
+ int getSpellsExpenseFactor() const {
+ return (_class == CLASS_PALADIN || _class == CLASS_ARCHER || _class == CLASS_RANGER) ? 1 : 0;
+ }
/**
* Clears the character of any currently set conditions
@@ -321,6 +356,14 @@ public:
void clearConditions();
};
+class CharacterArray : public Common::Array<Character> {
+public:
+ /**
+ * Returns the index of a given character in the array
+ */
+ int indexOf(const Character &c);
+};
+
} // End of namespace Xeen
#endif /* XEEN_CHARACTER_H */
diff --git a/engines/xeen/combat.cpp b/engines/xeen/combat.cpp
index 603b6aef71..4dd2ac6e8a 100644
--- a/engines/xeen/combat.cpp
+++ b/engines/xeen/combat.cpp
@@ -114,6 +114,7 @@ Combat::Combat(XeenEngine *vm): _vm(vm), _missVoc("miss.voc") {
_monsterDamage = 0;
_weaponDamage = 0;
_weaponDie = _weaponDice = 0;
+ _weaponElemMaterial = 0;
_attackWeapon = nullptr;
_attackWeaponId = 0;
_hitChanceBonus = 0;
@@ -141,9 +142,8 @@ void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) {
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
Windows &windows = *_vm->_windows;
- int charIndex1 = charIndex + 1;
- int selectedIndex1 = 0;
- int selectedIndex2 = 0;
+ int endIndex = charIndex + 1;
+ int selectedIndex = 0;
bool breakFlag = false;
windows.closeAll();
@@ -155,11 +155,11 @@ void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) {
Condition condition = c.worstCondition();
if (!(condition >= UNCONSCIOUS && condition <= ERADICATED)) {
- if (!selectedIndex1) {
- selectedIndex1 = idx + 1;
+ if (!charIndex) {
+ charIndex = idx + 1;
} else {
- selectedIndex2 = idx + 1;
- --selectedIndex1;
+ selectedIndex = idx + 1;
+ --charIndex;
break;
}
}
@@ -167,12 +167,12 @@ void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) {
}
if (idx == (int)party._activeParty.size()) {
if (!_combatTarget)
- selectedIndex1 = 0;
+ charIndex = 0;
}
for (;;) {
- for (; selectedIndex1 < (_combatTarget ? charIndex1 : (int)party._activeParty.size()); ++selectedIndex1) {
- Character &c = party._activeParty[selectedIndex1];
+ for (; charIndex < (_combatTarget ? endIndex : (int)party._activeParty.size()); ++charIndex) {
+ Character &c = party._activeParty[charIndex];
c._conditions[ASLEEP] = 0; // Force attacked character to be awake
int frame = 0, fx = 0;
@@ -224,7 +224,7 @@ void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) {
// Draw the attack effect on the character sprite
sound.playFX(fx);
- intf._charPowSprites.draw(0, frame, Common::Point(Res.CHAR_FACES_X[selectedIndex1], 150));
+ intf._charPowSprites.draw(0, frame, Common::Point(Res.CHAR_FACES_X[charIndex], 150));
windows[33].update();
// Reduce damage if power shield active, and set it zero
@@ -235,7 +235,6 @@ void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) {
if (damage < 0)
damage = 0;
- // Attacked characters which are asleep are killed
if (attackType == DT_SLEEP) {
damage = c._currentHp;
c._conditions[DEAD] = 1;
@@ -243,15 +242,15 @@ void Combat::giveCharDamage(int damage, DamageType attackType, int charIndex) {
// Subtract the hit points from the character
c.subtractHitPoints(damage);
- if (selectedIndex2)
+ if (selectedIndex)
break;
}
// Break check and if not, move to other index
- if (!selectedIndex2 || breakFlag)
+ if (!selectedIndex || breakFlag)
break;
- selectedIndex1 = selectedIndex2 - 1;
+ charIndex = selectedIndex - 1;
breakFlag = true;
}
@@ -325,7 +324,7 @@ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) {
intf._charPowSprites.draw(0, frame, Common::Point(Res.CHAR_FACES_X[charNum], 150));
windows[33].update();
- damage -= party._powerShield;
+ damage = MAX(damage - party._powerShield, 0);
if (damage > 0 && monsterData._specialAttack && !c.charSavingThrow(DT_PHYSICAL)) {
switch (monsterData._specialAttack) {
case SA_POISON:
@@ -349,13 +348,7 @@ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) {
sound.playFX(36);
break;
case SA_CURSEITEM:
- for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
- if (c._weapons[idx]._id != 34)
- c._weapons[idx]._bonusFlags |= ITEMFLAG_CURSED;
- c._armor[idx]._bonusFlags |= ITEMFLAG_CURSED;
- c._accessories[idx]._bonusFlags |= ITEMFLAG_CURSED;
- c._misc[idx]._bonusFlags |= ITEMFLAG_CURSED;
- }
+ c._items.curseUncurse(true);
sound.playFX(37);
break;
case SA_DRAINSP:
@@ -385,8 +378,8 @@ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) {
case SA_BREAKWEAPON:
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
XeenItem &weapon = c._weapons[idx];
- if (weapon._id != 34 && weapon._id != 0 && weapon._frame != 0) {
- weapon._bonusFlags |= ITEMFLAG_BROKEN;
+ if (weapon._id < XEEN_SLAYER_SWORD && weapon._id != 0 && weapon._frame != 0) {
+ weapon._state._broken = true;
weapon._frame = 0;
}
}
@@ -428,15 +421,15 @@ void Combat::doCharDamage(Character &c, int charNum, int monsterDataIndex) {
default:
break;
}
-
- if (debugger._invincible)
- // Invincibility mode is on, so reset conditions that were set
- c.clearConditions();
- else
- // Standard gameplay, deal out the damage
- c.subtractHitPoints(damage);
}
+ if (debugger._invincible)
+ // Invincibility mode is on, so reset conditions that were set
+ c.clearConditions();
+ else
+ // Standard gameplay, deal out the damage
+ c.subtractHitPoints(damage);
+
events.ipause(2);
intf.drawParty(true);
}
@@ -461,7 +454,9 @@ void Combat::moveMonsters() {
for (uint idx = 0; idx < map._mobData._monsters.size(); ++idx) {
MazeMonster &monster = map._mobData._monsters[idx];
- if ((uint)monster._position.y < 32) {
+
+ // WORKAROUND: Original only checked on y, but some monsters have an invalid X instead
+ if ((uint)monster._position.x < 32 && (uint)monster._position.y < 32) {
assert((uint)monster._position.x < 32);
_monsterMap[monster._position.y][monster._position.x]++;
}
@@ -496,12 +491,12 @@ void Combat::moveMonsters() {
switch (party._mazeDirection) {
case DIR_NORTH:
case DIR_SOUTH:
- if (monsterCanMove(pt, Res.MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
+ if (canMonsterMove(pt, Res.MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) {
// Move the monster
moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex]));
} else {
- if (monsterCanMove(pt, Res.MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
+ if (canMonsterMove(pt, Res.MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0,
arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex],
idx)) {
@@ -516,7 +511,7 @@ void Combat::moveMonsters() {
case DIR_EAST:
case DIR_WEST:
- if (monsterCanMove(pt, Res.MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
+ if (canMonsterMove(pt, Res.MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX2[arrIndex]],
arrIndex >= 21 && arrIndex <= 27 ? MONSTER_GRID3[arrIndex] : 0,
arrIndex >= 21 && arrIndex <= 27 ? 0 : MONSTER_GRID3[arrIndex],
idx)) {
@@ -525,7 +520,7 @@ void Combat::moveMonsters() {
} else {
moveMonster(idx, Common::Point(0, MONSTER_GRID3[arrIndex]));
}
- } else if (monsterCanMove(pt, Res.MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
+ } else if (canMonsterMove(pt, Res.MONSTER_GRID_BITMASK[MONSTER_GRID_BITINDEX1[arrIndex]],
MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex], idx)) {
moveMonster(idx, Common::Point(MONSTER_GRID_X[arrIndex], MONSTER_GRID_Y[arrIndex]));
}
@@ -638,12 +633,12 @@ void Combat::monstersAttack() {
_monstersAttacking = false;
- if (_vm->_mode != MODE_SLEEPING) {
+ if (_vm->_mode == MODE_SLEEPING) {
for (uint charNum = 0; charNum < party._activeParty.size(); ++charNum) {
Condition condition = party._activeParty[charNum].worstCondition();
- if (condition != ASLEEP && (condition < PARALYZED || condition == NO_CONDITION)) {
- _vm->_mode = MODE_1;
+ if (condition == DEPRESSED || condition == CONFUSED || condition == NO_CONDITION) {
+ _vm->_mode = MODE_INTERACTIVE;
break;
}
}
@@ -675,8 +670,7 @@ void Combat::setupMonsterAttack(int monsterDataIndex, const Common::Point &pt) {
}
}
-bool Combat::monsterCanMove(const Common::Point &pt, int wallShift,
- int xDiff, int yDiff, int monsterId) {
+bool Combat::canMonsterMove(const Common::Point &pt, int wallShift, int xDiff, int yDiff, int monsterId) {
Map &map = *_vm->_map;
MazeMonster &monster = map._mobData._monsters[monsterId];
MonsterStruct &monsterData = *monster._monsterData;
@@ -709,7 +703,7 @@ bool Combat::monsterCanMove(const Common::Point &pt, int wallShift,
} else if (surfaceType == SURFTYPE_SPACE) {
return monsterData._flying;
} else {
- return _vm->_files->_isDarkCc || monster._spriteId != 59;
+ return _vm->_files->_ccNum || monster._spriteId != 59;
}
default:
return v <= map.mazeData()._difficulties._wallNoPass;
@@ -722,6 +716,10 @@ void Combat::moveMonster(int monsterId, const Common::Point &moveDelta) {
MazeMonster &monster = map._mobData._monsters[monsterId];
Common::Point newPos = monster._position + moveDelta;
+ // FIXME: Monster moved outside mapping area. Which shouldn't happen, so ignore the move if it does
+ if ((uint)newPos.x >= 32 || (uint)newPos.y >= 32)
+ return;
+
if (_monsterMap[newPos.y][newPos.x] < 3 && monster._damageType == DT_PHYSICAL && _moveMonsters) {
// Adjust monster's position
++_monsterMap[newPos.y][newPos.x];
@@ -819,15 +817,20 @@ void Combat::doMonsterTurn(int monsterId) {
}
MonsterStruct &monsterData = map._monsterData[monsterId];
- bool flag = false;
for (int attackNum = 0; attackNum < monsterData._numberOfAttacks; ++attackNum) {
int charNum = -1;
bool isHated = false;
- if (monsterData._hatesClass != -1) {
- if (monsterData._hatesClass == 15)
- // Monster hates all classes
- goto loop;
+ if (monsterData._hatesClass != CLASS_PALADIN) {
+ if (monsterData._hatesClass == HATES_PARTY) {
+ // Monster hates entire party, even the disabled/dead
+ for (uint idx = 0; idx < _combatParty.size(); ++idx) {
+ doMonsterTurn(monsterId, idx);
+ }
+
+ // Move onto monster's next attack (if any)
+ continue;
+ }
for (uint charIndex = 0; charIndex < _combatParty.size(); ++charIndex) {
Character &c = *_combatParty[charIndex];
@@ -835,10 +838,8 @@ void Combat::doMonsterTurn(int monsterId) {
if (cond >= PARALYZED && cond <= ERADICATED)
continue;
- isHated = false;
switch (monsterData._hatesClass) {
case CLASS_KNIGHT:
- case CLASS_PALADIN:
case CLASS_ARCHER:
case CLASS_CLERIC:
case CLASS_SORCERER:
@@ -849,7 +850,7 @@ void Combat::doMonsterTurn(int monsterId) {
case CLASS_RANGER:
isHated = c._class == monsterData._hatesClass;
break;
- case 12:
+ case HATES_DWARF:
isHated = c._race == DWARF;
break;
default:
@@ -864,102 +865,78 @@ void Combat::doMonsterTurn(int monsterId) {
}
if (!isHated) {
- // No particularly hated foe, so decide which character to start with
- switch (_combatParty.size()) {
- case 1:
- charNum = 0;
- break;
- case 2:
- case 3:
- case 4:
- case 5:
- charNum = _vm->getRandomNumber(0, _combatParty.size() - 1);
- break;
- case 6:
- if (_vm->getRandomNumber(1, 6) == 6)
- charNum = 5;
- else
- charNum = _vm->getRandomNumber(0, 4);
- break;
- }
+ // No particularly hated foe, so pick a random character to start with
+ // Note: Original had a whole switch statement depending on party size, that boiled down to
+ // picking a random character in all cases anyway
+ charNum = _vm->getRandomNumber(0, _combatParty.size() - 1);
}
- // Attacking loop
- do {
- if (!flag) {
- Condition cond = _combatParty[charNum]->worstCondition();
-
- if (cond >= PARALYZED && cond <= ERADICATED) {
- Common::Array<int> ableChars;
- bool skip = false;
-
- for (uint idx = 0; idx < _combatParty.size() && !skip; ++idx) {
- switch (_combatParty[idx]->worstCondition()) {
- case PARALYZED:
- case UNCONSCIOUS:
- //if (flag)
- // skip = true;
- break;
- case DEAD:
- case STONED:
- case ERADICATED:
- break;
- default:
- ableChars.push_back(idx);
- break;
- }
- }
-
- if (!skip) {
- if (ableChars.size() == 0) {
- party._dead = true;
- _vm->_mode = MODE_1;
- return;
- }
-
- charNum = ableChars[_vm->getRandomNumber(0, ableChars.size() - 1)];
- }
+ // If the chosen character is already disabled, we need to pick a still able body character
+ // from the remainder of the combat party
+ Condition cond = _combatParty[charNum]->worstCondition();
+ if (cond >= PARALYZED && cond <= ERADICATED) {
+ Common::Array<int> ableChars;
+
+ for (uint idx = 0; idx < _combatParty.size(); ++idx) {
+ switch (_combatParty[idx]->worstCondition()) {
+ case PARALYZED:
+ case UNCONSCIOUS:
+ case DEAD:
+ case STONED:
+ case ERADICATED:
+ break;
+ default:
+ ableChars.push_back(idx);
+ break;
}
}
- // Unconditional if to get around goto initialization errors
- if (true) {
- Character &c = *_combatParty[charNum];
- if (monsterData._attackType != DT_PHYSICAL || c._conditions[ASLEEP]) {
- doCharDamage(c, charNum, monsterId);
- } else {
- int v = _vm->getRandomNumber(1, 20);
- if (v == 1) {
- // Critical Save
- sound.playFX(6);
- } else {
- if (v == 20)
- // Critical failure
- doCharDamage(c, charNum, monsterId);
- v += monsterData._hitChance / 4 + _vm->getRandomNumber(1,
- monsterData._hitChance);
-
- int ac = c.getArmorClass() + (!_charsBlocked[charNum] ? 10 :
- c.getCurrentLevel() / 2 + 15);
- if (ac > v) {
- sound.playFX(6);
- } else {
- doCharDamage(c, charNum, monsterId);
- }
- }
- }
-
- if (flag)
- break;
+ if (ableChars.size() == 0) {
+ party._dead = true;
+ _vm->_mode = MODE_INTERACTIVE;
+ return;
}
-loop:
- flag = true;
- } while (++charNum < (int)_combatParty.size());
+
+ charNum = ableChars[_vm->getRandomNumber(0, ableChars.size() - 1)];
+ }
+
+ doMonsterTurn(monsterId, charNum);
}
intf.drawParty(true);
}
+void Combat::doMonsterTurn(int monsterId, int charNum) {
+ Map &map = *_vm->_map;
+ Sound &sound = *_vm->_sound;
+ MonsterStruct &monsterData = map._monsterData[monsterId];
+ Character &c = *_combatParty[charNum];
+
+ if (monsterData._attackType != DT_PHYSICAL || c._conditions[ASLEEP]) {
+ doCharDamage(c, charNum, monsterId);
+ } else {
+ int v = _vm->getRandomNumber(1, 20);
+ if (v == 1) {
+ // Critical Save
+ sound.playFX(6);
+ } else {
+ if (v == 20)
+ // Critical failure
+ doCharDamage(c, charNum, monsterId);
+ v += monsterData._hitChance / 4 + _vm->getRandomNumber(1,
+ monsterData._hitChance);
+
+ int ac = c.getArmorClass() + (!_charsBlocked[charNum] ? 10 :
+ c.getCurrentLevel() / 2 + 15);
+ if (ac > v) {
+ sound.playFX(6);
+ } else {
+ doCharDamage(c, charNum, monsterId);
+ }
+ }
+ }
+}
+
int Combat::stopAttack(const Common::Point &diffPt) {
Map &map = *_vm->_map;
Party &party = *_vm->_party;
@@ -1083,7 +1060,7 @@ void Combat::setSpeedTable() {
bool hasSpeed = _whosSpeed != -1;
int oldSpeed = hasSpeed && _whosSpeed < (int)_speedTable.size() ? _speedTable[_whosSpeed] : 0;
- // Set up speeds for party membres
+ // Set up speeds for party members
int maxSpeed = 0;
for (uint charNum = 0; charNum < _combatParty.size(); ++charNum) {
Character &c = *_combatParty[charNum];
@@ -1108,7 +1085,7 @@ void Combat::setSpeedTable() {
// Populate the _speedTable list with the character/monster indexes
// in order of attacking speed
_speedTable.clear();
- for (; maxSpeed >= 0; --maxSpeed) {
+ for (; maxSpeed > 0; --maxSpeed) {
for (uint idx = 0; idx < charSpeeds.size(); ++idx) {
if (charSpeeds[idx] == maxSpeed)
_speedTable.push_back(idx);
@@ -1116,8 +1093,10 @@ void Combat::setSpeedTable() {
}
if (hasSpeed) {
- if (_speedTable[_whosSpeed] != oldSpeed) {
- for (_whosSpeed = 0; _whosSpeed < (int)charSpeeds.size(); ++_whosSpeed) {
+ if (_speedTable.empty()) {
+ _whosSpeed = 0;
+ } else if (_whosSpeed >= (int)_speedTable.size() || _speedTable[_whosSpeed] != oldSpeed) {
+ for (_whosSpeed = 0; _whosSpeed < (int)_speedTable.size(); ++_whosSpeed) {
if (oldSpeed == _speedTable[_whosSpeed])
break;
}
@@ -1350,32 +1329,34 @@ void Combat::attack(Character &c, RangeType rangeType) {
for (int itemIndex = 0; itemIndex < INV_ITEMS_TOTAL; ++itemIndex) {
XeenItem &weapon = c._weapons[itemIndex];
- if (weapon._frame != 0) {
- switch (weapon._bonusFlags & ITEMFLAG_BONUS_MASK) {
- case 1:
+ if (weapon.isEquipped()) {
+ switch (weapon._state._counter) {
+ case EFFECTIVE_DRAGON:
if (monsterData._monsterType == MONSTER_DRAGON)
damage *= 3;
break;
- case 2:
+ case EFFECTIVE_UNDEAD :
if (monsterData._monsterType == MONSTER_UNDEAD)
damage *= 3;
break;
- case 3:
+ case EFFECTIVE_GOLEM:
if (monsterData._monsterType == MONSTER_GOLEM)
damage *= 3;
break;
- case 4:
+ case EFFECTIVE_INSECT:
if (monsterData._monsterType == MONSTER_INSECT)
damage *= 3;
break;
- case 5:
- if (monsterData._monsterType == MONSTER_0)
+ case EFFEctIVE_MONSTERS:
+ if (monsterData._monsterType == MONSTER_MONSTERS)
damage *= 3;
break;
- case 6:
+ case EFFECTIVE_ANIMAL:
if (monsterData._monsterType == MONSTER_ANIMAL)
damage *= 3;
break;
+ default:
+ break;
}
}
}
@@ -1387,28 +1368,31 @@ void Combat::attack(Character &c, RangeType rangeType) {
}
void Combat::attack2(int damage, RangeType rangeType) {
+ Debugger &debugger = *_vm->_debugger;
Interface &intf = *_vm->_interface;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
- bool isDarkCc = _vm->_files->_isDarkCc;
+ int ccNum = _vm->_files->_ccNum;
MazeMonster &monster = map._mobData._monsters[_monster2Attack];
MonsterStruct &monsterData = *monster._monsterData;
bool monsterDied = false;
- if (!isDarkCc && damage && rangeType != RT_SINGLE && monster._spriteId == 89)
+ if (!ccNum && damage && rangeType != RT_SINGLE && monster._spriteId == 89)
damage = 0;
+ if (debugger._superStrength)
+ damage = 10000;
if (!damage) {
sound.playSound(_missVoc, 1);
sound.playFX(6);
} else {
- if (!isDarkCc && monster._spriteId == 89)
+ if (!ccNum && monster._spriteId == 89)
damage += 100;
if (monster._damageType == DT_SLEEP || monster._damageType == DT_DRAGONSLEEP)
monster._damageType = DT_PHYSICAL;
- if ((rangeType == RT_SINGLE || _damageType == DT_PHYSICAL) && _attackWeaponId != 34) {
+ if ((rangeType == RT_SINGLE || _damageType == DT_PHYSICAL) && _attackWeaponId < XEEN_SLAYER_SWORD) {
if (monsterData._phsyicalResistence != 0) {
if (monsterData._phsyicalResistence == 100) {
// Completely immune to the damage
@@ -1430,7 +1414,7 @@ void Combat::attack2(int damage, RangeType rangeType) {
int monsterResist = getMonsterResistence(rangeType);
damage += monsterResist;
if (monsterResist > 0) {
- _pow[_attackDurationCtr]._elemFrame = _attackWeapon->getElementalCategory();
+ _pow[_attackDurationCtr]._elemFrame = XeenItem::getElementalCategory(_weaponElemMaterial);
_pow[_attackDurationCtr]._elemScale = getDamageScale(monsterResist);
} else if (rangeType != RT_HIT) {
_pow[_attackDurationCtr]._elemFrame = 0;
@@ -1471,9 +1455,9 @@ void Combat::attack2(int damage, RangeType rangeType) {
intf.draw3d(true);
sound.stopSound();
- File powVoc(Common::String::format("pow%d.voc",
- POW_WEAPON_VOCS[_attackWeaponId]));
- sound.playFX(60 + POW_WEAPON_VOCS[_attackWeaponId]);
+ int powNum = (_attackWeaponId > XEEN_SLAYER_SWORD) ? 0 : POW_WEAPON_VOCS[_attackWeaponId];
+ File powVoc(Common::String::format("pow%d.voc", powNum));
+ sound.playFX(60 + powNum);
sound.playSound(powVoc, 1);
if (monster._hp > damage) {
@@ -1488,12 +1472,12 @@ void Combat::attack2(int damage, RangeType rangeType) {
intf.draw3d(true);
if (monsterDied) {
- if (!isDarkCc) {
+ if (!ccNum) {
if (_monster2Attack == 20 && party._mazeId == 41)
party._gameFlags[0][11] = true;
if (_monster2Attack == 8 && party._mazeId == 78) {
party._gameFlags[0][60] = true;
- party._questFlags[0][23] = false;
+ party._questFlags[23] = false;
for (uint idx = 0; idx < party._activeParty.size(); ++idx)
party._activeParty[idx].setAward(42, true);
@@ -1506,14 +1490,14 @@ void Combat::attack2(int damage, RangeType rangeType) {
giveExperience(monsterData._experience);
if (party._mazeId != 85) {
- party._treasure._gold = monsterData._gold;
- party._treasure._gems = monsterData._gems;
+ party._treasure._gold += monsterData._gold;
+ party._treasure._gems += monsterData._gems;
- if (!isDarkCc && monster._spriteId == 89) {
+ if (!ccNum && monster._spriteId == 89) {
// Xeen's Scepter of Temporal Distortion
party._treasure._weapons[0]._id = 90;
- party._treasure._weapons[0]._bonusFlags = 0;
party._treasure._weapons[0]._material = 0;
+ party._treasure._weapons[0]._state.clear();
party._treasure._hasItems = true;
party._questItems[8]++;
}
@@ -1527,7 +1511,7 @@ void Combat::attack2(int damage, RangeType rangeType) {
switch (category) {
case CATEGORY_WEAPON:
for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- if (party._treasure._weapons[idx]._id == 0) {
+ if (party._treasure._weapons[idx].empty()) {
party._treasure._weapons[idx] = tempChar._weapons[0];
party._treasure._hasItems = true;
break;
@@ -1536,7 +1520,7 @@ void Combat::attack2(int damage, RangeType rangeType) {
break;
case CATEGORY_ARMOR:
for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- if (party._treasure._armor[idx]._id == 0) {
+ if (party._treasure._armor[idx].empty()) {
party._treasure._armor[idx] = tempChar._armor[0];
party._treasure._hasItems = true;
break;
@@ -1545,7 +1529,7 @@ void Combat::attack2(int damage, RangeType rangeType) {
break;
case CATEGORY_ACCESSORY:
for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- if (party._treasure._accessories[idx]._id == 0) {
+ if (party._treasure._accessories[idx].empty()) {
party._treasure._accessories[idx] = tempChar._accessories[0];
party._treasure._hasItems = true;
break;
@@ -1554,7 +1538,7 @@ void Combat::attack2(int damage, RangeType rangeType) {
break;
case CATEGORY_MISC:
for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- if (party._treasure._accessories[idx]._id == 0) {
+ if (party._treasure._accessories[idx].empty()) {
party._treasure._accessories[idx] = tempChar._accessories[0];
party._treasure._hasItems = true;
break;
@@ -1592,7 +1576,7 @@ void Combat::quickFight() {
break;
case QUICK_SPELL:
if (c->_currentSpell != -1) {
- spells.castSpell(c, (MagicSpell)Res.SPELLS_ALLOWED[c->getClassCategory()][c->_currentSpell]);
+ spells.castSpell(c, (MagicSpell)Res.SPELLS_ALLOWED[c->getSpellsCategory()][c->_currentSpell]);
}
break;
case QUICK_BLOCK:
@@ -1676,6 +1660,7 @@ void Combat::getWeaponDamage(Character &c, RangeType rangeType) {
_weaponDie = _weaponDice = 0;
_weaponDamage = 0;
_hitChanceBonus = 0;
+ _weaponElemMaterial = 0;
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
XeenItem &weapon = c._weapons[idx];
@@ -1687,10 +1672,12 @@ void Combat::getWeaponDamage(Character &c, RangeType rangeType) {
}
if (flag) {
- if (!(weapon._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) {
+ if (!weapon.isBad()) {
_attackWeapon = &weapon;
- if (weapon._material >= 37 && weapon._material < 59) {
+ if (weapon._material < 37) {
+ _weaponElemMaterial = weapon._material;
+ } else if (weapon._material < 59) {
_hitChanceBonus = Res.METAL_DAMAGE_PERCENT[weapon._material - 37];
_weaponDamage = Res.METAL_DAMAGE[weapon._material - 37];
}
@@ -1761,7 +1748,7 @@ int Combat::getMonsterResistence(RangeType rangeType) {
break;
}
} else {
- int material = !_attackWeapon ? 0 : _attackWeapon->_material;
+ int material = _weaponElemMaterial;
damage = Res.ELEMENTAL_DAMAGE[material];
if (material != 0) {
@@ -1869,7 +1856,7 @@ void Combat::rangedAttack(PowType powNum) {
_attackDurationCtr = -1;
if (_monster2Attack != -1) {
- _attackDurationCtr--;
+ _attackDurationCtr = attackDurationCtr - 1;
if (attackMonsters.empty())
attackMonsters.resize(1);
attackMonsters[0] = monster2Attack;
@@ -2098,4 +2085,21 @@ void Combat::shootRangedWeapon() {
rangedAttack(POW_ARROW);
}
+bool Combat::areMonstersPresent() const {
+ for (int idx = 0; idx < 26; ++idx) {
+ if (_attackMonsters[idx] != -1)
+ return true;
+ }
+
+ return false;
+}
+
+void Combat::reset() {
+ clearShooting();
+ setupCombatParty();
+
+ _combatMode = COMBATMODE_INTERACTIVE;
+ _monster2Attack = -1;
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/combat.h b/engines/xeen/combat.h
index 938845b022..e1a02c0759 100644
--- a/engines/xeen/combat.h
+++ b/engines/xeen/combat.h
@@ -58,7 +58,7 @@ enum ShootType {
};
enum CombatMode {
- COMBATMODE_STARTUP = 0, COMBATMODE_1 = 1, COMBATMODE_2 = 2
+ COMBATMODE_STARTUP = 0, COMBATMODE_INTERACTIVE = 1, COMBATMODE_2 = 2
};
enum PowType {
@@ -77,6 +77,7 @@ enum RangeType {
class XeenEngine;
class Character;
class XeenItem;
+class MonsterStruct;
struct PowSlot {
bool _active;
@@ -151,7 +152,7 @@ private:
public:
Common::Array<Character *> _combatParty;
bool _charsBlocked[PARTY_AND_MONSTERS];
- Common::Array<int> _charsGone;
+ int _charsGone[PARTY_AND_MONSTERS];
SpriteResource _powSprites;
int _attackMonsters[ATTACK_MONSTERS_COUNT];
int _monster2Attack;
@@ -176,6 +177,7 @@ public:
int _monsterDamage;
int _weaponDamage;
int _weaponDie, _weaponDice;
+ int _weaponElemMaterial;
XeenItem *_attackWeapon;
int _attackWeaponId;
File _missVoc;
@@ -204,6 +206,11 @@ public:
void clearShooting();
/**
+ * Resets all combat related data
+ */
+ void reset();
+
+ /**
* Gives damage to character or characters in the party
*/
void giveCharDamage(int damage, DamageType attackType, int charIndex);
@@ -272,18 +279,30 @@ public:
/**
* Determines whether a given monster can move
+ * @param pt Monster position
+ * @param wallShift Shift mask for determining direction being moved
+ * @param xDiff X Delta for move
+ * @param yDiff Y Delta for move
+ * @param monsterId Monster number being tested
*/
- bool monsterCanMove(const Common::Point &pt, int wallShift,
- int v1, int v2, int monsterId);
+ bool canMonsterMove(const Common::Point &pt, int wallShift, int xDiff, int yDiff, int monsterId);
/**
* Moves a monster by a given delta amount if it's a valid move
*/
void moveMonster(int monsterId, const Common::Point &moveDelta);
+ /**
+ * Handle a monster's turn at attacking combat party members
+ */
void doMonsterTurn(int monsterId);
/**
+ * Handles a monster's turn at attacking a specific member of the combat party
+ */
+ void doMonsterTurn(int monsterId, int charNum);
+
+ /**
* Called when combat has ended
*/
void endAttack();
@@ -304,6 +323,11 @@ public:
* Fires off a ranged attack at all oncoming monsters
*/
void shootRangedWeapon();
+
+ /**
+ * Returns true if there are any monsters in the vacinity
+ */
+ bool areMonstersPresent() const;
};
} // End of namespace Xeen
diff --git a/engines/xeen/configure.engine b/engines/xeen/configure.engine
index 489254f269..6907bde982 100644
--- a/engines/xeen/configure.engine
+++ b/engines/xeen/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 xeen "World of Xeen" no
+add_engine xeen "World of Xeen" yes
diff --git a/engines/xeen/debugger.cpp b/engines/xeen/debugger.cpp
index 42f61b02b5..7d8f170129 100644
--- a/engines/xeen/debugger.cpp
+++ b/engines/xeen/debugger.cpp
@@ -45,7 +45,7 @@ static int strToInt(const char *s) {
/*------------------------------------------------------------------------*/
Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm),
- _invincible(false) {
+ _spellId(-1), _invincible(false), _intangible(false), _superStrength(false) {
registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
registerCmd("spell", WRAP_METHOD(Debugger, cmdSpell));
registerCmd("spells", WRAP_METHOD(Debugger, cmdSpells));
@@ -55,8 +55,8 @@ Debugger::Debugger(XeenEngine *vm) : GUI::Debugger(), _vm(vm),
registerCmd("map", WRAP_METHOD(Debugger, cmdMap));
registerCmd("pos", WRAP_METHOD(Debugger, cmdPos));
registerCmd("invincible", WRAP_METHOD(Debugger, cmdInvincible));
-
- _spellId = -1;
+ registerCmd("strength", WRAP_METHOD(Debugger, cmdSuperStrength));
+ registerCmd("intangible", WRAP_METHOD(Debugger, cmdIntangible));
}
void Debugger::update() {
@@ -95,7 +95,7 @@ bool Debugger::cmdSpells(int argc, const char **argv) {
for (uint charIdx = 0; charIdx < party._activeParty.size(); ++charIdx) {
Character &c = party._activeParty[charIdx];
- Common::fill(c._spells, c._spells + MAX_SPELLS_PER_CLASS, true);
+ Common::fill(c._spells, c._spells + SPELLS_PER_CLASS, true);
c._currentSp = 9999;
}
@@ -160,20 +160,19 @@ bool Debugger::cmdGems(int argc, const char **argv) {
}
bool Debugger::cmdMap(int argc, const char **argv) {
- FileManager &files = *g_vm->_files;
Map &map = *g_vm->_map;
Party &party = *g_vm->_party;
if (argc < 2) {
- debugPrintf("map mapId [ sideNum [ xp, yp ]]\n");
+ debugPrintf("map mapId [ xp, yp ] [ sideNum ]\n");
return true;
} else {
int mapId = strToInt(argv[1]);
- bool side = argc < 3 ? files._isDarkCc : strToInt(argv[2]) != 0;
- int x = argc < 4 ? 8 : strToInt(argv[3]);
- int y = argc < 5 ? 8 : strToInt(argv[4]);
+ int x = argc < 3 ? 8 : strToInt(argv[2]);
+ int y = argc < 4 ? 8 : strToInt(argv[3]);
- map._loadDarkSide = side;
+ if (argc == 5)
+ map._loadCcNum = strToInt(argv[4]);
map.load(mapId);
party._mazePosition.x = x;
party._mazePosition.y = y;
@@ -202,4 +201,16 @@ bool Debugger::cmdInvincible(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdSuperStrength(int argc, const char **argv) {
+ _superStrength = (argc < 2) || strcmp(argv[1], "off");
+ debugPrintf("Super-powered attacks are %s\n", _superStrength ? "on" : "off");
+ return true;
+}
+
+bool Debugger::cmdIntangible(int argc, const char **argv) {
+ _intangible = (argc < 2) || strcmp(argv[1], "off");
+ debugPrintf("Intangibility is %s\n", _intangible ? "on" : "off");
+ return true;
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/debugger.h b/engines/xeen/debugger.h
index b7e1f1c325..48eb8f35f6 100644
--- a/engines/xeen/debugger.h
+++ b/engines/xeen/debugger.h
@@ -74,8 +74,20 @@ private:
* Flags whether to make the party invincible
*/
bool cmdInvincible(int argc, const char **argv);
+
+ /**
+ * Flags whether to make the party super-strength attacks
+ */
+ bool cmdSuperStrength(int argc, const char **argv);
+
+ /**
+ * Flags whether to make the party invincible
+ */
+ bool cmdIntangible(int argc, const char **argv);
public:
bool _invincible;
+ bool _intangible;
+ bool _superStrength;
public:
Debugger(XeenEngine *vm);
diff --git a/engines/xeen/detection.cpp b/engines/xeen/detection.cpp
index cf033b632f..8a5e096220 100644
--- a/engines/xeen/detection.cpp
+++ b/engines/xeen/detection.cpp
@@ -28,6 +28,7 @@
#include "common/savefile.h"
#include "engines/advancedDetector.h"
#include "common/system.h"
+#include "common/translation.h"
#define MAX_SAVES 99
@@ -60,6 +61,10 @@ Common::Platform XeenEngine::getPlatform() const {
return _gameDescription->desc.platform;
}
+bool XeenEngine::getIsCD() const {
+ return getFeatures() & ADGF_CD;
+}
+
} // End of namespace Xeen
static const PlainGameDescriptor XeenGames[] = {
@@ -71,11 +76,40 @@ static const PlainGameDescriptor XeenGames[] = {
{0, 0}
};
+#define GAMEOPTION_SHOW_ITEM_COSTS GUIO_GAMEOPTIONS1
+#define GAMEOPTION_DURABLE_ARMOR GUIO_GAMEOPTIONS2
+
#include "xeen/detection_tables.h"
+
+static const ADExtraGuiOptionsMap optionsList[] = {
+ {
+ GAMEOPTION_SHOW_ITEM_COSTS,
+ {
+ _s("Show item costs in standard inventory mode"),
+ _s("Shows item costs in standard inventory mode, allowing the value of items to be compared"),
+ "ShowItemCosts",
+ false
+ }
+ },
+
+ {
+ GAMEOPTION_DURABLE_ARMOR,
+ {
+ _s("More durable armor"),
+ _s("Armor won't break until character is at -80HP, rather than merely -10HP"),
+ "DurableArmor",
+ false
+ }
+ },
+
+ AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
class XeenMetaEngine : public AdvancedMetaEngine {
public:
- XeenMetaEngine() : AdvancedMetaEngine(Xeen::gameDescriptions, sizeof(Xeen::XeenGameDescription), XeenGames) {
+ XeenMetaEngine() : AdvancedMetaEngine(Xeen::gameDescriptions, sizeof(Xeen::XeenGameDescription),
+ XeenGames, optionsList) {
_maxScanDepth = 3;
}
@@ -137,32 +171,29 @@ SaveStateList XeenMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray filenames;
Common::String saveDesc;
- Common::String pattern = Common::String::format("%s.0??", target);
+ Common::String pattern = Common::String::format("%s.###", target);
Xeen::XeenSavegameHeader 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) {
const char *ext = strrchr(file->c_str(), '.');
int slot = ext ? atoi(ext + 1) : -1;
- if (slot >= 0 && slot < MAX_SAVES) {
+ if (slot >= 0 && slot <= MAX_SAVES) {
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
if (in) {
- Xeen::SavesManager::readSavegameHeader(in, header);
- saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+ if (Xeen::SavesManager::readSavegameHeader(in, header))
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
- if (header._thumbnail)
- header._thumbnail->free();
- delete header._thumbnail;
delete in;
}
}
}
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
return saveList;
}
@@ -181,7 +212,11 @@ SaveStateDescriptor XeenMetaEngine::querySaveMetaInfos(const char *target, int s
if (f) {
Xeen::XeenSavegameHeader header;
- Xeen::SavesManager::readSavegameHeader(f, header);
+ if (!Xeen::SavesManager::readSavegameHeader(f, header, false)) {
+ delete f;
+ return SaveStateDescriptor();
+ }
+
delete f;
// Create the return descriptor
diff --git a/engines/xeen/detection_tables.h b/engines/xeen/detection_tables.h
index c311bde202..fdb9dbd668 100644
--- a/engines/xeen/detection_tables.h
+++ b/engines/xeen/detection_tables.h
@@ -35,8 +35,8 @@ static const XeenGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO0()
+ ADGF_TESTING,
+ GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
},
GType_WorldOfXeen,
0
@@ -54,8 +54,8 @@ static const XeenGameDescription gameDescriptions[] = {
},
Common::DE_DEU,
Common::kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO0()
+ ADGF_UNSTABLE,
+ GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
},
GType_WorldOfXeen,
0
@@ -65,7 +65,7 @@ static const XeenGameDescription gameDescriptions[] = {
// World of Xeen (2 CD talkie version)
{
"worldofxeen",
- nullptr,
+ "CD",
{
{"xeen.cc", 0, "964078c53f649937ce9a1a3596ce3d9f", 13438429},
{"dark.cc", 0, "7f755ce39ea614fa6adb016f8bfc6e43", 11288403},
@@ -73,8 +73,8 @@ static const XeenGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO0()
+ ADGF_TESTING | ADGF_CD,
+ GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
},
GType_WorldOfXeen,
0
@@ -91,8 +91,8 @@ static const XeenGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO0()
+ ADGF_TESTING,
+ GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
},
GType_Clouds,
0
@@ -109,15 +109,15 @@ static const XeenGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO0()
+ ADGF_TESTING,
+ GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
},
GType_DarkSide,
0
},
{
- // Swords of Xeen (GOG)
+ // Swords of Xeen
{
"swordsofxeen",
nullptr,
@@ -127,8 +127,8 @@ static const XeenGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformDOS,
- ADGF_NO_FLAGS,
- GUIO0()
+ ADGF_TESTING,
+ GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
},
GType_Swords,
0
diff --git a/engines/xeen/dialogs/credits_screen.cpp b/engines/xeen/dialogs/credits_screen.cpp
index 09547ba282..d0269ad716 100644
--- a/engines/xeen/dialogs/credits_screen.cpp
+++ b/engines/xeen/dialogs/credits_screen.cpp
@@ -28,7 +28,7 @@ namespace Xeen {
void CreditsScreen::show(XeenEngine *vm) {
CreditsScreen *dlg = new CreditsScreen(vm);
-
+
switch (vm->getGameID()) {
case GType_Clouds:
dlg->execute(Res.CLOUDS_CREDITS);
@@ -41,7 +41,7 @@ void CreditsScreen::show(XeenEngine *vm) {
dlg->execute(Res.DARK_SIDE_CREDITS);
break;
}
-
+
delete dlg;
}
diff --git a/engines/xeen/dialogs/dialogs.cpp b/engines/xeen/dialogs/dialogs.cpp
index d7a696b8d5..d5c732e51a 100644
--- a/engines/xeen/dialogs/dialogs.cpp
+++ b/engines/xeen/dialogs/dialogs.cpp
@@ -66,48 +66,54 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) {
EventsManager &events = *vm->_events;
Party &party = *vm->_party;
Windows &windows = *_vm->_windows;
+ PendingEvent event;
_buttonValue = 0;
- if (events._leftButton) {
- Common::Point pt = events._mousePos;
-
- // Check for party member glyphs being clicked
- Common::Rect r(0, 0, 32, 32);
- for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
- r.moveTo(Res.CHAR_FACES_X[idx], 150);
- if (r.contains(pt)) {
- _buttonValue = Common::KEYCODE_F1 + idx;
- break;
+ if (events.getEvent(event)) {
+ if (event._leftButton) {
+ Common::Point pt = events._mousePos;
+
+ // Check for party member glyphs being clicked
+ Common::Rect r(0, 0, 32, 32);
+ for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
+ r.moveTo(Res.CHAR_FACES_X[idx], 150);
+ if (r.contains(pt)) {
+ _buttonValue = Common::KEYCODE_F1 + idx;
+ break;
+ }
}
- }
- // Check whether any button is selected
- for (uint i = 0; i < _buttons.size(); ++i) {
- if (_buttons[i]._bounds.contains(pt)) {
- events.debounceMouse();
+ // Check whether any button is selected
+ for (uint i = 0; i < _buttons.size(); ++i) {
+ if (_buttons[i]._bounds.contains(pt)) {
+ events.debounceMouse();
- _buttonValue = _buttons[i]._value;
- break;
+ _buttonValue = _buttons[i]._value;
+ break;
+ }
+ }
+
+ if (!_buttonValue && _waitBounds.contains(pt)) {
+ _buttonValue = Common::KEYCODE_SPACE;
+ return true;
}
- }
- if (!_buttonValue && Common::Rect(8, 8, 224, 135).contains(pt)) {
- _buttonValue = 1;
- return true;
+ } else if (event.isKeyboard()) {
+ const Common::KeyCode &keycode = event._keyState.keycode;
+
+ if (keycode == Common::KEYCODE_KP8)
+ _buttonValue = Common::KEYCODE_UP;
+ else if (keycode == Common::KEYCODE_KP2)
+ _buttonValue = Common::KEYCODE_DOWN;
+ else if (keycode == Common::KEYCODE_KP_ENTER)
+ _buttonValue = Common::KEYCODE_RETURN;
+ else if (keycode != Common::KEYCODE_LCTRL && keycode != Common::KEYCODE_RCTRL
+ && keycode != Common::KEYCODE_LALT && keycode != Common::KEYCODE_RALT)
+ _buttonValue = keycode;
+
+ if (_buttonValue)
+ _buttonValue |= (event._keyState.flags & ~Common::KBD_STICKY) << 16;
}
- } else if (events.isKeyPending()) {
- Common::KeyState keyState;
- events.getKey(keyState);
-
- _buttonValue = keyState.keycode;
- if (_buttonValue == Common::KEYCODE_KP8)
- _buttonValue = Common::KEYCODE_UP;
- else if (_buttonValue == Common::KEYCODE_KP2)
- _buttonValue = Common::KEYCODE_DOWN;
- else if (_buttonValue == Common::KEYCODE_KP_ENTER)
- _buttonValue = Common::KEYCODE_RETURN;
-
- _buttonValue |= (keyState.flags & ~Common::KBD_STICKY) << 16;
}
if (_buttonValue) {
@@ -118,8 +124,7 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) {
if (btn._draw && btn._value == _buttonValue) {
// Found the correct button
// Draw button depressed
- btn._sprites->draw(0, btn._frameNum + 1,
- Common::Point(btn._bounds.left, btn._bounds.top));
+ btn._sprites->draw(0, btn._selectedFrame, Common::Point(btn._bounds.left, btn._bounds.top));
win.setBounds(btn._bounds);
win.update();
@@ -128,8 +133,7 @@ bool ButtonContainer::checkEvents(XeenEngine *vm) {
events.wait(2);
// Redraw button in it's original non-depressed form
- btn._sprites->draw(0, btn._frameNum,
- Common::Point(btn._bounds.left, btn._bounds.top));
+ btn._sprites->draw(0, btn._frameNum, Common::Point(btn._bounds.left, btn._bounds.top));
win.setBounds(btn._bounds);
win.update();
break;
@@ -146,6 +150,7 @@ void ButtonContainer::drawButtons(XSurface *surface) {
for (uint btnIndex = 0; btnIndex < _buttons.size(); ++btnIndex) {
UIButton &btn = _buttons[btnIndex];
if (btn._draw) {
+ assert(btn._sprites);
btn._sprites->draw(*surface, btn._frameNum,
Common::Point(btn._bounds.left, btn._bounds.top));
}
@@ -153,7 +158,7 @@ void ButtonContainer::drawButtons(XSurface *surface) {
}
bool ButtonContainer::doScroll(bool rollUp, bool fadeIn) {
- if (_vm->_files->_isDarkCc) {
+ if (_vm->_files->_ccNum) {
return Cutscenes::doScroll(rollUp, fadeIn);
} else {
saveButtons();
diff --git a/engines/xeen/dialogs/dialogs.h b/engines/xeen/dialogs/dialogs.h
index 9038f75ef8..e97e46c5d3 100644
--- a/engines/xeen/dialogs/dialogs.h
+++ b/engines/xeen/dialogs/dialogs.h
@@ -39,14 +39,36 @@ public:
Common::Rect _bounds;
SpriteResource *_sprites;
int _value;
- uint _frameNum;
+ uint _frameNum, _selectedFrame;
bool _draw;
+ /**
+ * Constructor
+ */
UIButton(const Common::Rect &bounds, int value, uint frameNum, SpriteResource *sprites, bool draw) :
- _bounds(bounds), _value(value), _frameNum(frameNum),
+ _bounds(bounds), _value(value), _frameNum(frameNum), _selectedFrame(frameNum | 1),
_sprites(sprites), _draw(draw) {}
- UIButton() : _value(0), _frameNum(0), _sprites(nullptr), _draw(false) {}
+ /**
+ * Constructor
+ */
+ UIButton() : _value(0), _frameNum(0), _selectedFrame(0), _sprites(nullptr), _draw(false) {}
+
+ /**
+ * Set the frame
+ */
+ void setFrame(uint frameNum) {
+ _frameNum = frameNum;
+ _selectedFrame = frameNum | 1;
+ }
+
+ /**
+ * Set the frame
+ */
+ void setFrame(uint frameNum, uint selectedFrame) {
+ _frameNum = frameNum;
+ _selectedFrame = selectedFrame;
+ }
};
class ButtonContainer : public Cutscenes {
@@ -55,6 +77,7 @@ private:
protected:
Common::Array<UIButton> _buttons;
Common::StringArray _textStrings;
+ Common::Rect _waitBounds;
int _buttonValue;
bool checkEvents(XeenEngine *vm);
@@ -102,6 +125,11 @@ public:
* Draws the buttons onto the passed surface
*/
void drawButtons(XSurface *surface);
+
+ /**
+ * Clears any currently set button value
+ */
+ void clearEvents() { _buttonValue = 0; }
};
class SettingsBaseDialog : public ButtonContainer {
diff --git a/engines/xeen/dialogs/dialogs_char_info.cpp b/engines/xeen/dialogs/dialogs_char_info.cpp
index 0ae64ed608..aec8be5ee4 100644
--- a/engines/xeen/dialogs/dialogs_char_info.cpp
+++ b/engines/xeen/dialogs/dialogs_char_info.cpp
@@ -142,7 +142,7 @@ void CharacterInfo::execute(int charIndex) {
case Common::KEYCODE_RETURN:
case Common::KEYCODE_KP_ENTER:
_buttonValue = _cursorCell + Common::KEYCODE_a;
- // Deliberate fall-through
+ // fall through
case 1001:
case 1002:
@@ -198,6 +198,7 @@ void CharacterInfo::execute(int charIndex) {
}
_vm->_mode = MODE_CHARACTER_INFO;
+ redrawFlag = true;
break;
case Common::KEYCODE_q:
@@ -395,14 +396,18 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
bounds.setHeight(42);
break;
- case 10:
+ case 10: {
// Hit Points
- stat1 = c._currentHp;
- stat2 = c.getMaxHP();
- msg = Common::String::format(Res.CURRENT_MAXIMUM_TEXT, Res.STAT_NAMES[attrib],
- stat1, stat2);
+ Common::String fmt(Res.CURRENT_MAXIMUM_TEXT);
+ const char *p;
+ while ((p = strstr(fmt.c_str(), "%u")) != nullptr)
+ fmt.setChar('d', p - fmt.c_str() + 1);
+
+ msg = Common::String::format(fmt.c_str(), Res.STAT_NAMES[attrib],
+ c._currentHp, c.getMaxHP());
bounds.setHeight(42);
break;
+ }
case 11:
// Spell Points
@@ -521,14 +526,22 @@ bool CharacterInfo::expandStat(int attrib, const Character &c) {
++total;
}
- if (party._blessed)
+ if (party._blessed) {
lines[16] = Common::String::format(Res.BLESSED, party._blessed);
- if (party._powerShield)
+ ++total;
+ }
+ if (party._powerShield) {
lines[17] = Common::String::format(Res.POWER_SHIELD, party._powerShield);
- if (party._holyBonus)
+ ++total;
+ }
+ if (party._holyBonus) {
lines[18] = Common::String::format(Res.HOLY_BONUS, party._holyBonus);
- if (party._heroism)
+ ++total;
+ }
+ if (party._heroism) {
lines[19] = Common::String::format(Res.HEROISM, party._heroism);
+ ++total;
+ }
msg = Common::String::format("\x2\x3""c%s\x3l%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\x1",
Res.CONSUMABLE_NAMES[3], lines[0].c_str(), lines[1].c_str(),
diff --git a/engines/xeen/dialogs/dialogs_control_panel.cpp b/engines/xeen/dialogs/dialogs_control_panel.cpp
index 177c7785f8..80d1715ff7 100644
--- a/engines/xeen/dialogs/dialogs_control_panel.cpp
+++ b/engines/xeen/dialogs/dialogs_control_panel.cpp
@@ -61,9 +61,10 @@ int ControlPanel::execute() {
w.writeString("\xB""000\t000\x1");
w.update();
+ events.updateGameCounter();
+ intf.draw3d(false, false);
+
do {
- events.updateGameCounter();
- intf.draw3d(false, false);
w.writeString("\r");
drawButtons(&w);
w.writeString(text);
@@ -80,7 +81,7 @@ int ControlPanel::execute() {
checkEvents(_vm);
if (_vm->shouldExit())
return 0;
- } while (!_buttonValue && !events.timeElapsed());
+ } while (!_buttonValue && events.timeElapsed() < 2);
switch (_buttonValue) {
case Common::KEYCODE_q:
@@ -97,11 +98,11 @@ int ControlPanel::execute() {
sound.playFX(51);
if (g_vm->getGameID() == GType_WorldOfXeen) {
- map._loadDarkSide = false;
+ map._loadCcNum = 0;
map.load(28);
party._mazeDirection = DIR_EAST;
} else {
- map._loadDarkSide = true;
+ map._loadCcNum = 1;
map.load(29);
party._mazeDirection = DIR_SOUTH;
}
@@ -169,7 +170,8 @@ int ControlPanel::execute() {
intf.drawParty(true);
if (result == 3) {
- saves.loadGame();
+ if (g_vm->canLoadGameStateCurrently())
+ saves.loadGame();
} else if (result == 4) {
saves.saveGame();
}
diff --git a/engines/xeen/dialogs/dialogs_copy_protection.cpp b/engines/xeen/dialogs/dialogs_copy_protection.cpp
new file mode 100644
index 0000000000..7788cb5a22
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_copy_protection.cpp
@@ -0,0 +1,100 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "xeen/dialogs/dialogs_copy_protection.h"
+#include "xeen/dialogs/dialogs_input.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool CopyProtection::show(XeenEngine *vm) {
+ CopyProtection *dlg = new CopyProtection(vm);
+ int result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+CopyProtection::CopyProtection(XeenEngine *vm) : Input(vm, &(*vm->_windows)[11]) {
+ loadEntries();
+}
+
+bool CopyProtection::execute() {
+ EventsManager &events = *_vm->_events;
+ Sound &sound = *_vm->_sound;
+ Window &w = *_window;
+ bool result = false;
+ Common::String line;
+
+ // Choose a random entry
+ ProtectionEntry &protEntry = _entries[_vm->getRandomNumber(_entries.size() - 1)];
+ Common::String msg = Common::String::format(Res.WHATS_THE_PASSWORD,
+ protEntry._pageNum, protEntry._lineNum, protEntry._wordNum);
+
+ w.open();
+ w.writeString(msg);
+ w.update();
+
+ for (int tryNum = 0; tryNum < 3 && !_vm->shouldExit(); ++tryNum) {
+ line.clear();
+ if (getString(line, 20, 200, false) && !line.compareToIgnoreCase(protEntry._text)) {
+ sound.playFX(20);
+ result = true;
+ break;
+ }
+
+ sound.playFX(21);
+ w.writeString("\x3l\v040\n\x4""200");
+ w.writeString(Res.PASSWORD_INCORRECT);
+ w.update();
+
+ events.updateGameCounter();
+ events.wait(50, false);
+ }
+
+ w.close();
+ return result;
+}
+
+void CopyProtection::loadEntries() {
+ FileManager &files = *g_vm->_files;
+ File f(files._ccNum ? "timer.drv" : "cpstruct");
+ ProtectionEntry pe;
+ byte seed = 0;
+ char text[13];
+
+ while (f.pos() < f.size()) {
+ pe._pageNum = f.readByte() ^ seed++;
+ pe._lineNum = f.readByte() ^ seed++;
+ pe._wordNum = f.readByte() ^ seed++;
+
+ for (int idx = 0; idx < 13; ++idx)
+ text[idx] = f.readByte() ^ seed++;
+ text[12] = '\0';
+ pe._text = Common::String(text);
+
+ _entries.push_back(pe);
+ }
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_copy_protection.h b/engines/xeen/dialogs/dialogs_copy_protection.h
new file mode 100644
index 0000000000..97c8a6a53e
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_copy_protection.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.
+ *
+ */
+
+#ifndef XEEN_DIALOGS_COPY_PROTECTION_H
+#define XEEN_DIALOGS_COPY_PROTECTION_H
+
+#include "xeen/dialogs/dialogs_input.h"
+#include "common/array.h"
+
+namespace Xeen {
+
+class CopyProtection : public Input {
+ struct ProtectionEntry {
+ uint8 _pageNum;
+ uint8 _lineNum;
+ uint8 _wordNum;
+ Common::String _text;
+ };
+private:
+ Common::Array<ProtectionEntry> _entries;
+private:
+ /**
+ * Constructor
+ */
+ CopyProtection(XeenEngine *vm);
+
+ /**
+ * Execute the dialog
+ */
+ bool execute();
+
+ /**
+ * Load the copy protection entries
+ */
+ void loadEntries();
+public:
+ /**
+ * Show the dialog
+ */
+ static bool show(XeenEngine *vm);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_COPY_PROTECTION_H */
diff --git a/engines/xeen/dialogs/dialogs_create_char.cpp b/engines/xeen/dialogs/dialogs_create_char.cpp
index 577ae5314b..ab86c4939a 100644
--- a/engines/xeen/dialogs/dialogs_create_char.cpp
+++ b/engines/xeen/dialogs/dialogs_create_char.cpp
@@ -389,7 +389,8 @@ int CreateCharacterDialog::newCharDetails(Race race, Sex sex, int classId,
// Set up default skill for the race, if any
if (Res.NEW_CHAR_RACE_SKILLS[race] != -1) {
- raceSkillStr = Res.SKILL_NAMES[Res.NEW_CHAR_RACE_SKILLS[race]];
+ const char *skillP = Res.SKILL_NAMES[Res.NEW_CHAR_RACE_SKILLS[race]];
+ raceSkillStr = Common::String(skillP + Res.NEW_CHAR_SKILLS_OFFSET[race]);
}
// Set up color to use for each skill string to be displayed, based
@@ -554,7 +555,7 @@ int CreateCharacterDialog::exchangeAttribute(int srcAttr) {
break;
int destAttr = getAttribFromKeycode(_buttonValue);
-
+
if (destAttr != -1 && srcAttr != destAttr) {
result = destAttr;
break;
@@ -579,7 +580,7 @@ bool CreateCharacterDialog::saveCharacter(Character &c, int classId, Race race,
Window &w = windows[6];
Common::String name;
int result;
- bool isDarkCc = _vm->_files->_isDarkCc;
+ int ccNum = _vm->_files->_ccNum;
// Prompt for a character name
w.open();
@@ -597,11 +598,11 @@ bool CreateCharacterDialog::saveCharacter(Character &c, int classId, Race race,
c.clear();
c._name = name;
c._savedMazeId = party._priorMazeId;
- c._xeenSide = map._loadDarkSide;
+ c._xeenSide = map._loadCcNum;
c._sex = sex;
c._race = race;
c._class = (CharacterClass)classId;
- c._level._permanent = isDarkCc ? 5 : 1;
+ c._level._permanent = ccNum ? 5 : 1;
c._might._permanent = _attribs[MIGHT];
c._intellect._permanent = _attribs[INTELLECT];
diff --git a/engines/xeen/dialogs/dialogs_dismiss.cpp b/engines/xeen/dialogs/dialogs_dismiss.cpp
index 716f8f0035..7f9c8d972f 100644
--- a/engines/xeen/dialogs/dialogs_dismiss.cpp
+++ b/engines/xeen/dialogs/dialogs_dismiss.cpp
@@ -70,6 +70,10 @@ void Dismiss::execute() {
w.close();
ErrorScroll::show(_vm, Res.CANT_DISMISS_LAST_CHAR, WT_NONFREEZED_WAIT);
w.open();
+ } else if (party._activeParty[_buttonValue]._weapons.hasElderWeapon()) {
+ w.close();
+ ErrorScroll::show(_vm, Res.DELETE_CHAR_WITH_ELDER_WEAPON, WT_NONFREEZED_WAIT);
+ w.open();
} else {
// Remove the character from the party
party._activeParty.remove_at(_buttonValue);
diff --git a/engines/xeen/dialogs/dialogs_input.cpp b/engines/xeen/dialogs/dialogs_input.cpp
index 1d05c81f32..b72e47e37a 100644
--- a/engines/xeen/dialogs/dialogs_input.cpp
+++ b/engines/xeen/dialogs/dialogs_input.cpp
@@ -84,9 +84,9 @@ Common::KeyState Input::waitForKey(const Common::String &msg) {
intf._tillMove = 0;
bool flag = !_vm->_startupWindowActive && !windows[25]._enabled
- && _vm->_mode != MODE_FF && _vm->_mode != MODE_17;
+ && _vm->_mode != MODE_FF && _vm->_mode != MODE_INTERACTIVE7;
- Common::KeyState ks;
+ PendingEvent pe;
while (!_vm->shouldExit()) {
events.updateGameCounter();
@@ -100,11 +100,8 @@ Common::KeyState Input::waitForKey(const Common::String &msg) {
windows[3].update();
events.wait(1);
-
- if (events.isKeyPending()) {
- events.getKey(ks);
+ if (events.getEvent(pe) && pe.isKeyboard())
break;
- }
}
_window->writeString("");
@@ -113,7 +110,7 @@ Common::KeyState Input::waitForKey(const Common::String &msg) {
intf._tillMove = oldTillMove;
intf._upDoorText = oldUpDoorText;
- return ks;
+ return pe._keyState;
}
void Input::animateCursor() {
@@ -144,7 +141,6 @@ int StringInput::show(XeenEngine *vm, bool type, const Common::String &msg1,
int StringInput::execute(bool type, const Common::String &expected,
const Common::String &title, int opcode) {
FileManager &files = *_vm->_files;
- Interface &intf = *_vm->_interface;
Scripts &scripts = *_vm->_scripts;
Windows &windows = *_vm->_windows;
Window &w = windows[6];
@@ -158,9 +154,9 @@ int StringInput::execute(bool type, const Common::String &expected,
Common::String line;
if (getString(line, 30, 200, false)) {
if (type) {
- if (line == intf._interfaceText) {
+ if (!line.compareToIgnoreCase(scripts._message)) {
result = true;
- } else if (line == expected) {
+ } else if (!line.compareToIgnoreCase(expected)) {
result = (opcode == 55) ? -1 : 1;
}
} else {
@@ -168,14 +164,14 @@ int StringInput::execute(bool type, const Common::String &expected,
MirrorEntry me;
scripts._mirror.clear();
- File f(Common::String::format("%smirr.txt", files._isDarkCc ? "dark" : "xeen"), 1);
+ File f(Common::String::format("%smirr.txt", files._ccNum ? "dark" : "xeen"), 1);
while (me.synchronize(f))
scripts._mirror.push_back(me);
f.close();
// Load in any extended mirror entries
Common::File f2;
- if (f2.open(Common::String::format("%smirr.ext", files._isDarkCc ? "dark" : "xeen"))) {
+ if (f2.open(Common::String::format("%smirr.ext", files._ccNum ? "dark" : "xeen"))) {
while (me.synchronize(f2))
scripts._mirror.push_back(me);
f2.close();
@@ -184,7 +180,7 @@ int StringInput::execute(bool type, const Common::String &expected,
for (uint idx = 0; idx < scripts._mirror.size(); ++idx) {
if (!line.compareToIgnoreCase(scripts._mirror[idx]._name)) {
result = idx + 1;
- sound.playFX(_vm->_files->_isDarkCc ? 35 : 61);
+ sound.playFX(_vm->_files->_ccNum ? 35 : 61);
break;
}
}
@@ -219,8 +215,8 @@ int NumericInput::execute(int maxLength, int maxWidth) {
/*------------------------------------------------------------------------*/
-int Choose123::show(XeenEngine *vm, int numOptions) {
- assert(numOptions <= 3);
+int Choose123::show(XeenEngine *vm, uint numOptions) {
+ assert(numOptions <= 9);
Choose123 *dlg = new Choose123(vm);
int result = dlg->execute(numOptions);
delete dlg;
@@ -228,7 +224,7 @@ int Choose123::show(XeenEngine *vm, int numOptions) {
return result;
}
-int Choose123::execute(int numOptions) {
+int Choose123::execute(uint numOptions) {
EventsManager &events = *_vm->_events;
Interface &intf = *_vm->_interface;
LocationManager &loc = *_vm->_locations;
@@ -256,24 +252,17 @@ int Choose123::execute(int numOptions) {
}
events.wait(delay);
+ checkEvents(_vm);
+
if (_vm->shouldExit())
return 0;
} while (!_buttonValue);
- switch (_buttonValue) {
- case Common::KEYCODE_ESCAPE:
+ if (_buttonValue == Common::KEYCODE_ESCAPE) {
result = 0;
- break;
- case Common::KEYCODE_1:
- case Common::KEYCODE_2:
- case Common::KEYCODE_3: {
- int v = _buttonValue - Common::KEYCODE_1 + 1;
- if (v <= numOptions)
- result = v;
- break;
- }
- default:
- break;
+ } else if (_buttonValue >= Common::KEYCODE_1 && _buttonValue < (Common::KEYCODE_1 + (int)numOptions)) {
+ _buttonValue -= Common::KEYCODE_0;
+ result = (_buttonValue == (int)numOptions) ? 0 : _buttonValue;
}
}
@@ -283,15 +272,17 @@ int Choose123::execute(int numOptions) {
return result;
}
-void Choose123::loadButtons(int numOptions) {
+void Choose123::loadButtons(uint numOptions) {
+ assert(numOptions > 0 && numOptions <= 9);
_iconSprites.load("choose.icn");
+ const int XPOS[3] = { 235, 260, 286 };
+ const int YPOS[3] = { 75, 96, 117 };
- if (numOptions >= 1)
- addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_1, &_iconSprites);
- if (numOptions >= 2)
- addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_2, &_iconSprites);
- if (numOptions >= 3)
- addButton(Common::Rect(286, 75, 311, 95), Common::KEYCODE_3, &_iconSprites);
+ for (uint idx = 0; idx < numOptions; ++idx) {
+ Common::Rect r(24, 20);
+ r.moveTo(XPOS[idx % 3], YPOS[idx / 3]);
+ addButton(r, Common::KEYCODE_1 + idx, &_iconSprites);
+ }
}
/*------------------------------------------------------------------------*/
diff --git a/engines/xeen/dialogs/dialogs_input.h b/engines/xeen/dialogs/dialogs_input.h
index 270495ffd5..8cb41f3d36 100644
--- a/engines/xeen/dialogs/dialogs_input.h
+++ b/engines/xeen/dialogs/dialogs_input.h
@@ -82,11 +82,11 @@ private:
Choose123(XeenEngine *vm) : ButtonContainer(vm) {}
- int execute(int numOptions);
+ int execute(uint numOptions);
- void loadButtons(int numOptions);
+ void loadButtons(uint numOptions);
public:
- static int show(XeenEngine *vm, int numOptions);
+ static int show(XeenEngine *vm, uint numOptions);
};
class HowMuch : public ButtonContainer {
diff --git a/engines/xeen/dialogs/dialogs_items.cpp b/engines/xeen/dialogs/dialogs_items.cpp
index 24d4603617..b67e5a4aac 100644
--- a/engines/xeen/dialogs/dialogs_items.cpp
+++ b/engines/xeen/dialogs/dialogs_items.cpp
@@ -43,43 +43,35 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
Party &party = *_vm->_party;
Windows &windows = *_vm->_windows;
+ ItemsMode priorMode = ITEMMODE_INVALID;
Character *startingChar = c;
ItemCategory category = mode == ITEMMODE_RECHARGE || mode == ITEMMODE_COMBAT ?
CATEGORY_MISC : CATEGORY_WEAPON;
int varA = mode == ITEMMODE_COMBAT ? 1 : 0;
if (varA != 0)
mode = ITEMMODE_CHAR_INFO;
- bool updateStock = mode == ITEMMODE_BLACKSMITH;
+ bool updateStock = mode == ITEMMODE_BUY;
int itemIndex = -1;
Common::StringArray lines;
uint arr[40];
int actionIndex = -1;
- events.setCursor(0);
- loadButtons(mode, c);
+ if (mode == ITEMMODE_BUY) {
+ _oldCharacter = c;
+ c = &_itemsCharacter;
+ party._blacksmithWares.blackData2CharData(_itemsCharacter);
+ setEquipmentIcons();
+ } else if (mode == ITEMMODE_ENCHANT) {
+ _oldCharacter = c;
+ }
+ events.setCursor(0);
windows[29].open();
windows[30].open();
enum { REDRAW_NONE, REDRAW_TEXT, REDRAW_FULL } redrawFlag = REDRAW_FULL;
for (;;) {
if (redrawFlag == REDRAW_FULL) {
- if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_ENCHANT
- && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
- _buttons[4]._bounds.moveTo(148, _buttons[4]._bounds.top);
- _buttons[9]._draw = false;
- } else if (mode == ITEMMODE_RECHARGE) {
- _buttons[4]._value = Common::KEYCODE_r;
- } else if (mode == ITEMMODE_ENCHANT) {
- _buttons[4]._value = Common::KEYCODE_e;
- } else if (mode == ITEMMODE_TO_GOLD) {
- _buttons[4]._value = Common::KEYCODE_g;
- } else {
- _buttons[4]._bounds.moveTo(0, _buttons[4]._bounds.top);
- _buttons[9]._draw = true;
- _buttons[9]._value = Common::KEYCODE_u;
- }
-
// Write text for the dialog
Common::String msg;
if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_8 && mode != ITEMMODE_ENCHANT
@@ -99,41 +91,22 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
}
windows[29].writeString(msg);
- drawButtons(&windows[0]);
Common::fill(&arr[0], &arr[40], 0);
itemIndex = -1;
+ priorMode = ITEMMODE_INVALID;
+ }
+
+ if (mode != priorMode) {
+ // Set up the buttons for the dialog
+ loadButtons(mode, c, category);
+ priorMode = mode;
+ drawButtons(&windows[0]);
}
if (redrawFlag == REDRAW_TEXT || redrawFlag == REDRAW_FULL) {
lines.clear();
- if (mode == ITEMMODE_CHAR_INFO || category != 3) {
- _iconSprites.draw(0, 8, Common::Point(148, 109));
- }
- if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
- _iconSprites.draw(0, 10, Common::Point(182, 109));
- _iconSprites.draw(0, 12, Common::Point(216, 109));
- _iconSprites.draw(0, 14, Common::Point(250, 109));
- }
-
- switch (mode) {
- case ITEMMODE_CHAR_INFO:
- _iconSprites.draw(0, 9, Common::Point(148, 109));
- break;
- case ITEMMODE_BLACKSMITH:
- _iconSprites.draw(0, 11, Common::Point(182, 109));
- break;
- case ITEMMODE_REPAIR:
- _iconSprites.draw(0, 15, Common::Point(250, 109));
- break;
- case ITEMMODE_IDENTIFY:
- _iconSprites.draw(0, 13, Common::Point(216, 109));
- break;
- default:
- break;
- }
-
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
DrawStruct &ds = _itemsDrawList[idx];
XeenItem &i = c->_items[category][idx];
@@ -147,8 +120,8 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
case CATEGORY_ARMOR:
case CATEGORY_ACCESSORY:
if (i._id) {
- if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
- || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
+ if ((mode == ITEMMODE_CHAR_INFO && !g_vm->_extOptions._showItemCosts)
+ || mode == ITEMMODE_8 || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
lines.push_back(Common::String::format(Res.ITEMS_DIALOG_LINE1,
arr[idx], idx + 1,
c->_items[category].getFullDescription(idx, arr[idx]).c_str()));
@@ -156,7 +129,8 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
lines.push_back(Common::String::format(Res.ITEMS_DIALOG_LINE2,
arr[idx], idx + 1,
c->_items[category].getFullDescription(idx, arr[idx]).c_str(),
- calcItemCost(c, idx, mode,
+ calcItemCost(c, idx,
+ (mode == ITEMMODE_CHAR_INFO) ? ITEMMODE_BUY : mode,
mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT],
category)
));
@@ -209,7 +183,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
case ITEMMODE_CHAR_INFO:
case ITEMMODE_8:
windows[30].writeString(Common::String::format(Res.X_FOR_THE_Y,
- category == CATEGORY_MISC ? "\x3l" : "\x3c",
+ category == CATEGORY_MISC ? "\x3l" : "\x3""c",
Res.CATEGORY_NAMES[category], c->_name.c_str(), Res.CLASS_NAMES[c->_class],
category == CATEGORY_MISC ? Res.FMT_CHARGES : " ",
lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
@@ -218,7 +192,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
));
break;
- case ITEMMODE_BLACKSMITH:
+ case ITEMMODE_BUY:
windows[30].writeString(Common::String::format(Res.AVAILABLE_GOLD_COST,
Res.CATEGORY_NAMES[category], party._gold,
lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
@@ -227,7 +201,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
));
break;
- case ITEMMODE_2:
+ case ITEMMODE_SELL:
case ITEMMODE_RECHARGE:
case ITEMMODE_ENCHANT:
case ITEMMODE_REPAIR:
@@ -265,10 +239,10 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
if (itemIndex != -1) {
switch (mode) {
- case ITEMMODE_BLACKSMITH:
+ case ITEMMODE_BUY:
actionIndex = 0;
break;
- case ITEMMODE_2:
+ case ITEMMODE_SELL:
actionIndex = 1;
break;
case ITEMMODE_REPAIR:
@@ -336,36 +310,38 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
if (_buttonValue < (int)(_vm->_mode == MODE_COMBAT ?
combat._combatParty.size() : party._activeParty.size())) {
// Character number is valid
- redrawFlag = REDRAW_TEXT;
+ redrawFlag = REDRAW_FULL;
Character *newChar = _vm->_mode == MODE_COMBAT ?
combat._combatParty[_buttonValue] : &party._activeParty[_buttonValue];
- if (mode == ITEMMODE_BLACKSMITH) {
+ if (mode == ITEMMODE_BUY) {
_oldCharacter = newChar;
startingChar = newChar;
c = &_itemsCharacter;
- } else if (mode == ITEMMODE_2 || mode == ITEMMODE_REPAIR || mode == ITEMMODE_IDENTIFY) {
+ } else if (mode == ITEMMODE_SELL || mode == ITEMMODE_REPAIR || mode == ITEMMODE_IDENTIFY) {
_oldCharacter = newChar;
startingChar = newChar;
c = newChar;
} else if (itemIndex != -1) {
+ // Switching item to another character
InventoryItems &destItems = newChar->_items[category];
- XeenItem &destItem = destItems[INV_ITEMS_TOTAL - 1];
InventoryItems &srcItems = c->_items[category];
XeenItem &srcItem = srcItems[itemIndex];
- if (srcItem._bonusFlags & ITEMFLAG_CURSED)
+ if (srcItem._state._cursed)
ErrorScroll::show(_vm, Res.CANNOT_REMOVE_CURSED_ITEM);
- else if (destItems[INV_ITEMS_TOTAL - 1]._id)
+ else if (destItems.isFull())
ErrorScroll::show(_vm, Common::String::format(
Res.CATEGORY_BACKPACK_IS_FULL[category], c->_name.c_str()));
else {
+ XeenItem &destItem = destItems[INV_ITEMS_TOTAL - 1];
destItem = srcItem;
srcItem.clear();
destItem._frame = 0;
srcItems.sort();
destItems.sort();
+ continue;
}
} else {
c = newChar;
@@ -399,9 +375,12 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
Common::fill(&arr[0], &arr[40], 0);
arr[itemIndex] = 15;
}
-
- redrawFlag = REDRAW_TEXT;
+ } else {
+ Common::fill(&arr[0], &arr[40], 0);
+ itemIndex = -1;
}
+
+ redrawFlag = REDRAW_TEXT;
break;
case Common::KEYCODE_a:
@@ -414,7 +393,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
// Buy
if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
- mode = ITEMMODE_BLACKSMITH;
+ mode = ITEMMODE_BUY;
c = &_itemsCharacter;
redrawFlag = REDRAW_FULL;
}
@@ -466,7 +445,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
case Common::KEYCODE_m:
// Misc
category = CATEGORY_MISC;
- redrawFlag = REDRAW_TEXT;
+ redrawFlag = REDRAW_FULL;
break;
case Common::KEYCODE_q:
@@ -487,7 +466,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
case Common::KEYCODE_s:
if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_RECHARGE &&
mode != ITEMMODE_ENCHANT && mode != ITEMMODE_TO_GOLD) {
- mode = ITEMMODE_2;
+ mode = ITEMMODE_SELL;
c = startingChar;
redrawFlag = REDRAW_TEXT;
}
@@ -501,7 +480,7 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
case Common::KEYCODE_w:
// Weapons category
category = CATEGORY_WEAPON;
- redrawFlag = REDRAW_TEXT;
+ redrawFlag = REDRAW_FULL;
break;
}
}
@@ -516,12 +495,13 @@ Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
return c;
}
-void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
- Party &party = *g_vm->_party;
- _iconSprites.load(Common::String::format("%s.icn",
- (mode == ITEMMODE_CHAR_INFO) ? "items" : "buy"));
- _equipSprites.load("equip.icn");
+void ItemsDialog::loadButtons(ItemsMode mode, Character *&c, ItemCategory category) {
+ if (_iconSprites.empty())
+ _iconSprites.load(Common::String::format("%s.icn", (mode == ITEMMODE_CHAR_INFO) ? "items" : "buy"));
+ if (_equipSprites.empty())
+ _equipSprites.load("equip.icn");
+ clearButtons();
if (mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE || mode == ITEMMODE_TO_GOLD) {
// Enchant button list
addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites);
@@ -541,14 +521,16 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8);
addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9);
} else {
+ bool flag = mode == ITEMMODE_BUY || mode == ITEMMODE_SELL || mode == ITEMMODE_IDENTIFY
+ || mode == ITEMMODE_REPAIR;
addButton(Common::Rect(12, 109, 36, 129), Common::KEYCODE_w, &_iconSprites);
addButton(Common::Rect(46, 109, 70, 129), Common::KEYCODE_a, &_iconSprites);
addButton(Common::Rect(80, 109, 104, 129), Common::KEYCODE_c, &_iconSprites);
addButton(Common::Rect(114, 109, 138, 129), Common::KEYCODE_m, &_iconSprites);
- addButton(Common::Rect(148, 109, 172, 129), Common::KEYCODE_e, &_iconSprites);
- addButton(Common::Rect(182, 109, 206, 129), Common::KEYCODE_r, &_iconSprites);
- addButton(Common::Rect(216, 109, 240, 129), Common::KEYCODE_d, &_iconSprites);
- addButton(Common::Rect(250, 109, 274, 129), Common::KEYCODE_q, &_iconSprites);
+ addButton(Common::Rect(148, 109, 172, 129), flag ? Common::KEYCODE_b : Common::KEYCODE_e, &_iconSprites);
+ addButton(Common::Rect(182, 109, 206, 129), flag ? Common::KEYCODE_s : Common::KEYCODE_r, &_iconSprites);
+ addButton(Common::Rect(216, 109, 240, 129), flag ? Common::KEYCODE_i : Common::KEYCODE_d, &_iconSprites);
+ addButton(Common::Rect(250, 109, 274, 129), flag ? Common::KEYCODE_f : Common::KEYCODE_q, &_iconSprites);
addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites);
addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1);
addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2);
@@ -562,22 +544,44 @@ void ItemsDialog::loadButtons(ItemsMode mode, Character *&c) {
addPartyButtons(_vm);
}
- if (mode == ITEMMODE_BLACKSMITH) {
- _oldCharacter = c;
- c = &_itemsCharacter;
- party._blacksmithWares.blackData2CharData(_itemsCharacter);
+ if (mode == ITEMMODE_CHAR_INFO && category == CATEGORY_MISC) {
+ _buttons[4].setFrame(18);
+ _buttons[4]._value = Common::KEYCODE_u;
+ }
+ if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
+ _buttons[5].setFrame(10);
+ _buttons[6].setFrame(12);
+ _buttons[7].setFrame(14);
+ }
- _buttons[4]._value = Common::KEYCODE_b;
- _buttons[5]._value = Common::KEYCODE_s;
- _buttons[6]._value = Common::KEYCODE_i;
- _buttons[7]._value = Common::KEYCODE_f;
+ // Set button as depressed depending on which mode the dialog is currently in
+ switch (mode) {
+ case ITEMMODE_BUY:
+ _buttons[4].setFrame(9);
+ break;
+ case ITEMMODE_SELL:
+ _buttons[5].setFrame(11);
+ break;
+ case ITEMMODE_IDENTIFY:
+ _buttons[6].setFrame(13);
+ break;
+ case ITEMMODE_REPAIR:
+ _buttons[7].setFrame(15);
+ break;
+ default:
+ break;
+ }
- setEquipmentIcons();
- } else {
+ if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_ENCHANT
+ && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
+ _buttons[4]._bounds.moveTo(148, _buttons[4]._bounds.top);
+ _buttons[9]._draw = false;
+ } else if (mode == ITEMMODE_RECHARGE) {
+ _buttons[4]._value = Common::KEYCODE_r;
+ } else if (mode == ITEMMODE_ENCHANT) {
_buttons[4]._value = Common::KEYCODE_e;
- _buttons[5]._value = Common::KEYCODE_r;
- _buttons[6]._value = Common::KEYCODE_d;
- _buttons[7]._value = Common::KEYCODE_q;
+ } else if (mode == ITEMMODE_TO_GOLD) {
+ _buttons[4]._value = Common::KEYCODE_g;
}
}
@@ -643,10 +647,10 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
};
switch (mode) {
- case ITEMMODE_BLACKSMITH:
+ case ITEMMODE_BUY:
level = 0;
break;
- case ITEMMODE_2:
+ case ITEMMODE_SELL:
case ITEMMODE_TO_GOLD:
level = level == 0 ? 1 : 0;
break;
@@ -692,8 +696,8 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
amount3 = Res.ELEMENTAL_DAMAGE[i._material - 59 + 7] * 100;
switch (mode) {
- case ITEMMODE_BLACKSMITH:
- case ITEMMODE_2:
+ case ITEMMODE_BUY:
+ case ITEMMODE_SELL:
case ITEMMODE_REPAIR:
case ITEMMODE_IDENTIFY:
case ITEMMODE_TO_GOLD:
@@ -712,8 +716,8 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
amount4 = Res.MISC_BASE_COSTS[i._id];
switch (mode) {
- case ITEMMODE_BLACKSMITH:
- case ITEMMODE_2:
+ case ITEMMODE_BUY:
+ case ITEMMODE_SELL:
case ITEMMODE_REPAIR:
case ITEMMODE_IDENTIFY:
case ITEMMODE_TO_GOLD:
@@ -721,6 +725,15 @@ int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
if (!result)
result = 1;
break;
+
+ case ITEMMODE_3:
+ case ITEMMODE_RECHARGE:
+ case ITEMMODE_5:
+ case ITEMMODE_ENCHANT:
+ // Show number of charges
+ result = i._state._counter;
+ break;
+
default:
break;
}
@@ -742,64 +755,18 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
Sound &sound = *_vm->_sound;
Spells &spells = *_vm->_spells;
Windows &windows = *_vm->_windows;
- bool isDarkCc = _vm->_files->_isDarkCc;
+ int ccNum = _vm->_files->_ccNum;
- XeenItem *itemCategories[4] = { &c._weapons[0], &c._armor[0], &c._accessories[0], &c._misc[0] };
- XeenItem *items = itemCategories[category];
- if (!items[0]._id)
+ InventoryItems &items = c._items[category];
+ if (items[0].empty())
// Inventory is empty
return category == CATEGORY_MISC ? 0 : 2;
- Window &w = windows[11];
- SpriteResource escSprites;
- if (itemIndex < 0 || itemIndex > 8) {
- saveButtons();
-
- escSprites.load("esc.icn");
- addButton(Common::Rect(235, 111, 259, 131), Common::KEYCODE_ESCAPE, &escSprites);
- addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1);
- addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2);
- addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3);
- addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4);
- addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5);
- addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6);
- addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7);
- addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8);
- addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9);
-
- w.open();
- w.writeString(Common::String::format(Res.WHICH_ITEM, Res.ITEM_ACTIONS[actionIndex]));
- _iconSprites.draw(0, 0, Common::Point(235, 111));
- w.update();
-
- while (!_vm->shouldExit()) {
- while (!_buttonValue) {
- events.pollEventsAndWait();
- checkEvents(_vm);
- if (_vm->shouldExit())
- return false;
- }
-
- if (_buttonValue == Common::KEYCODE_ESCAPE) {
- itemIndex = -1;
- break;
- } else if (_buttonValue >= Common::KEYCODE_1 && _buttonValue <= Common::KEYCODE_9) {
- // Check whether there's an item at the selected index
- int selectedIndex = _buttonValue - Common::KEYCODE_1;
- if (!items[selectedIndex]._id)
- continue;
-
- itemIndex = selectedIndex;
- break;
- }
- }
-
- w.close();
- restoreButtons();
- }
+ if (itemIndex < 0 || itemIndex > 8)
+ itemIndex = ItemSelectionDialog::show(actionIndex, items);
if (itemIndex != -1) {
- XeenItem &item = c._items[category][itemIndex];
+ XeenItem &item = items[itemIndex];
switch (mode) {
case ITEMMODE_CHAR_INFO:
@@ -830,10 +797,8 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
default:
if (combat._itemFlag) {
ErrorScroll::show(_vm, Res.USE_ITEM_IN_COMBAT);
- } else if (i._id && (i._bonusFlags & ITEMFLAG_BONUS_MASK)
- && !(i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED))) {
- int charges = (i._bonusFlags & ITEMFLAG_BONUS_MASK) - 1;
- i._bonusFlags = charges;
+ } else if (i._id && !i.isBad() && i._state._counter > 0) {
+ --i._state._counter;
_oldCharacter = &c;
windows[30].close();
@@ -841,7 +806,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
windows[24].close();
spells.castItemSpell(i._id);
- if (!charges) {
+ if (!i._state._counter) {
// Ran out of charges, so make item disappear
c._items[category][itemIndex].clear();
c._items[category].sort();
@@ -868,7 +833,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
}
break;
- case ITEMMODE_BLACKSMITH: {
+ case ITEMMODE_BUY: {
InventoryItems &invItems = _oldCharacter->_items[category];
if (invItems.isFull()) {
// Character's inventory for that category is already full
@@ -880,15 +845,18 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
if (Confirm::show(_vm, Common::String::format(Res.BUY_X_FOR_Y_GOLD,
desc.c_str(), cost))) {
if (party.subtract(CONS_GOLD, cost, WHERE_PARTY, WT_FREEZE_WAIT)) {
- if (isDarkCc) {
+ if (ccNum) {
sound.stopSound();
sound.playSound("choice2.voc");
}
// Add entry to the end of the list
- XeenItem &bsItem = c._items[category][itemIndex];
- _oldCharacter->_items[category][INV_ITEMS_TOTAL - 1] = bsItem;
- bsItem.clear();
+ XeenItem &srcItem = c._items[category][itemIndex];
+ XeenItem &destItem = _oldCharacter->_items[category][INV_ITEMS_TOTAL - 1];
+ destItem = srcItem;
+ destItem._frame = 0;
+
+ srcItem.clear();
c._items[category].sort();
_oldCharacter->_items[category].sort();
}
@@ -897,14 +865,14 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
break;
}
- case ITEMMODE_2: {
+ case ITEMMODE_SELL: {
bool noNeed;
switch (category) {
case CATEGORY_WEAPON:
- noNeed = (item._bonusFlags & ITEMFLAG_CURSED) || item._id == 34;
+ noNeed = (item._state._cursed) || item._id >= XEEN_SLAYER_SWORD;
break;
default:
- noNeed = item._bonusFlags & ITEMFLAG_CURSED;
+ noNeed = item._state._cursed;
break;
}
@@ -929,17 +897,12 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
}
case ITEMMODE_RECHARGE:
- if (category != CATEGORY_MISC || c._misc[itemIndex]._material > 9
- || c._misc[itemIndex]._id == 53 || c._misc[itemIndex]._id == 0) {
+ if (category != CATEGORY_MISC || item.empty() || item._material > 9 || item._id == 53) {
sound.playFX(21);
ErrorScroll::show(_vm, Common::String::format(Res.NOT_RECHARGABLE, Res.SPELL_FAILED));
} else {
- int charges = MIN(63, _vm->getRandomNumber(1, 6) +
- (c._misc[itemIndex]._bonusFlags & ITEMFLAG_BONUS_MASK));
+ item._state._counter = MIN(63, _vm->getRandomNumber(1, 6) + item._state._counter);
sound.playFX(20);
-
- c._misc[itemIndex]._bonusFlags = (c._misc[itemIndex]._bonusFlags
- & ~ITEMFLAG_BONUS_MASK) | charges;
}
return 2;
@@ -951,7 +914,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
}
case ITEMMODE_REPAIR:
- if (!(item._bonusFlags & ITEMFLAG_BROKEN)) {
+ if (!item._state._broken) {
ErrorScroll::show(_vm, Res.ITEM_NOT_BROKEN);
} else {
int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
@@ -961,7 +924,7 @@ int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, Ite
cost);
if (Confirm::show(_vm, msg) && party.subtract(CONS_GOLD, cost, WHERE_PARTY)) {
- item._bonusFlags &= ~ITEMFLAG_BROKEN;
+ item._state._broken = false;
}
}
break;
@@ -1016,11 +979,11 @@ void ItemsDialog::itemToGold(Character &c, int itemIndex, ItemCategory category,
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
- if (category == CATEGORY_WEAPON && item._id == 34) {
+ if (category == CATEGORY_WEAPON && item._id >= XEEN_SLAYER_SWORD) {
sound.playFX(21);
ErrorScroll::show(_vm, Common::String::format("\v012\t000\x03""c%s",
Res.SPELL_FAILED));
- } else if (item._id != 0) {
+ } else if (!item.empty()) {
// There is a valid item present
// Calculate cost of item and add it to the party's total
int cost = calcItemCost(&c, itemIndex, mode, 1, category);
@@ -1032,4 +995,67 @@ void ItemsDialog::itemToGold(Character &c, int itemIndex, ItemCategory category,
}
}
+/*------------------------------------------------------------------------*/
+
+int ItemSelectionDialog::show(int actionIndex, InventoryItems &items) {
+ ItemSelectionDialog *dlg = new ItemSelectionDialog(g_vm, actionIndex, items);
+ int result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+void ItemSelectionDialog::loadButtons() {
+ _icons.load("esc.icn");
+ addButton(Common::Rect(235, 111, 259, 131), Common::KEYCODE_ESCAPE, &_icons);
+ addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1);
+ addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2);
+ addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3);
+ addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4);
+ addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5);
+ addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6);
+ addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7);
+ addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8);
+ addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9);
+}
+
+int ItemSelectionDialog::execute() {
+ EventsManager &events = *g_vm->_events;
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[13];
+
+ w.open();
+ w.writeString(Common::String::format(Res.WHICH_ITEM, Res.ITEM_ACTIONS[_actionIndex]));
+ _icons.draw(0, 0, Common::Point(235, 111));
+ w.update();
+
+ int itemIndex = -1;
+ while (!_vm->shouldExit()) {
+ _buttonValue = 0;
+ while (!_buttonValue) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ if (_vm->shouldExit())
+ return false;
+ }
+
+ if (_buttonValue == Common::KEYCODE_ESCAPE) {
+ itemIndex = -1;
+ break;
+ }
+ else if (_buttonValue >= Common::KEYCODE_1 && _buttonValue <= Common::KEYCODE_9) {
+ // Check whether there's an item at the selected index
+ int selectedIndex = _buttonValue - Common::KEYCODE_1;
+ if (!_items[selectedIndex]._id)
+ continue;
+
+ itemIndex = selectedIndex;
+ break;
+ }
+ }
+
+ w.close();
+ return itemIndex;
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_items.h b/engines/xeen/dialogs/dialogs_items.h
index 33930640f1..d3632dc8dc 100644
--- a/engines/xeen/dialogs/dialogs_items.h
+++ b/engines/xeen/dialogs/dialogs_items.h
@@ -30,9 +30,10 @@
namespace Xeen {
enum ItemsMode {
- ITEMMODE_CHAR_INFO = 0, ITEMMODE_BLACKSMITH = 1, ITEMMODE_2 = 2, ITEMMODE_3 = 3,
+ ITEMMODE_CHAR_INFO = 0, ITEMMODE_BUY = 1, ITEMMODE_SELL = 2, ITEMMODE_3 = 3,
ITEMMODE_RECHARGE = 4, ITEMMODE_5 = 5, ITEMMODE_ENCHANT = 6, ITEMMODE_COMBAT = 7, ITEMMODE_8 = 8,
- ITEMMODE_REPAIR = 9, ITEMMODE_IDENTIFY = 10, ITEMMODE_TO_GOLD = 11
+ ITEMMODE_REPAIR = 9, ITEMMODE_IDENTIFY = 10, ITEMMODE_TO_GOLD = 11,
+ ITEMMODE_INVALID = -1
};
class ItemsDialog : public ButtonContainer {
@@ -50,7 +51,7 @@ private:
/**
* Load the buttons for the dialog
*/
- void loadButtons(ItemsMode mode, Character *&c);
+ void loadButtons(ItemsMode mode, Character *&c, ItemCategory category);
/**
* Sets the equipment icon to use for each item for display
@@ -58,7 +59,7 @@ private:
void setEquipmentIcons();
/**
- * Calculate the cost of an item
+ * Calculate the cost of an item, or charges renaming for Misc items as appropriate
*/
int calcItemCost(Character *c, int itemIndex, ItemsMode mode, int skillLevel,
ItemCategory category);
@@ -71,6 +72,38 @@ public:
static Character *show(XeenEngine *vm, Character *c, ItemsMode mode);
};
+class ItemSelectionDialog : public ButtonContainer {
+private:
+ SpriteResource _icons;
+ int _actionIndex;
+ InventoryItems &_items;
+
+ ItemSelectionDialog(XeenEngine *vm, int actionIndex, InventoryItems &items) : ButtonContainer(vm),
+ _actionIndex(actionIndex), _items(items) {
+ loadButtons();
+ }
+
+ /**
+ * Executes the dialog
+ * @returns Selected item index
+ */
+ int execute();
+
+ /**
+ * Loads buttons
+ */
+ void loadButtons();
+public:
+ /**
+ * Shows the dialog
+ * @param actionIndex Current action type
+ * @param items Currently active items category
+ * @returns Selected item index
+ */
+ static int show(int actionIndex, InventoryItems &items);
+};
+
+
} // End of namespace Xeen
#endif /* XEEN_DIALOGS_ITEMS_H */
diff --git a/engines/xeen/dialogs/dialogs_message.cpp b/engines/xeen/dialogs/dialogs_message.cpp
index df8afea34c..f571e6e811 100644
--- a/engines/xeen/dialogs/dialogs_message.cpp
+++ b/engines/xeen/dialogs/dialogs_message.cpp
@@ -51,7 +51,7 @@ void MessageDialog::execute(const Common::String &msg, MessageWaitType waitType)
break;
case WT_ANIMATED_WAIT:
- if (windows[11]._enabled || _vm->_mode == MODE_17) {
+ if (windows[11]._enabled || _vm->_mode == MODE_INTERACTIVE7) {
g_vm->_locations->wait();
break;
}
diff --git a/engines/xeen/dialogs/dialogs_party.cpp b/engines/xeen/dialogs/dialogs_party.cpp
index c3d6843ffd..cf49007f30 100644
--- a/engines/xeen/dialogs/dialogs_party.cpp
+++ b/engines/xeen/dialogs/dialogs_party.cpp
@@ -45,6 +45,7 @@ void PartyDialog::show(XeenEngine *vm) {
void PartyDialog::execute() {
EventsManager &events = *_vm->_events;
+ FileManager &files = *_vm->_files;
Interface &intf = *_vm->_interface;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
@@ -54,18 +55,19 @@ void PartyDialog::execute() {
bool modeFlag = false;
int startingChar = 0;
+ sound.playSong(files._ccNum ? "newbrigh.m" : "inn.m");
loadButtons();
setupBackground();
while (!_vm->shouldExit()) {
- _vm->_mode = MODE_1;
+ _vm->_mode = MODE_INTERACTIVE;
// Build up a list of available characters in the Roster that are on the
// same side of Xeen as the player is currently on
_charList.clear();
for (int i = 0; i < XEEN_TOTAL_CHARACTERS; ++i) {
Character &player = party._roster[i];
- if (player._name.empty() || player._xeenSide != (map._loadDarkSide ? 1 : 0))
+ if (player._name.empty() || player._xeenSide != map._loadCcNum)
continue;
_charList.push_back(i);
diff --git a/engines/xeen/dialogs/dialogs_query.cpp b/engines/xeen/dialogs/dialogs_query.cpp
index 79f46826cd..876ddafc2b 100644
--- a/engines/xeen/dialogs/dialogs_query.cpp
+++ b/engines/xeen/dialogs/dialogs_query.cpp
@@ -68,8 +68,11 @@ bool Confirm::execute(const Common::String &msg, int mode) {
bool result = false;
while (!_vm->shouldExit()) {
- events.pollEvents();
- checkEvents(_vm);
+ _buttonValue = 0;
+ while (!_vm->shouldExit() && !_buttonValue) {
+ events.pollEvents();
+ checkEvents(_vm);
+ }
if ((mode & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE
|| _buttonValue == Common::KEYCODE_n)
@@ -81,6 +84,7 @@ bool Confirm::execute(const Common::String &msg, int mode) {
}
}
+ events.clearEvents();
w.close();
return result;
}
@@ -108,6 +112,7 @@ bool YesNo::execute(bool type, bool townFlag) {
Mode oldMode = _vm->_mode;
_vm->_mode = oldMode == MODE_7 ? MODE_8 : MODE_7;
+ events.clearEvents();
if (!type) {
confirmSprites.load("confirm.icn");
diff --git a/engines/xeen/dialogs/dialogs_quests.cpp b/engines/xeen/dialogs/dialogs_quests.cpp
index e4f62270ef..94834c1c02 100644
--- a/engines/xeen/dialogs/dialogs_quests.cpp
+++ b/engines/xeen/dialogs/dialogs_quests.cpp
@@ -44,6 +44,9 @@ void Quests::execute() {
int count = 0;
bool headerShown = false;
int topRow = 0;
+ const char **questItemNames = (g_vm->getGameID() == GType_Swords) ? Res.QUEST_ITEM_NAMES_SWORDS : Res.QUEST_ITEM_NAMES;
+ int itemsCount = (g_vm->getGameID() == GType_Swords) ? TOTAL_QUEST_ITEMS_SWORDS : TOTAL_QUEST_ITEMS;
+ const char *title1 = (g_vm->getGameID() == GType_Swords) ? Res.SWORDS_OF_XEEN_LINE : Res.CLOUDS_OF_XEEN_LINE;
addButtons();
loadQuestNotes();
@@ -66,37 +69,49 @@ void Quests::execute() {
switch (mode) {
case QUEST_ITEMS:
- for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx)
+ for (int idx = 0; idx < itemsCount; ++idx)
lines[idx] = "\b \b*";
count = 0;
headerShown = false;
- for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx) {
+ for (int idx = 0; idx < itemsCount; ++idx) {
if (party._questItems[idx]) {
- if (!count && !headerShown && idx < 35) {
- lines[count++] = Res.CLOUDS_OF_XEEN_LINE;
- }
- if (idx >= 35 && !headerShown) {
+ if (!count ) {
+ if (_vm->getGameID() == GType_Swords)
+ lines[count++] = Res.SWORDS_OF_XEEN_LINE;
+ else if (idx < 35)
+ lines[count++] = Res.CLOUDS_OF_XEEN_LINE;
+ } else if (_vm->getGameID() != GType_Swords && idx >= 35 && !headerShown) {
lines[count++] = Res.DARKSIDE_OF_XEEN_LINE;
headerShown = true;
}
- switch (idx) {
- case 17:
- case 26:
- case 79:
- case 80:
- case 81:
- case 82:
- case 83:
- case 84:
+ bool multiFlag = false;
+ if (_vm->getGameID() == GType_Swords) {
+ multiFlag = (idx == 20) || (idx == 27) || (idx == 41);
+ } else {
+ switch (idx) {
+ case 17:
+ case 26:
+ case 79:
+ case 80:
+ case 81:
+ case 82:
+ case 83:
+ case 84:
+ multiFlag = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (multiFlag) {
lines[count++] = Common::String::format("%d %s%c",
- party._questItems[idx], Res.QUEST_ITEM_NAMES[idx],
+ party._questItems[idx], questItemNames[idx],
party._questItems[idx] == 1 ? ' ' : 's');
- break;
- default:
- lines[count++] = Res.QUEST_ITEM_NAMES[idx];
- break;
+ } else {
+ lines[count++] = questItemNames[idx];
}
}
}
@@ -115,17 +130,17 @@ void Quests::execute() {
break;
case CURRENT_QUESTS:
- for (int idx = 0; idx < TOTAL_QUEST_ITEMS; ++idx)
+ for (int idx = 0; idx < itemsCount; ++idx)
lines[idx] = "";
count = 0;
headerShown = false;
for (int idx = 0; idx < TOTAL_QUEST_FLAGS; ++idx) {
- if (party._questFlags[(idx + 1) / 30][(idx + 1) % 30]) {
- if (!count && !headerShown && idx < 29) {
- lines[count++] = Res.CLOUDS_OF_XEEN_LINE;
+ if (party._questFlags[idx + 1]) {
+ if (!count && !headerShown && (_vm->getGameID() == GType_Swords || idx < 29)) {
+ lines[count++] = title1;
}
- if (idx > 28 && !headerShown) {
+ if (_vm->getGameID() != GType_Swords && idx > 28 && !headerShown) {
lines[count++] = Res.DARKSIDE_OF_XEEN_LINE;
headerShown = true;
}
@@ -141,23 +156,39 @@ void Quests::execute() {
lines[topRow].c_str(), lines[topRow + 1].c_str(), lines[topRow + 2].c_str()));
break;
- case AUTO_NOTES:
- for (int idx = 0; idx < MAX_DIALOG_LINES; ++idx)
+ case AUTO_NOTES: {
+ int max, offset;
+ switch (_vm->getGameID()) {
+ case GType_Swords:
+ max = 49;
+ offset = 51;
+ break;
+ case GType_Clouds:
+ max = MAX_DIALOG_LINES;
+ offset = 31;
+ break;
+ default:
+ max = MAX_DIALOG_LINES;
+ offset = 56;
+ break;
+ }
+
+ for (int idx = 0; idx < max; ++idx)
lines[idx] = "";
count = 0;
headerShown = false;
- for (int idx = 0; idx < MAX_DIALOG_LINES; ++idx) {
- if (party._worldFlags[idx]) {
- if (!count && !headerShown && idx < 72) {
- lines[count++] = Res.CLOUDS_OF_XEEN_LINE;
+ for (int idx = 0; idx < max; ++idx) {
+ if (party._worldFlags[idx + (_vm->getGameID() != GType_Swords ? 1 : 0)]) {
+ if (!count && !headerShown && (_vm->getGameID() == GType_Swords || idx < 72)) {
+ lines[count++] = title1;
}
if (idx >= 72 && !headerShown) {
lines[count++] = Res.DARKSIDE_OF_XEEN_LINE;
headerShown = true;
}
- lines[count++] = _questNotes[idx + 56];
+ lines[count++] = _questNotes[idx + offset];
}
}
@@ -173,6 +204,7 @@ void Quests::execute() {
));
break;
}
+ }
windows[30].writeString("\v000\t000");
windows[24].update();
@@ -245,7 +277,7 @@ void Quests::addButtons() {
}
void Quests::loadQuestNotes() {
- File f("qnotes.bin");
+ File f("qnotes.bin", 1);
while (f.pos() < f.size())
_questNotes.push_back(f.readString());
f.close();
diff --git a/engines/xeen/dialogs/dialogs_spells.cpp b/engines/xeen/dialogs/dialogs_spells.cpp
index 3da5a5149e..27329e48df 100644
--- a/engines/xeen/dialogs/dialogs_spells.cpp
+++ b/engines/xeen/dialogs/dialogs_spells.cpp
@@ -31,37 +31,40 @@
namespace Xeen {
Character *SpellsDialog::show(XeenEngine *vm, ButtonContainer *priorDialog,
- Character *c, int isCasting) {
+ Character *c, SpellDialogMode mode) {
SpellsDialog *dlg = new SpellsDialog(vm);
- Character *result = dlg->execute(priorDialog, c, isCasting);
+ Character *result = dlg->execute(priorDialog, c, mode);
delete dlg;
return result;
}
-Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int isCasting) {
+Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int mode) {
EventsManager &events = *_vm->_events;
Interface &intf = *_vm->_interface;
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
Spells &spells = *_vm->_spells;
Windows &windows = *_vm->_windows;
- bool isDarkCc = _vm->_files->_isDarkCc;
+ Window &w = windows[25];
+ int ccNum = _vm->_files->_ccNum;
+
loadButtons();
+ loadStrings("spldesc.bin");
- int castingCopy = isCasting;
- isCasting &= 0x7f;
+ int modeCopy = mode;
+ mode &= 0x7f;
int selection = -1;
int topIndex = 0;
int newSelection;
- windows[25].open();
+ w.open();
do {
- if (!isCasting) {
+ if (!mode) {
if (!c->guildMember()) {
sound.stopSound();
intf._overallFrame = 5;
- sound.playSound(isDarkCc ? "skull1.voc" : "guild11.voc", 1);
+ sound.playSound(ccNum ? "skull1.voc" : "guild11.voc", 1);
break;
}
@@ -69,13 +72,12 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
Common::String msg = Common::String::format(Res.GUILD_OPTIONS,
title.c_str(), XeenEngine::printMil(party._gold).c_str());
windows[10].writeString(msg);
-
- warning("TODO: Sprite draw using previously used button sprites");
+ priorDialog->drawButtons(&windows[10]);
}
_spells.clear();
- const char *errorMsg = setSpellText(c, castingCopy);
- windows[25].writeString(Common::String::format(Res.SPELLS_FOR,
+ const char *errorMsg = setSpellText(c, modeCopy);
+ w.writeString(Common::String::format(Res.SPELLS_FOR,
errorMsg == nullptr ? Res.SPELL_LINES_0_TO_9 : "",
c->_name.c_str()));
@@ -103,18 +105,19 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
colors[3], names[3], colors[4], names[4], colors[5], names[5],
colors[6], names[6], colors[7], names[7], colors[8], names[8],
colors[9], names[9],
- isCasting ? Res.SPELL_PTS : Res.GOLD,
- isCasting ? c->_currentSp : party._gold
+ mode ? Res.SPELL_PTS : Res.GOLD,
+ mode ? c->_currentSp : party._gold
));
_scrollSprites.draw(0, 4, Common::Point(39, 26));
_scrollSprites.draw(0, 0, Common::Point(187, 26));
_scrollSprites.draw(0, 2, Common::Point(187, 111));
- if (isCasting)
- _scrollSprites.draw(windows[25], 5, Common::Point(132, 123));
+ if (mode)
+ _scrollSprites.draw(w, 5, Common::Point(132, 123));
- windows[25].update();
+ w.update();
+ _buttonValue = 0;
do {
events.pollEventsAndWait();
checkEvents(_vm);
@@ -134,27 +137,14 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
spells._lastCaster = _buttonValue;
intf.highlightChar(_buttonValue);
- if (_vm->_mode == MODE_17) {
+ if (_vm->_mode == MODE_INTERACTIVE7) {
windows[10].writeString(Common::String::format(Res.GUILD_OPTIONS,
XeenEngine::printMil(party._gold).c_str(), Res.GUILD_TEXT, c->_name.c_str()));
} else {
- int category;
- switch (c->_class) {
- case CLASS_ARCHER:
- case CLASS_SORCERER:
- category = 1;
- break;
- case CLASS_DRUID:
- case CLASS_RANGER:
- category = 2;
- break;
- default:
- category = 0;
- break;
- }
+ SpellsCategory category = c->getSpellsCategory();
+ int spellIndex = (c->_currentSpell == -1) ? SPELLS_PER_CLASS : c->_currentSpell;
+ int spellId = (category == SPELLCAT_INVALID) ? NO_SPELL : Res.SPELLS_ALLOWED[category][spellIndex];
- int spellIndex = (c->_currentSpell == -1) ? 39 : c->_currentSpell;
- int spellId = Res.SPELLS_ALLOWED[category][spellIndex];
windows[10].writeString(Common::String::format(Res.CAST_SPELL_DETAILS,
c->_name.c_str(), spells._spellNames[spellId].c_str(),
spells.calcSpellPoints(spellId, c->getCurrentLevel()),
@@ -194,53 +184,31 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
(_buttonValue - Common::KEYCODE_1));
if (newSelection < (int)_spells.size()) {
- int expenseFactor = 0;
- int category = 0;
-
- switch (c->_class) {
- case CLASS_PALADIN:
- expenseFactor = 1;
- category = 0;
- break;
- case CLASS_ARCHER:
- expenseFactor = 1;
- category = 1;
- break;
- case CLASS_CLERIC:
- category = 0;
- break;
- case CLASS_SORCERER:
- category = 1;
- break;
- case CLASS_DRUID:
- category = 2;
- break;
- case CLASS_RANGER:
- expenseFactor = 1;
- category = 2;
- break;
- default:
- break;
- }
+ SpellsCategory category = c->getSpellsCategory();
+ int expenseFactor = c->getSpellsExpenseFactor();
int spellIndex = _spells[newSelection]._spellIndex;
int spellId = Res.SPELLS_ALLOWED[category][spellIndex];
int spellCost = spells.calcSpellCost(spellId, expenseFactor);
- if (isCasting) {
+ if (mode) {
+ // Casting
selection = newSelection;
} else {
- Common::String spellName = _spells[newSelection]._name;
- Common::String msg = (castingCopy & 0x80) ?
- Common::String::format(Res.SPELLS_PRESS_A_KEY, spellName.c_str()) :
- Common::String::format(Res.SPELLS_PURCHASE, spellName.c_str(), spellCost);
+ // Guild spells dialog: Spells Info or Buy
+ const Common::String &spellName = spells._spellNames[spellId];
+ const Common::String &spellDesc = _textStrings[spellId];
- if (Confirm::show(_vm, msg, castingCopy + 1)) {
+ Common::String msg = (modeCopy & 0x80) ?
+ Common::String::format(Res.SPELL_INFO, spellName.c_str(), spellDesc.c_str()) :
+ Common::String::format(Res.SPELL_PURCHASE, spellDesc.c_str(), spellName.c_str(), spellCost);
+
+ if (Confirm::show(_vm, msg, modeCopy + 1)) {
if (party.subtract(CONS_GOLD, spellCost, WHERE_PARTY, WT_FREEZE_WAIT)) {
c->_spells[spellIndex] = true;
sound.stopSound();
intf._overallFrame = 0;
- sound.playSound(isDarkCc ? "guild12.voc" : "parrot2.voc", 1);
+ sound.playSound(ccNum ? "parrot2.voc" : "guild12.voc", 1);
} else {
sound.playFX(21);
}
@@ -273,11 +241,11 @@ Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int
}
} while (!_vm->shouldExit() && _buttonValue != Common::KEYCODE_ESCAPE);
- windows[25].close();
+ w.close();
if (_vm->shouldExit())
selection = -1;
- if (isCasting && selection != -1)
+ if (mode && selection != -1)
c->_currentSpell = _spells[selection]._spellIndex;
return c;
@@ -305,52 +273,41 @@ void SpellsDialog::loadButtons() {
addPartyButtons(_vm);
}
-const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
+const char *SpellsDialog::setSpellText(Character *c, int mode) {
Party &party = *_vm->_party;
Spells &spells = *_vm->_spells;
- bool isDarkCc = _vm->_files->_isDarkCc;
- int expenseFactor = 0;
+ int ccNum = _vm->_files->_ccNum;
int currLevel = c->getCurrentLevel();
- int category;
+ SpellsCategory category = c->getSpellsCategory();
+ int expenseFactor = c->getSpellsExpenseFactor();
- if ((isCasting & 0x7f) == 0) {
- switch (c->_class) {
- case CLASS_PALADIN:
- expenseFactor = 1;
- category = 0;
- break;
- case CLASS_ARCHER:
- expenseFactor = 1;
- category = 1;
- break;
- case CLASS_CLERIC:
- category = 0;
- break;
- case CLASS_SORCERER:
- category = 1;
- break;
- case CLASS_DRUID:
- category = 2;
- break;
- case CLASS_RANGER:
- expenseFactor = 1;
- category = 2;
- break;
- default:
- category = -1;
- break;
- }
+ if ((mode & 0x7f) == 0) {
+ if (category != SPELLCAT_INVALID) {
+ if (_vm->getGameID() == GType_Swords && party._mazeId == 49) {
+ for (int spellId = 0; spellId < 10; ++spellId) {
+ int idx = 0;
+ while (idx < SPELLS_PER_CLASS && Res.SPELLS_ALLOWED[category][idx] !=
+ Res.DARK_SPELL_OFFSETS[category][spellId])
+ ++idx;
- if (category != -1) {
- if (party._mazeId == 49 || party._mazeId == 37) {
- for (uint spellId = 0; spellId < 76; ++spellId) {
+ if (idx < SPELLS_PER_CLASS) {
+ if (!c->_spells[idx] || (mode & 0x80)) {
+ int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
+ idx, spellId));
+ }
+ }
+ }
+ } else if (party._mazeId == 49 || party._mazeId == 37) {
+ for (uint spellId = 0; spellId < TOTAL_SPELLS; ++spellId) {
int idx = 0;
- while (idx < MAX_SPELLS_PER_CLASS && Res.SPELLS_ALLOWED[category][idx] != (int)spellId)
+ while (idx < SPELLS_PER_CLASS && Res.SPELLS_ALLOWED[category][idx] != (int)spellId)
++idx;
// Handling if the spell is appropriate for the character's class
- if (idx < MAX_SPELLS_PER_CLASS) {
- if (!c->_spells[idx] || (isCasting & 0x80)) {
+ if (idx < SPELLS_PER_CLASS) {
+ if (!c->_spells[idx] || (mode & 0x80)) {
int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
@@ -358,16 +315,38 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
}
}
}
- } else if (isDarkCc) {
- int groupIndex = (party._mazeId - 29) / 2;
- for (int spellId = Res.DARK_SPELL_RANGES[groupIndex][0];
- spellId < Res.DARK_SPELL_RANGES[groupIndex][1]; ++spellId) {
+ } else if (ccNum) {
+ const int *RANGE;
+
+ if (_vm->getGameID() == GType_Swords) {
+ // Set subset of spells to sell in each Swords of Xeen guild
+ int groupIndex;
+ switch (party._mazeId) {
+ case 92:
+ groupIndex = 1;
+ break;
+ case 63:
+ groupIndex = 2;
+ break;
+ case 53:
+ default:
+ groupIndex = 0;
+ break;
+ }
+ RANGE = Res.SWORDS_SPELL_RANGES[category * 4 + groupIndex];
+ } else {
+ int groupIndex = (party._mazeId - 29) / 2;
+ RANGE = Res.DARK_SPELL_RANGES[category * 4 + groupIndex];
+ }
+
+ for (int spellId = RANGE[0]; spellId < RANGE[1]; ++spellId) {
int idx = 0;
- while (idx < 40 && Res.SPELLS_ALLOWED[category][idx] ==
- Res.DARK_SPELL_OFFSETS[category][spellId]);
+ while (idx < SPELLS_PER_CLASS && Res.SPELLS_ALLOWED[category][idx] !=
+ Res.DARK_SPELL_OFFSETS[category][spellId])
+ ++idx;
- if (idx < 40) {
- if (!c->_spells[idx] || (isCasting & 0x80)) {
+ if (idx < SPELLS_PER_CLASS) {
+ if (!c->_spells[idx] || (mode & 0x80)) {
int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
@@ -378,11 +357,12 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
} else {
for (int spellId = 0; spellId < 20; ++spellId) {
int idx = 0;
- while (Res.CLOUDS_SPELL_OFFSETS[party._mazeId - 29][spellId] !=
- (int)Res.SPELLS_ALLOWED[category][idx] && idx < 40) ;
+ while (idx < SPELLS_PER_CLASS && Res.CLOUDS_GUILD_SPELLS[party._mazeId - 28][spellId] !=
+ (int)Res.SPELLS_ALLOWED[category][idx])
+ ++idx;
- if (idx < 40) {
- if (!c->_spells[idx] || (isCasting & 0x80)) {
+ if (idx < SPELLS_PER_CLASS) {
+ if (!c->_spells[idx] || (mode & 0x80)) {
int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
_spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
@@ -396,27 +376,11 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
if (c->getMaxSP() == 0)
return Res.NOT_A_SPELL_CASTER;
- } else if ((isCasting & 0x7f) == 1) {
- switch (c->_class) {
- case CLASS_ARCHER:
- case CLASS_SORCERER:
- category = 1;
- break;
- case CLASS_DRUID:
- case CLASS_RANGER:
- category = 2;
- break;
- case CLASS_PALADIN:
- case CLASS_CLERIC:
- default:
- category = 0;
- break;
- }
-
+ } else if ((mode & 0x7f) == 1) {
if (c->getMaxSP() == 0) {
return Res.NOT_A_SPELL_CASTER;
} else {
- for (int spellIndex = 0; spellIndex < MAX_SPELLS_PER_CLASS; ++spellIndex) {
+ for (int spellIndex = 0; spellIndex < SPELLS_PER_CLASS; ++spellIndex) {
if (c->_spells[spellIndex]) {
int spellId = Res.SPELLS_ALLOWED[category][spellIndex];
int gemCost = Res.SPELL_GEM_COST[spellId];
@@ -430,7 +394,7 @@ const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
}
}
- return nullptr;
+ return _spells.empty() ? Res.SPELLS_LEARNED_ALL : nullptr;
}
/*------------------------------------------------------------------------*/
@@ -460,6 +424,7 @@ int CastSpell::show(XeenEngine *vm) {
Interface &intf = *vm->_interface;
Party &party = *vm->_party;
Spells &spells = *vm->_spells;
+ int result = 0, spellId = 0;
int charNum;
// Get which character is doing the casting
@@ -476,23 +441,17 @@ int CastSpell::show(XeenEngine *vm) {
}
}
+ // Highlight the character
Character *c = &party._activeParty[charNum];
- intf.highlightChar(charNum);
-
- return show(vm, c);
-}
+ intf.highlightChar(c);
-int CastSpell::show(XeenEngine *vm, Character *&c) {
- Spells &spells = *vm->_spells;
CastSpell *dlg = new CastSpell(vm);
- int spellId;
- int result = -1;
-
do {
spellId = dlg->execute(c);
if (g_vm->shouldExit() || spellId == -1) {
- result = 0;
+ result = -1;
+ break;
} else {
result = spells.castSpell(c, (MagicSpell)spellId);
}
@@ -514,9 +473,10 @@ int CastSpell::execute(Character *&c) {
bool redrawFlag = true;
do {
if (redrawFlag) {
- int category = c->getClassCategory();
+ SpellsCategory category = c->getSpellsCategory();
+
int spellIndex = c->_currentSpell != -1 ? c->_currentSpell : 39;
- spellId = Res.SPELLS_ALLOWED[category][spellIndex];
+ spellId = (category == SPELLCAT_INVALID) ? NO_SPELL : Res.SPELLS_ALLOWED[category][spellIndex];
int gemCost = Res.SPELL_GEM_COST[spellId];
int spCost = spells.calcSpellPoints(spellId, c->getCurrentLevel());
@@ -553,6 +513,7 @@ int CastSpell::execute(Character *&c) {
if (_buttonValue < (int)party._activeParty.size()) {
c = &party._activeParty[_buttonValue];
intf.highlightChar(_buttonValue);
+ spells._lastCaster = _buttonValue;
redrawFlag = true;
break;
}
@@ -572,7 +533,7 @@ int CastSpell::execute(Character *&c) {
case Common::KEYCODE_n:
// Select new spell
_vm->_mode = (Mode)_oldMode;
- c = SpellsDialog::show(_vm, this, c, 1);
+ c = SpellsDialog::show(_vm, this, c, SPELLS_DIALOG_SELECT);
redrawFlag = true;
break;
@@ -698,7 +659,7 @@ int SelectElement::execute(int spellId) {
while (result == 999) {
do {
events.updateGameCounter();
- intf.draw3d(true);
+ intf.draw3d(true, false);
w.frame();
w.writeString(Res.WHICH_ELEMENT2);
drawButtons(&windows[0]);
@@ -797,14 +758,14 @@ bool LloydsBeacon::execute() {
Sound &sound = *_vm->_sound;
Windows &windows = *_vm->_windows;
Window &w = windows[10];
- bool isDarkCc = _vm->_files->_isDarkCc;
+ int ccNum = _vm->_files->_ccNum;
Character &c = *combat._oldCharacter;
loadButtons();
if (!c._lloydMap) {
// No destination previously set, so have a default ready
- if (isDarkCc) {
+ if (ccNum) {
c._lloydSide = 1;
c._lloydPosition = Common::Point(25, 21);
c._lloydMap = 29;
@@ -815,19 +776,14 @@ bool LloydsBeacon::execute() {
}
}
- // Open up the text file for the destination map and read in it's name
- File textFile(Common::String::format("%s%c%03d.txt",
- c._lloydSide == 0 ? "xeen" : "dark",
- c._lloydMap >= 100 ? 'x' : '0',
- c._lloydMap));
- Common::String mapName = textFile.readString();
- textFile.close();
+ // Get the destination map name
+ Common::String mapName = Map::getMazeName(c._lloydMap, c._lloydSide);
// Display the dialog
w.open();
- w.writeString(Common::String::format(Res.LLOYDS_BEACON,
- mapName.c_str(), c._lloydPosition.x, c._lloydPosition.y));
- drawButtons(&windows[0]);
+ w.writeString(Common::String::format(Res.LLOYDS_BEACON, mapName.c_str(),
+ c._lloydPosition.x, c._lloydPosition.y));
+ drawButtons(&w);
w.update();
bool result = true;
@@ -847,12 +803,13 @@ bool LloydsBeacon::execute() {
switch (_buttonValue) {
case Common::KEYCODE_r:
- if (!isDarkCc && c._lloydMap >= 75 && c._lloydMap <= 78 && !party._cloudsEnd) {
+ if (!ccNum && c._lloydMap >= XEEN_CASTLE1 && c._lloydMap <= XEEN_CASTLE4 && party._cloudsCompleted) {
+ // Xeen's Castle has already been destroyed
result = false;
} else {
sound.playFX(51);
- map._loadDarkSide = isDarkCc;
- if (c._lloydMap != party._mazeId || c._lloydSide != (isDarkCc ? 1 : 0)) {
+ if (c._lloydMap != party._mazeId || c._lloydSide != ccNum) {
+ map._loadCcNum = c._lloydSide;
map.load(c._lloydMap);
}
@@ -867,7 +824,7 @@ bool LloydsBeacon::execute() {
sound.playFX(20);
c._lloydMap = party._mazeId;
c._lloydPosition = party._mazePosition;
- c._lloydSide = isDarkCc ? 1 : 0;
+ c._lloydSide = ccNum;
_buttonValue = Common::KEYCODE_ESCAPE;
break;
@@ -932,10 +889,9 @@ int Teleport::execute() {
break;
}
- v = map.mazeLookup(pt, map._isOutdoors ? 0xF : 0xFFFF, 0);
+ v = map.mazeLookup(pt, 0, map._isOutdoors ? 0xF : 0xFFFF);
- if ((v != (map._isOutdoors ? 0 : INVALID_CELL)) &&
- (!map._isOutdoors || v == SURFTYPE_DWATER)) {
+ if ((v != (map._isOutdoors ? 0 : INVALID_CELL)) && (!map._isOutdoors || v != SURFTYPE_DWATER)) {
party._mazePosition = pt;
return 1;
} else {
@@ -961,20 +917,35 @@ int TownPortal::execute() {
Mode oldMode = _vm->_mode;
_vm->_mode = MODE_FF;
- // Build up a lsit of the names of the towns on the current side of Xeen
- for (int idx = 0; idx < 5; ++idx) {
- File f(Common::String::format("%s%04d.txt",
- map._sideTownPortal ? "dark" : "xeen",
- Res.TOWN_MAP_NUMBERS[map._sideTownPortal][idx]));
- townNames[idx] = f.readString();
- f.close();
+ w.open();
+
+ if (_vm->getGameID() == GType_Swords) {
+ // Build up a lsit of the names of the towns on the current side of Xeen
+ for (int idx = 0; idx < 3; ++idx) {
+ Common::String txtName = Common::String::format("%s%04d.txt", "dark", Res.TOWN_MAP_NUMBERS[2][idx]);
+ File f(txtName, 1);
+ townNames[idx] = f.readString();
+ f.close();
+ }
+
+ w.writeString(Common::String::format(Res.TOWN_PORTAL_SWORDS, townNames[0].c_str(), townNames[1].c_str(),
+ townNames[2].c_str()));
+ } else {
+ // Build up a lsit of the names of the towns on the current side of Xeen
+ for (int idx = 0; idx < 5; ++idx) {
+ Common::String txtName = Common::String::format("%s%04d.txt", map._sideTownPortal ? "dark" : "xeen",
+ Res.TOWN_MAP_NUMBERS[map._sideTownPortal][idx]);
+ File f(txtName, 1);
+ townNames[idx] = f.readString();
+ f.close();
+ }
+
+ w.writeString(Common::String::format(Res.TOWN_PORTAL,
+ townNames[0].c_str(), townNames[1].c_str(), townNames[2].c_str(),
+ townNames[3].c_str(), townNames[4].c_str()
+ ));
}
- w.open();
- w.writeString(Common::String::format(Res.TOWN_PORTAL,
- townNames[0].c_str(), townNames[1].c_str(), townNames[2].c_str(),
- townNames[3].c_str(), townNames[4].c_str()
- ));
w.update();
// Get the town number
@@ -983,7 +954,7 @@ int TownPortal::execute() {
do {
int result = Input::show(_vm, &w, num, 1, 160, true);
townNumber = !result ? 0 : atoi(num.c_str());
- } while (townNumber > 5);
+ } while (townNumber > (_vm->getGameID() == GType_Swords ? 3 : 5));
w.close();
_vm->_mode = oldMode;
@@ -1032,7 +1003,7 @@ void IdentifyMonster::execute() {
do {
events.updateGameCounter();
- intf.draw3d(false);
+ intf.draw3d(false, false);
w.frame();
windows[3].update();
@@ -1042,4 +1013,62 @@ void IdentifyMonster::execute() {
w.close();
}
+
+/*------------------------------------------------------------------------*/
+
+void DetectMonsters::show(XeenEngine *vm) {
+ DetectMonsters *dlg = new DetectMonsters(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+void DetectMonsters::execute() {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Resources &res = *_vm->_resources;
+ Sound &sound = *_vm->_sound;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[19];
+ int ccNum = _vm->_files->_ccNum;
+ int grid[7][7];
+
+ SpriteResource sprites(ccNum ? "detectmn.icn" : "detctmon.icn");
+ Common::fill(&grid[0][0], &grid[6][6], 0);
+
+ w.open();
+ w.writeString(Res.DETECT_MONSTERS);
+ sprites.draw(w, 0, Common::Point(243, 80));
+
+ for (int yDiff = 3; yDiff >= -3; --yDiff) {
+ for (int xDiff = -3; xDiff <= 3; ++xDiff) {
+ for (uint monIndex = 0; monIndex < map._mobData._monsters.size(); ++monIndex) {
+ MazeMonster &monster = map._mobData._monsters[monIndex];
+ Common::Point pt = party._mazePosition + Common::Point(xDiff, yDiff);
+ if (monster._position == pt) {
+ int &gridEntry = grid[yDiff + 3][xDiff + 3];
+ if (++gridEntry > 3)
+ gridEntry = 3;
+
+ sprites.draw(w, gridEntry, Common::Point(271 + xDiff * 9, 102 - yDiff * 7));
+ }
+ }
+ }
+ }
+
+ res._globalSprites.draw(w, party._mazeDirection + 1, Common::Point(270, 101));
+ sound.playFX(20);
+ w.update();
+
+ while (!g_vm->shouldExit() && !events.isKeyMousePressed()) {
+ events.updateGameCounter();
+ intf.draw3d(true);
+
+ events.wait(1, false);
+ }
+
+ w.close();
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/dialogs/dialogs_spells.h b/engines/xeen/dialogs/dialogs_spells.h
index 2bcaef43e5..26c3f00428 100644
--- a/engines/xeen/dialogs/dialogs_spells.h
+++ b/engines/xeen/dialogs/dialogs_spells.h
@@ -29,6 +29,10 @@
namespace Xeen {
+enum SpellDialogMode {
+ SPELLS_DIALOG_BUY = 0, SPELLS_DIALOG_SELECT = 1, SPELLS_DIALOG_INFO = 0x80
+};
+
struct SpellEntry {
Common::String _name;
int _spellIndex;
@@ -39,22 +43,41 @@ struct SpellEntry {
_name(name), _spellIndex(spellIndex), _spellId(spellId), _color(9) {}
};
+/**
+ * Spells list dialog. Used for both selecting spells to cast, as well as the
+ * spells listing when visiting Guild locations
+ */
class SpellsDialog : public ButtonContainer {
private:
SpriteResource _iconSprites;
SpriteResource _scrollSprites;
Common::Array<SpellEntry> _spells;
+ /**
+ * Constructor
+ */
SpellsDialog(XeenEngine *vm) : ButtonContainer(vm) {}
- Character *execute(ButtonContainer *priorDialog, Character *c, int isCasting);
+ /**
+ * Executes the dialog
+ */
+ Character *execute(ButtonContainer *priorDialog, Character *c, int mode);
+ /**
+ * Loads buttons for the dialog
+ */
void loadButtons();
+ /**
+ * Sets the spell text
+ */
const char *setSpellText(Character *c, int isCasting);
public:
+ /**
+ * Show the spells list dialog
+ */
static Character *show(XeenEngine *vm, ButtonContainer *priorDialog,
- Character *c, int isCasting);
+ Character *c, SpellDialogMode mode);
};
class CastSpell : public ButtonContainer {
@@ -70,7 +93,6 @@ private:
void loadButtons();
public:
static int show(XeenEngine *vm);
- static int show(XeenEngine *vm, Character *&c);
};
class SpellOnWho : public ButtonContainer {
@@ -146,6 +168,15 @@ public:
static void show(XeenEngine *vm);
};
+class DetectMonsters : public ButtonContainer {
+private:
+ DetectMonsters(XeenEngine *vm) : ButtonContainer(vm) {}
+
+ void execute();
+public:
+ static void show(XeenEngine *vm);
+};
+
} // End of namespace Xeen
#endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/events.cpp b/engines/xeen/events.cpp
index 6ceef4406b..17306a32fc 100644
--- a/engines/xeen/events.cpp
+++ b/engines/xeen/events.cpp
@@ -31,9 +31,9 @@
namespace Xeen {
-EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), _playTime(0),
- _frameCounter(0), _priorFrameCounterTime(0), _gameCounter(0),
- _leftButton(false), _rightButton(false), _sprites("mouse.icn") {
+EventsManager::EventsManager(XeenEngine *vm) : _vm(vm), _playTime(0), _gameCounter(0),
+ _frameCounter(0), _priorFrameCounterTime(0), _priorScreenRefreshTime(0),
+ _mousePressed(false), _sprites("mouse.icn") {
Common::fill(&_gameCounters[0], &_gameCounters[6], 0);
}
@@ -62,7 +62,15 @@ bool EventsManager::isCursorVisible() {
void EventsManager::pollEvents() {
uint32 timer = g_system->getMillis();
+
+ if (timer >= (_priorScreenRefreshTime + SCREEN_UPDATE_TIME)) {
+ // Refresh the screen at a higher frame rate than the game's own frame rate
+ // to allow for more responsive mouse movement
+ _priorScreenRefreshTime = timer;
+ g_vm->_screen->update();
+ }
if (timer >= (_priorFrameCounterTime + GAME_FRAME_TIME)) {
+ // Time to build up next game frame
_priorFrameCounterTime = timer;
nextFrame();
}
@@ -80,24 +88,24 @@ void EventsManager::pollEvents() {
_vm->_debugger->attach();
_vm->_debugger->onFrame();
} else {
- _keys.push(event.kbd);
+ addEvent(event.kbd);
}
break;
case Common::EVENT_MOUSEMOVE:
_mousePos = event.mouse;
break;
case Common::EVENT_LBUTTONDOWN:
- _leftButton = true;
- return;
- case Common::EVENT_LBUTTONUP:
- _leftButton = false;
+ _mousePressed = true;
+ addEvent(true, false);
return;
case Common::EVENT_RBUTTONDOWN:
- _rightButton = true;
+ _mousePressed = true;
+ addEvent(false, true);
return;
+ case Common::EVENT_LBUTTONUP:
case Common::EVENT_RBUTTONUP:
- _rightButton = false;
- break;
+ _mousePressed = false;
+ return;
default:
break;
}
@@ -110,31 +118,38 @@ void EventsManager::pollEventsAndWait() {
}
void EventsManager::clearEvents() {
- _keys.clear();
- _leftButton = _rightButton = false;
-
+ _pendingEvents.clear();
+ _mousePressed = false;
}
void EventsManager::debounceMouse() {
- while (_leftButton && !_vm->shouldExit()) {
+ while (_mousePressed && !_vm->shouldExit()) {
pollEventsAndWait();
}
}
-bool EventsManager::getKey(Common::KeyState &key) {
- if (_keys.empty()) {
+
+void EventsManager::addEvent(const Common::KeyState &keyState) {
+ if (_pendingEvents.size() < MAX_PENDING_EVENTS)
+ _pendingEvents.push(PendingEvent(keyState));
+}
+
+void EventsManager::addEvent(bool leftButton, bool rightButton) {
+ if (_pendingEvents.size() < MAX_PENDING_EVENTS)
+ _pendingEvents.push(PendingEvent(leftButton, rightButton));
+}
+
+
+bool EventsManager::getEvent(PendingEvent &pe) {
+ if (_pendingEvents.empty()) {
return false;
} else {
- key = _keys.pop();
+ pe = _pendingEvents.pop();
return true;
}
}
-bool EventsManager::isKeyPending() const {
- return !_keys.empty();
-}
-
bool EventsManager::isKeyMousePressed() {
- bool result = _leftButton || _rightButton || isKeyPending();
+ bool result = isEventPending();
debounceMouse();
clearEvents();
@@ -144,7 +159,7 @@ bool EventsManager::isKeyMousePressed() {
bool EventsManager::wait(uint numFrames, bool interruptable) {
while (!_vm->shouldExit() && timeElapsed() < numFrames) {
pollEventsAndWait();
- if (interruptable && (_leftButton || _rightButton || isKeyPending()))
+ if (interruptable && isEventPending())
return true;
}
@@ -200,9 +215,4 @@ void EventsManager::nextFrame() {
_vm->_screen->update();
}
-/*------------------------------------------------------------------------*/
-
-GameEvent::GameEvent() {
-}
-
} // End of namespace Xeen
diff --git a/engines/xeen/events.h b/engines/xeen/events.h
index 0ef2c3a9e7..9913b2fbf1 100644
--- a/engines/xeen/events.h
+++ b/engines/xeen/events.h
@@ -32,30 +32,52 @@ namespace Xeen {
#define GAME_FRAME_RATE (1000 / 50)
#define GAME_FRAME_TIME 50
+#define SCREEN_UPDATE_TIME 10
+#define MAX_PENDING_EVENTS 5
class XeenEngine;
+struct PendingEvent {
+ Common::KeyState _keyState;
+ bool _leftButton;
+ bool _rightButton;
+
+ PendingEvent() : _leftButton(false), _rightButton(false) {}
+ PendingEvent(const Common::KeyState &keyState) : _keyState(keyState), _leftButton(false), _rightButton(false) {}
+ PendingEvent(bool leftButton, bool rightButton) : _leftButton(leftButton), _rightButton(rightButton) {}
+
+ /**
+ * Returns true if a keyboard event is pending
+ */
+ bool isKeyboard() const { return _keyState.keycode != Common::KEYCODE_INVALID; }
+
+ /**
+ * Returns ture if a mouse button event is pending
+ */
+ bool isMouse() const { return _leftButton || _rightButton; }
+};
+
class EventsManager {
private:
XeenEngine *_vm;
uint32 _frameCounter;
uint32 _priorFrameCounterTime;
+ uint32 _priorScreenRefreshTime;
uint32 _gameCounter;
uint32 _gameCounters[6];
uint32 _playTime;
- Common::Queue<Common::KeyState> _keys;
+ Common::Queue<PendingEvent> _pendingEvents;
SpriteResource _sprites;
+ bool _mousePressed;
/**
* Handles moving to the next game frame
*/
void nextFrame();
public:
- bool _leftButton, _rightButton;
Common::Point _mousePos;
public:
EventsManager(XeenEngine *vm);
-
~EventsManager();
/*
@@ -78,17 +100,45 @@ public:
*/
bool isCursorVisible();
+ /**
+ * Polls the ScummVM backend for any pending events
+ */
void pollEvents();
+ /**
+ * Polls for events, and wait a slight delay. This ensures the game doesn't use up 100% of the CPU
+ */
void pollEventsAndWait();
+ /**
+ * Clears all pending events
+ */
void clearEvents();
+ /**
+ * Waits for a mouse press to be released
+ */
void debounceMouse();
- bool getKey(Common::KeyState &key);
+ /**
+ * Adds a keyboard event to the queue
+ */
+ void addEvent(const Common::KeyState &keyState);
- bool isKeyPending() const;
+ /**
+ * Adds a mouse button event to the queue
+ */
+ void addEvent(bool leftButton, bool rightButton);
+
+ /**
+ * Returns the next pending key/mouse press, if any
+ */
+ bool getEvent(PendingEvent &pe);
+
+ /**
+ * Returns true if a key or mouse event is pending
+ */
+ bool isEventPending() const { return !_pendingEvents.empty(); }
/**
* Returns true if a key or mouse press is pending
@@ -141,11 +191,6 @@ public:
void waitForPress();
};
-class GameEvent {
-public:
- GameEvent();
-};
-
} // End of namespace Xeen
#endif /* XEEN_EVENTS_H */
diff --git a/engines/xeen/files.cpp b/engines/xeen/files.cpp
index 83a4ca9072..d18b5c4dd6 100644
--- a/engines/xeen/files.cpp
+++ b/engines/xeen/files.cpp
@@ -218,7 +218,7 @@ Common::SeekableReadStream *CCArchive::createReadStreamForMember(const Common::S
/*------------------------------------------------------------------------*/
FileManager::FileManager(XeenEngine *vm) {
- _isDarkCc = vm->getGameID() == GType_DarkSide;
+ _ccNum = vm->getGameID() == GType_DarkSide;
File::_xeenCc = File::_darkCc = File::_introCc = nullptr;
File::_xeenSave = File::_darkSave = nullptr;
File::_currentSave = nullptr;
@@ -277,7 +277,7 @@ void FileManager::setGameCc(int ccMode) {
}
File::setCurrentArchive(ccMode);
- _isDarkCc = ccMode != 0;
+ _ccNum = ccMode != 0;
}
void FileManager::load(Common::SeekableReadStream &stream) {
@@ -285,7 +285,7 @@ void FileManager::load(Common::SeekableReadStream &stream) {
}
void FileManager::save(Common::WriteStream &s) {
- s.writeByte(_isDarkCc ? 1 : 0);
+ s.writeByte(_ccNum ? 1 : 0);
}
/*------------------------------------------------------------------------*/
@@ -330,7 +330,7 @@ bool File::open(const Common::String &filename, Common::Archive &archive) {
bool File::open(const Common::String &filename, int ccMode) {
FileManager &files = *g_vm->_files;
- int oldMode = files._isDarkCc ? 1 : 0;
+ int oldNum = files._ccNum;
files.setGameCc(ccMode);
if (File::exists(filename, *_currentArchive))
@@ -338,7 +338,7 @@ bool File::open(const Common::String &filename, int ccMode) {
else
File::open(filename);
- files.setGameCc(oldMode);
+ files.setGameCc(oldNum);
return true;
}
@@ -390,11 +390,11 @@ bool File::exists(const Common::String &filename) {
bool File::exists(const Common::String &filename, int ccMode) {
FileManager &files = *g_vm->_files;
- int oldMode = files._isDarkCc ? 1 : 0;
+ int oldNum = files._ccNum;
files.setGameCc(ccMode);
bool result = exists(filename);
- files.setGameCc(oldMode);
+ files.setGameCc(oldNum);
return result;
}
@@ -480,6 +480,7 @@ Common::SeekableReadStream *SaveArchive::createReadStreamForMember(uint16 id) co
}
void SaveArchive::load(Common::SeekableReadStream &stream) {
+ _newData.clear();
loadIndex(stream);
delete[] _data;
@@ -487,8 +488,10 @@ void SaveArchive::load(Common::SeekableReadStream &stream) {
_data = new byte[_dataSize];
stream.seek(0);
stream.read(_data, _dataSize);
+}
- // Load in the character stats and active party
+void SaveArchive::loadParty() {
+ // Load in the character roster and active party
Common::SeekableReadStream *chr = createReadStreamForMember("maze.chr");
Common::Serializer sChr(chr, nullptr);
_party->_roster.synchronize(sChr);
@@ -503,6 +506,7 @@ void SaveArchive::load(Common::SeekableReadStream &stream) {
void SaveArchive::reset(CCArchive *src) {
Common::MemoryWriteStreamDynamic saveFile(DisposeAfterUse::YES);
File fIn;
+ _newData.clear();
g_vm->_files->setGameCc(g_vm->getGameID() == GType_DarkSide ? 1 : 0);
const int RESOURCES[6] = { 0x2A0C, 0x2A1C, 0x2A2C, 0x2A3C, 0x284C, 0x2A5C };
diff --git a/engines/xeen/files.h b/engines/xeen/files.h
index 306ec96657..0d421547fb 100644
--- a/engines/xeen/files.h
+++ b/engines/xeen/files.h
@@ -77,13 +77,13 @@ struct CCEntry {
*/
class FileManager {
public:
- bool _isDarkCc;
+ int _ccNum;
public:
/**
* Constructor
*/
FileManager(XeenEngine *vm);
-
+
/**
* Destructor
*/
@@ -352,6 +352,11 @@ public:
void save(Common::WriteStream &s);
/**
+ * Load the character roster and party
+ */
+ void loadParty();
+
+ /**
* Sets a new resource entry
*/
void replaceEntry(uint16 id, const byte *data, size_t size);
@@ -373,7 +378,7 @@ public:
/**
* Finishes any pending writes, pushing out the written data
*/
- void finalize();
+ void finalize() override;
/**
* Writes data
diff --git a/engines/xeen/font.cpp b/engines/xeen/font.cpp
index 58381e1516..d5f05bac0a 100644
--- a/engines/xeen/font.cpp
+++ b/engines/xeen/font.cpp
@@ -218,7 +218,7 @@ const char *FontSurface::writeString(const Common::String &s, const Common::Rect
} else if (c == 10) {
// Newline
if (newLine(bounds))
- break;
+ return _displayString;
} else if (c == 11) {
// Set y position
int yp = fontAtoi();
@@ -330,6 +330,7 @@ void FontSurface::writeChar(char c, const Common::Rect &clipRect) {
int y = _writePos.y;
if (c == 'g' || c == 'p' || c == 'q' || c == 'y')
++y;
+ int yStart = y;
// Get pointers into font data and surface to write pixels to
int charIndex = (int)c + (_fontReduced ? 0x80 : 0);
@@ -354,8 +355,8 @@ void FontSurface::writeChar(char c, const Common::Rect &clipRect) {
}
}
- addDirtyRect(Common::Rect(_writePos.x, _writePos.y, _writePos.x + FONT_WIDTH,
- _writePos.y + FONT_HEIGHT));
+ addDirtyRect(Common::Rect(_writePos.x, yStart, _writePos.x + FONT_WIDTH,
+ yStart + FONT_HEIGHT));
_writePos.x += _fontData[0x1000 + charIndex];
}
diff --git a/engines/xeen/interface.cpp b/engines/xeen/interface.cpp
index 3d9f05b5a2..82a2cbd7d1 100644
--- a/engines/xeen/interface.cpp
+++ b/engines/xeen/interface.cpp
@@ -103,6 +103,7 @@ void PartyDrawer::drawParty(bool updateFlag) {
void PartyDrawer::highlightChar(int charId) {
Resources &res = *_vm->_resources;
Windows &windows = *_vm->_windows;
+ assert(charId < MAX_ACTIVE_PARTY);
if (charId != _hiliteChar && _hiliteChar != HILIGHT_CHAR_DISABLED) {
// Handle deselecting any previusly selected char
@@ -118,6 +119,12 @@ void PartyDrawer::highlightChar(int charId) {
}
}
+void PartyDrawer::highlightChar(const Character *c) {
+ int charNum = _vm->_party->_activeParty.indexOf(*c);
+ if (charNum != -1)
+ highlightChar(charNum);
+}
+
void PartyDrawer::unhighlightChar() {
Resources &res = *_vm->_resources;
Windows &windows = *_vm->_windows;
@@ -156,6 +163,7 @@ Interface::Interface(XeenEngine *vm) : ButtonContainer(vm), InterfaceScene(vm),
_upDoorText = false;
_tillMove = 0;
Common::fill(&_charFX[0], &_charFX[MAX_ACTIVE_PARTY], 0);
+ _waitBounds = Common::Rect(8, 8, 224, 140);
}
void Interface::setup() {
@@ -202,7 +210,7 @@ void Interface::mainIconsPrint() {
Windows &windows = *_vm->_windows;
windows[38].close();
windows[12].close();
-
+
res._globalSprites.draw(0, 7, Common::Point(232, 74));
drawButtons(&windows[0]);
windows[34].update();
@@ -255,23 +263,22 @@ void Interface::perform() {
Party &party = *_vm->_party;
Scripts &scripts = *_vm->_scripts;
Sound &sound = *_vm->_sound;
- Spells &spells = *_vm->_spells;
- const Common::Rect WAIT_BOUNDS(8, 8, 224, 140);
- events.updateGameCounter();
- draw3d(true);
-
- // Wait for a frame or a user event
do {
- events.pollEventsAndWait();
- checkEvents(_vm);
+ // Draw the next frame
+ events.updateGameCounter();
+ draw3d(true);
- if (events._leftButton && WAIT_BOUNDS.contains(events._mousePos))
- _buttonValue = Common::KEYCODE_SPACE;
- } while (!_buttonValue && events.timeElapsed() < 1 && !_vm->_party->_partyDead);
+ // Wait for a frame or a user event
+ _buttonValue = 0;
+ do {
+ events.pollEventsAndWait();
+ if (g_vm->shouldExit() || g_vm->isLoadPending() || party._dead)
+ return;
- if (!_buttonValue && !_vm->_party->_partyDead)
- return;
+ checkEvents(g_vm);
+ } while (!_buttonValue && events.timeElapsed() < 1);
+ } while (!_buttonValue);
if (_buttonValue == Common::KEYCODE_SPACE) {
int lookupId = map.mazeLookup(party._mazePosition,
@@ -281,28 +288,24 @@ void Interface::perform() {
switch (lookupId) {
case 1:
if (!map._isOutdoors) {
- scripts.openGrate(13, 1);
- eventsFlag = _buttonValue != 0;
+ eventsFlag = !scripts.openGrate(13, 1);
}
break;
case 6:
// Open grate being closed
if (!map._isOutdoors) {
- scripts.openGrate(9, 0);
- eventsFlag = _buttonValue != 0;
+ eventsFlag = !scripts.openGrate(9, 0);
}
break;
case 9:
// Closed grate being opened
if (!map._isOutdoors) {
- scripts.openGrate(6, 0);
- eventsFlag = _buttonValue != 0;
+ eventsFlag = !scripts.openGrate(6, 0);
}
break;
case 13:
if (!map._isOutdoors) {
- scripts.openGrate(1, 1);
- eventsFlag = _buttonValue != 0;
+ eventsFlag = !scripts.openGrate(1, 1);
}
break;
default:
@@ -312,6 +315,8 @@ void Interface::perform() {
scripts.checkEvents();
if (_vm->shouldExit())
return;
+ } else {
+ clearEvents();
}
}
@@ -460,6 +465,13 @@ void Interface::perform() {
}
break;
+ case (Common::KBD_CTRL << 16) | Common::KEYCODE_DOWN:
+ party._mazeDirection = (Direction)((int)party._mazeDirection ^ 2);
+ _flipSky = !_flipSky;
+ _isAnimReset = true;
+ stepTime();
+ break;
+
case Common::KEYCODE_F1:
case Common::KEYCODE_F2:
case Common::KEYCODE_F3:
@@ -508,25 +520,18 @@ void Interface::perform() {
}
break;
- case Common::KEYCODE_c: {
+ case Common::KEYCODE_c:
// Cast spell
if (_tillMove) {
combat.moveMonsters();
draw3d(true);
}
- Character *c = &party._activeParty[(spells._lastCaster < 0 ||
- spells._lastCaster >= (int)party._activeParty.size()) ?
- (int)party._activeParty.size() - 1 : spells._lastCaster];
-
- int result = CastSpell::show(_vm, c);
-
- if (result == 1) {
+ if (CastSpell::show(_vm) != -1) {
chargeStep();
doStepCode();
}
break;
- }
case Common::KEYCODE_i:
// Show Info dialog
@@ -562,7 +567,7 @@ void Interface::perform() {
if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1
|| combat._attackMonsters[2] != -1) {
- if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING)
+ if ((_vm->_mode == MODE_INTERACTIVE || _vm->_mode == MODE_SLEEPING)
&& !combat._monstersAttacking && !_charsShooting) {
doCombat();
}
@@ -585,7 +590,7 @@ void Interface::perform() {
}
void Interface::chargeStep() {
- if (!_vm->_party->_partyDead) {
+ if (!_vm->_party->_dead) {
_vm->_party->changeTime(_vm->_map->_isOutdoors ? 10 : 1);
if (_tillMove) {
_vm->_combat->moveMonsters();
@@ -628,7 +633,7 @@ void Interface::doStepCode() {
switch (surfaceId) {
case SURFTYPE_SPACE:
// Wheeze.. can't breathe in space! Explosive decompression, here we come
- party._partyDead = true;
+ party._dead = true;
break;
case SURFTYPE_LAVA:
// It burns, it burns!
@@ -657,7 +662,7 @@ void Interface::doStepCode() {
break;
}
- if (_vm->_files->_isDarkCc && party._gameFlags[1][118]) {
+ if (_vm->getGameID() != GType_Swords && _vm->_files->_ccNum && party._gameFlags[1][118]) {
_falling = FALL_NONE;
} else {
if (_falling != FALL_NONE)
@@ -678,7 +683,7 @@ void Interface::doStepCode() {
combat._combatTarget = oldTarget;
_flipGround = !_flipGround;
- } else if (party._partyDead) {
+ } else if (party._dead) {
draw3d(true);
}
}
@@ -688,9 +693,9 @@ void Interface::startFalling(bool flag) {
Combat &combat = *_vm->_combat;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
- bool isDarkCc = _vm->_files->_isDarkCc;
+ int ccNum = _vm->_files->_ccNum;
- if (isDarkCc && party._gameFlags[1][118]) {
+ if (ccNum && party._gameFlags[1][118]) {
_falling = FALL_NONE;
return;
}
@@ -700,10 +705,10 @@ void Interface::startFalling(bool flag) {
_falling = FALL_START;
draw3d(false);
- if (flag && (!isDarkCc || party._fallMaze != 0)) {
+ if (flag && (!ccNum || party._fallMaze != 0)) {
party._mazeId = party._fallMaze;
party._mazePosition = party._fallPosition;
- } else if (!isDarkCc) {
+ } else if (!ccNum) {
switch (party._mazeId - 25) {
case 0:
case 26:
@@ -768,8 +773,8 @@ void Interface::startFalling(bool flag) {
break;
}
} else {
- if (party._mazeId > 89 && party._mazeId < 113) {
- party._mazeId += 168;
+ if (party._mazeId > 88 && party._mazeId < 114) {
+ party._mazeId -= 88;
} else {
switch (party._mazeId - 25) {
case 0:
@@ -848,7 +853,7 @@ void Interface::startFalling(bool flag) {
break;
case 103:
case 104:
- map._loadDarkSide = false;
+ map._loadCcNum = 0;
party._mazeId = 8;
party._mazePosition = Common::Point(11, 15);
party._mazeDirection = DIR_NORTH;
@@ -893,11 +898,18 @@ void Interface::startFalling(bool flag) {
}
bool Interface::checkMoveDirection(int key) {
+ Debugger &debugger = *g_vm->_debugger;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
- Direction dir = party._mazeDirection;
+ // If intangibility is turned on in the debugger, allow any movement
+ if (debugger._intangible)
+ return true;
+
+ // For strafing or moving backwards, temporarily move to face the direction being checked,
+ // since the call to getCell will the adjacent cell details in the direction being faced
+ Direction dir = party._mazeDirection;
switch (key) {
case (Common::KBD_CTRL << 16) | Common::KEYCODE_LEFT:
party._mazeDirection = (party._mazeDirection == DIR_NORTH) ? DIR_WEST :
@@ -914,16 +926,19 @@ bool Interface::checkMoveDirection(int key) {
break;
}
+ // Get next facing tile information
map.getCell(7);
+
int startSurfaceId = map._currentSurfaceId;
int surfaceId;
if (map._isOutdoors) {
+ // Reset direction back to original facing, if it was changed for strafing checks
party._mazeDirection = dir;
switch (map._currentWall) {
case 5:
- if (_vm->_files->_isDarkCc)
+ if (_vm->_files->_ccNum)
goto check;
// fall through
@@ -965,18 +980,16 @@ bool Interface::checkMoveDirection(int key) {
}
} else {
surfaceId = map.getCell(2);
+
+ // Reset direction back to original facing, if it was changed for strafing checks
+ party._mazeDirection = dir;
+
if (surfaceId >= map.mazeData()._difficulties._wallNoPass) {
- party._mazeDirection = dir;
sound.playFX(46);
return false;
} else {
- party._mazeDirection = dir;
-
- if (startSurfaceId == SURFTYPE_SWAMP || party.checkSkill(SWIMMING) ||
+ if (startSurfaceId != SURFTYPE_SWAMP || party.checkSkill(SWIMMING) ||
party._walkOnWaterActive) {
- sound.playFX(46);
- return false;
- } else {
if (_buttonValue == Common::KEYCODE_UP && _wo[107]) {
_openDoor = true;
sound.playFX(47);
@@ -984,6 +997,9 @@ bool Interface::checkMoveDirection(int key) {
_openDoor = false;
}
return true;
+ } else {
+ sound.playFX(46);
+ return false;
}
}
}
@@ -998,7 +1014,7 @@ void Interface::rest() {
map.cellFlagLookup(party._mazePosition);
if ((map._currentCantRest || (map.mazeData()._mazeFlags & RESTRICTION_REST))
- && _vm->_mode != MODE_12) {
+ && _vm->_mode != MODE_INTERACTIVE2) {
ErrorScroll::show(_vm, Res.TOO_DANGEROUS_TO_REST, WT_NONFREEZED_WAIT);
} else {
// Check whether any character is in danger of dying
@@ -1024,14 +1040,14 @@ void Interface::rest() {
Mode oldMode = _vm->_mode;
_vm->_mode = MODE_SLEEPING;
- if (oldMode == MODE_12) {
+ if (oldMode == MODE_INTERACTIVE2) {
party.changeTime(8 * 60);
} else {
for (int idx = 0; idx < 10; ++idx) {
chargeStep();
draw3d(true);
- if (_vm->_mode == MODE_1) {
+ if (_vm->_mode == MODE_INTERACTIVE) {
_vm->_mode = oldMode;
return;
}
@@ -1068,6 +1084,10 @@ void Interface::rest() {
c._conditions[UNCONSCIOUS] = 0;
c._currentHp = c.getMaxHP();
c._currentSp = c.getMaxSP();
+
+ // WORKAROUND: Resting curing weakness only originally worked due to a bug in changeTime
+ // resetting WEAK if party wasn't drunk. With that resolved, we have to reset WEAK here
+ c._conditions[WEAK] = 0;
}
}
}
@@ -1189,7 +1209,7 @@ void Interface::draw3d(bool updateFlag, bool pauseFlag) {
_flipUIFrame = (_flipUIFrame + 1) % 4;
if (_flipUIFrame == 0)
_flipWater = !_flipWater;
- if (_tillMove && (_vm->_mode == MODE_1 || _vm->_mode == MODE_COMBAT) &&
+ if (_tillMove && (_vm->_mode == MODE_INTERACTIVE || _vm->_mode == MODE_COMBAT) &&
!combat._monstersAttacking && combat._moveMonsters) {
if (--_tillMove == 0)
combat.moveMonsters();
@@ -1225,7 +1245,7 @@ void Interface::draw3d(bool updateFlag, bool pauseFlag) {
if (combat._attackMonsters[0] != -1 || combat._attackMonsters[1] != -1
|| combat._attackMonsters[2] != -1) {
- if ((_vm->_mode == MODE_1 || _vm->_mode == MODE_SLEEPING) &&
+ if ((_vm->_mode == MODE_INTERACTIVE || _vm->_mode == MODE_SLEEPING) &&
!combat._monstersAttacking && !_charsShooting && combat._moveMonsters) {
doCombat();
if (scripts._eventSkipped)
@@ -1357,9 +1377,9 @@ void Interface::assembleBorder() {
_face2UIFrame = (_face2UIFrame + 1) % 4 + 12;
if (_face2State == 0)
- _face2UIFrame += 252;
+ _face2UIFrame -= 3;
else if (_face2State == 2)
- _face2UIFrame = 0;
+ _face2UIFrame = 8;
if (!_vm->_party->_clairvoyanceActive) {
_face1UIFrame = 0;
@@ -1422,8 +1442,7 @@ void Interface::assembleBorder() {
// Draw direction character if direction sense is active
if (_vm->_party->checkSkill(DIRECTION_SENSE) && !_vm->_noDirectionSense) {
const char *dirText = Res.DIRECTION_TEXT_UPPER[_vm->_party->_mazeDirection];
- Common::String msg = Common::String::format(
- "\002""08\003""c\013""139\011""116%c\014""d\001", *dirText);
+ Common::String msg = Common::String::format("\x2\f08\x3""c\v139\t116%c\fd\x1", *dirText);
windows[0].writeString(msg);
}
@@ -1438,11 +1457,11 @@ void Interface::doCombat() {
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Scripts &scripts = *_vm->_scripts;
- Spells &spells = *_vm->_spells;
Sound &sound = *_vm->_sound;
Windows &windows = *_vm->_windows;
bool upDoorText = _upDoorText;
bool reloadMap = false;
+ int index = 0;
_upDoorText = false;
combat._combatMode = COMBATMODE_2;
@@ -1454,7 +1473,6 @@ void Interface::doCombat() {
mainIconsPrint();
combat._combatParty.clear();
- combat._charsGone.clear();
combat.clearBlocked();
combat._pow[0]._duration = 0;
combat._pow[1]._duration = 0;
@@ -1467,9 +1485,8 @@ void Interface::doCombat() {
combat.setSpeedTable();
// Initialize arrays for character/monster states
- combat._charsGone.resize(combat._speedTable.size());
- Common::fill(&combat._charsGone[0], &combat._charsGone[0] + combat._speedTable.size(), 0);
- Common::fill(&combat._charsBlocked[0], &combat._charsBlocked[0] + combat._speedTable.size(), false);
+ Common::fill(&combat._charsGone[0], &combat._charsGone[PARTY_AND_MONSTERS], 0);
+ Common::fill(&combat._charsBlocked[0], &combat._charsBlocked[PARTY_AND_MONSTERS], false);
combat._whosSpeed = -1;
combat._whosTurn = -1;
@@ -1489,18 +1506,24 @@ void Interface::doCombat() {
w.open();
bool breakFlag = false;
- while (!_vm->shouldExit() && !breakFlag) {
+ while (!_vm->shouldExit() && !breakFlag && !party._dead && _vm->_mode == MODE_COMBAT) {
+ // FIXME: I've had a rare issue where the loop starts with a non-party _whosTurn. Unfortunately,
+ // I haven't been able to consistently replicate and diagnose the problem, so for now,
+ // I'm simply detecting if it happens and resetting the combat round
+ if (combat._whosTurn >= (int)party._activeParty.size())
+ goto new_round;
+
highlightChar(combat._whosTurn);
combat.setSpeedTable();
// Write out the description of the monsters being battled
w.writeString(combat.getMonsterDescriptions());
_combatIcons.draw(0, 32, Common::Point(233, combat._attackDurationCtr * 10 + 27),
- SPRFLAG_800, 1);
+ SPRFLAG_800, 0);
w.update();
// Wait for keypress
- int index = 0;
+ index = 0;
do {
events.updateGameCounter();
draw3d(true);
@@ -1517,7 +1540,7 @@ void Interface::doCombat() {
} while (!_vm->shouldExit() && events.timeElapsed() < 1 && !_buttonValue);
} while (!_vm->shouldExit() && !_buttonValue);
if (_vm->shouldExit())
- return;
+ goto exit;
switch (_buttonValue) {
case Common::KEYCODE_TAB:
@@ -1554,13 +1577,10 @@ void Interface::doCombat() {
case Common::KEYCODE_c: {
// Cast spell
- int spellId = CastSpell::show(_vm);
- if (spellId != -1) {
- Character *c = combat._combatParty[combat._whosTurn];
- spells.castSpell(c, (MagicSpell)spellId);
+ if (CastSpell::show(_vm) != -1) {
nextChar();
} else {
- highlightChar(combat._combatParty[combat._whosTurn]->_rosterId);
+ highlightChar(combat._whosTurn);
}
break;
}
@@ -1594,7 +1614,7 @@ void Interface::doCombat() {
combat.run();
nextChar();
- if (_vm->_mode == MODE_1) {
+ if (_vm->_mode == MODE_INTERACTIVE) {
party._treasure._gems = 0;
party._treasure._gold = 0;
party._treasure._hasItems = false;
@@ -1649,7 +1669,8 @@ void Interface::doCombat() {
// Handling for if the combat turn is complete
if (combat.allHaveGone()) {
- Common::fill(&combat._charsGone[0], &combat._charsGone[0] + combat._charsGone.size(), false);
+new_round:
+ Common::fill(&combat._charsGone[0], &combat._charsGone[PARTY_AND_MONSTERS], false);
combat.clearBlocked();
combat.setSpeedTable();
combat._whosTurn = -1;
@@ -1681,11 +1702,9 @@ void Interface::doCombat() {
}
party.checkPartyDead();
- if (party._dead || _vm->_mode != MODE_COMBAT)
- break;
}
- _vm->_mode = MODE_1;
+ _vm->_mode = MODE_INTERACTIVE;
if (combat._partyRan && (combat._attackMonsters[0] != -1 ||
combat._attackMonsters[1] != -1 || combat._attackMonsters[2] != -1)) {
party.checkPartyDead();
@@ -1699,14 +1718,14 @@ void Interface::doCombat() {
}
}
}
-
+exit:
w.close();
events.clearEvents();
_vm->_mode = MODE_COMBAT;
draw3d(true);
party.giveTreasure();
- _vm->_mode = MODE_1;
+ _vm->_mode = MODE_INTERACTIVE;
party._stepped = true;
unhighlightChar();
@@ -1719,21 +1738,23 @@ void Interface::doCombat() {
mainIconsPrint();
combat._monster2Attack = -1;
- if (upDoorText) {
- map.cellFlagLookup(party._mazePosition);
- if (map._currentIsEvent)
- scripts.checkEvents();
- }
+ if (!g_vm->isLoadPending()) {
+ if (upDoorText) {
+ map.cellFlagLookup(party._mazePosition);
+ if (map._currentIsEvent)
+ scripts.checkEvents();
+ }
- if (reloadMap) {
- sound.playFX(51);
- map._loadDarkSide = _vm->getGameID() != GType_WorldOfXeen;
- map.load(_vm->getGameID() == GType_WorldOfXeen ? 28 : 29);
- party._mazeDirection = _vm->getGameID() == GType_WorldOfXeen ?
- DIR_EAST : DIR_SOUTH;
+ if (reloadMap) {
+ sound.playFX(51);
+ map._loadCcNum = _vm->getGameID() != GType_WorldOfXeen ? 1 : 0;
+ map.load(_vm->getGameID() == GType_WorldOfXeen ? 28 : 29);
+ party._mazeDirection = _vm->getGameID() == GType_WorldOfXeen ?
+ DIR_EAST : DIR_SOUTH;
+ }
}
- combat._combatMode = COMBATMODE_1;
+ combat._combatMode = COMBATMODE_INTERACTIVE;
}
void Interface::nextChar() {
@@ -1744,7 +1765,7 @@ void Interface::nextChar() {
return;
if ((combat._attackMonsters[0] == -1 && combat._attackMonsters[1] == -1 &&
combat._attackMonsters[2] == -1) || combat._combatParty.size() == 0) {
- _vm->_mode = MODE_1;
+ _vm->_mode = MODE_INTERACTIVE;
return;
}
@@ -1754,7 +1775,7 @@ void Interface::nextChar() {
// Check if party is dead
party.checkPartyDead();
if (party._dead) {
- _vm->_mode = MODE_1;
+ _vm->_mode = MODE_INTERACTIVE;
break;
}
@@ -1788,7 +1809,7 @@ void Interface::nextChar() {
combat.setSpeedTable();
combat._whosTurn = -1;
combat._whosSpeed = -1;
- Common::fill(&combat._charsGone[0], &combat._charsGone[0] + combat._charsGone.size(), 0);
+ Common::fill(&combat._charsGone[0], &combat._charsGone[PARTY_AND_MONSTERS], false);
continue;
}
diff --git a/engines/xeen/interface.h b/engines/xeen/interface.h
index bbc2a77f1e..5639171c40 100644
--- a/engines/xeen/interface.h
+++ b/engines/xeen/interface.h
@@ -71,8 +71,18 @@ public:
void drawParty(bool updateFlag);
+ /**
+ * Highlights the specified character in the party display at the bottom of the screen
+ * @param charId Character number
+ */
void highlightChar(int charId);
+ /**
+ * Highlights the specified character in the party display at the bottom of the screen
+ * @param c Character to highlight
+ */
+ void highlightChar(const Character *c);
+
void unhighlightChar();
void resetHighlight();
@@ -154,7 +164,6 @@ private:
void nextChar();
public:
Obscurity _obscurity;
- Common::String _interfaceText;
FallState _falling;
int _face1State, _face2State;
int _face1UIFrame, _face2UIFrame;
diff --git a/engines/xeen/interface_minimap.cpp b/engines/xeen/interface_minimap.cpp
index 5ab10696bc..5805047d9e 100644
--- a/engines/xeen/interface_minimap.cpp
+++ b/engines/xeen/interface_minimap.cpp
@@ -141,7 +141,7 @@ void InterfaceMinimap::drawIndoorsMinimap() {
}
// Draw the specific surface type for each cell
- for (int yp = MINIMAP_YSTART + (TILE_HEIGHT / 2), mazeY = pt.y + MINIMAP_DIFF;
+ for (int yp = MINIMAP_YSTART + (TILE_HEIGHT / 2) + 1, mazeY = pt.y + MINIMAP_DIFF;
mazeY >= (pt.y - MINIMAP_DIFF); yp += TILE_HEIGHT, --mazeY) {
for (int xp = MINIMAP_XSTART + (TILE_WIDTH / 2), mazeX = pt.x - MINIMAP_DIFF;
mazeX <= (pt.x + MINIMAP_DIFF); xp += TILE_WIDTH, ++mazeX) {
@@ -161,13 +161,13 @@ void InterfaceMinimap::drawIndoorsMinimap() {
(map._currentSteppedOn || party._wizardEyeActive)) {
map._tileSprites.draw(1,
map.mazeData()._surfaceTypes[map._currentSurfaceId] + 36,
- Common::Point(MINIMAP_XSTART - (TILE_WIDTH / 2),
+ Common::Point(MINIMAP_XSTART - (TILE_WIDTH / 2),
MINIMAP_YSTART - (TILE_HEIGHT / 2) + 1));
}
// Handle drawing surface sprites partially clipped at the left edge
- for (int yp = MINIMAP_YSTART, mazeY = pt.y + MINIMAP_DIFF; mazeY >= (pt.y - MINIMAP_DIFF);
- yp += TILE_HEIGHT, --mazeY) {
+ for (int yp = MINIMAP_YSTART + (TILE_HEIGHT / 2) + 1, mazeY = pt.y + MINIMAP_DIFF;
+ mazeY >= (pt.y - MINIMAP_DIFF); yp += TILE_HEIGHT, --mazeY) {
v = map.mazeLookup(Common::Point(pt.x - MINIMAP_DIFF - 1, mazeY), 0, 0xffff);
if (v != INVALID_CELL && map._currentSurfaceId &&
@@ -192,7 +192,7 @@ void InterfaceMinimap::drawIndoorsMinimap() {
}
// Handle drawing partially clip top row and left column
- for (int xp = MINIMAP_XSTART, yp = MINIMAP_YSTART + (MINIMAP_SIZE - 1) * TILE_HEIGHT,
+ for (int xp = MINIMAP_XSTART, yp = MINIMAP_YSTART + (MINIMAP_SIZE - 1) * TILE_HEIGHT,
mazeX = pt.x - MINIMAP_DIFF, mazeY = pt.y + MINIMAP_DIFF;
mazeX <= (pt.x - MINIMAP_DIFF);
xp += TILE_WIDTH, yp -= TILE_HEIGHT, ++mazeX, --mazeY) {
diff --git a/engines/xeen/interface_scene.cpp b/engines/xeen/interface_scene.cpp
index 51cb6d8b13..0fdf867448 100644
--- a/engines/xeen/interface_scene.cpp
+++ b/engines/xeen/interface_scene.cpp
@@ -63,11 +63,11 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]),
_data[25] = DrawStruct(0, 8, 109);
_data[26] = DrawStruct(0, 201, 109);
_data[27] = DrawStruct(0, 8, 109);
- _data[28] = DrawStruct(1, -64, 61, 14, SPRFLAG_SCENE_CLIPPED);
+ _data[28] = DrawStruct(1, -64, 61, 14);
_data[29] = DrawStruct(1, -40, 61, 14, 0);
_data[30] = DrawStruct(1, -16, 61, 14, 0);
_data[31] = DrawStruct(1, 8, 61, 14, 0);
- _data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[32] = DrawStruct(1, 128, 61, 14, SPRFLAG_HORIZ_FLIPPED);
_data[33] = DrawStruct(1, 104, 61, 14, SPRFLAG_HORIZ_FLIPPED);
_data[34] = DrawStruct(1, 80, 61, 14, SPRFLAG_HORIZ_FLIPPED);
_data[35] = DrawStruct(1, 56, 61, 14, SPRFLAG_HORIZ_FLIPPED);
@@ -123,10 +123,10 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]),
_data[85] = DrawStruct(2, 146, 40, 0, SPRFLAG_HORIZ_FLIPPED);
_data[86] = DrawStruct(1, 32, 40, 6, 0);
_data[87] = DrawStruct(0, -7, 30, 7, 0);
- _data[88] = DrawStruct(0, -112, 30, 7, SPRFLAG_SCENE_CLIPPED);
- _data[89] = DrawStruct(0, 98, 30, 7, SPRFLAG_SCENE_CLIPPED);
- _data[90] = DrawStruct(0, -112, 30, 8, SPRFLAG_SCENE_CLIPPED);
- _data[91] = DrawStruct(0, 98, 30, 8, SPRFLAG_SCENE_CLIPPED);
+ _data[88] = DrawStruct(0, -112, 30, 7);
+ _data[89] = DrawStruct(0, 98, 30, 7);
+ _data[90] = DrawStruct(0, -112, 30, 8);
+ _data[91] = DrawStruct(0, 98, 30, 8);
_data[92] = DrawStruct(0, -38, 30, 8, 0);
_data[93] = DrawStruct(0, 25, 30, 8, 0);
_data[94] = DrawStruct(0, -7, 30, 8, 0);
@@ -141,22 +141,22 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]),
_data[103] = DrawStruct(0, 8, 24);
_data[104] = DrawStruct(0, 169, 24, 0, SPRFLAG_HORIZ_FLIPPED);
_data[105] = DrawStruct(1, 32, 24);
- _data[106] = DrawStruct(0, -23, 40, 0, SPRFLAG_SCENE_CLIPPED);
- _data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[106] = DrawStruct(0, -23, 40, 0);
+ _data[107] = DrawStruct(0, 200, 40, 0, SPRFLAG_HORIZ_FLIPPED);
_data[108] = DrawStruct(0, 8, 47);
_data[109] = DrawStruct(0, 169, 47, 0, SPRFLAG_HORIZ_FLIPPED);
- _data[110] = DrawStruct(1, -56, -4, SCALE_ENLARGE, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
- _data[111] = DrawStruct(0, -5, 2, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
- _data[112] = DrawStruct(0, -67, 2, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[110] = DrawStruct(1, -56, -4, SCALE_ENLARGE, SPRFLAG_BOTTOM_CLIPPED);
+ _data[111] = DrawStruct(0, -5, 2, 0, SPRFLAG_BOTTOM_CLIPPED);
+ _data[112] = DrawStruct(0, -67, 2, 0, SPRFLAG_BOTTOM_CLIPPED);
_data[113] = DrawStruct(0, 44, 73);
_data[114] = DrawStruct(0, 44, 73);
- _data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[115] = DrawStruct(0, 58, 14, 0, SPRFLAG_BOTTOM_CLIPPED);
_data[116] = DrawStruct(0, 169, 73);
_data[117] = DrawStruct(0, 169, 73);
- _data[118] = DrawStruct(0, -5, 14, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[118] = DrawStruct(0, -5, 14, 0, SPRFLAG_BOTTOM_CLIPPED);
_data[119] = DrawStruct(0, 110, 73);
_data[120] = DrawStruct(0, 110, 73);
- _data[121] = DrawStruct(0, -5, 14, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[121] = DrawStruct(0, -5, 14, 0, SPRFLAG_BOTTOM_CLIPPED);
_data[122] = DrawStruct(0, 110, 73);
_data[123] = DrawStruct(0, 110, 73);
_data[124] = DrawStruct(0, 72, 43);
@@ -167,6 +167,18 @@ OutdoorDrawList::OutdoorDrawList() : _sky1(_data[0]), _sky2(_data[1]),
_data[129] = DrawStruct(0, 47, 36, 0, SPRFLAG_HORIZ_FLIPPED);
_data[130] = DrawStruct(0, 118, 42);
_data[131] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED);
+
+ for (int idx = 0; idx < 132; ++idx)
+ _data[idx]._flags |= SPRFLAG_SCENE_CLIPPED;
+}
+
+void OutdoorDrawList::draw() {
+ // Mark all items to be drawn as being clipped to the scene area
+ for (int idx = 0; idx < size(); ++idx)
+ _data[idx]._flags |= SPRFLAG_SCENE_CLIPPED;
+
+ // Draw the list
+ (*g_vm->_windows)[3].drawList(_data, size());
}
/*------------------------------------------------------------------------*/
@@ -283,16 +295,16 @@ IndoorDrawList::IndoorDrawList() :
_data[84] = DrawStruct(0, 71, 53, 12, SPRFLAG_HORIZ_FLIPPED);
_data[85] = DrawStruct(0, 80, 57, 12, 0);
_data[86] = DrawStruct(0, 64, 57, 12, SPRFLAG_HORIZ_FLIPPED);
- _data[87] = DrawStruct(7, -24, 52, 0, SPRFLAG_SCENE_CLIPPED);
+ _data[87] = DrawStruct(7, -24, 52, 0);
_data[88] = DrawStruct(7, 32, 52);
_data[89] = DrawStruct(7, 88, 52);
_data[90] = DrawStruct(0, 144, 52);
- _data[91] = DrawStruct(0, 200, 52, 0, SPRFLAG_SCENE_CLIPPED);
- _data[92] = DrawStruct(0, -79, 52, 11, SPRFLAG_SCENE_CLIPPED);
+ _data[91] = DrawStruct(0, 200, 52, 0);
+ _data[92] = DrawStruct(0, -79, 52, 11);
_data[93] = DrawStruct(0, -27, 52, 11, 0);
_data[94] = DrawStruct(0, 32, 52, 11, 0);
_data[95] = DrawStruct(0, 89, 52, 11, 0);
- _data[96] = DrawStruct(0, 145, 52, 11, SPRFLAG_SCENE_CLIPPED);
+ _data[96] = DrawStruct(0, 145, 52, 11);
_data[97] = DrawStruct(0, -8, 50, 12, 0);
_data[98] = DrawStruct(0, -65, 50, 12, 0);
_data[99] = DrawStruct(0, 49, 50, 12, 0);
@@ -315,17 +327,17 @@ IndoorDrawList::IndoorDrawList() :
_data[116] = DrawStruct(0, 63, 47, 8, SPRFLAG_HORIZ_FLIPPED);
_data[117] = DrawStruct(0, 94, 52, 8, 0);
_data[118] = DrawStruct(0, 50, 52, 8, SPRFLAG_HORIZ_FLIPPED);
- _data[119] = DrawStruct(6, -40, 40, 0, SPRFLAG_SCENE_CLIPPED);
+ _data[119] = DrawStruct(6, -40, 40, 0);
_data[120] = DrawStruct(6, 64, 40);
- _data[121] = DrawStruct(0, 168, 40, 0, SPRFLAG_SCENE_CLIPPED);
- _data[122] = DrawStruct(0, -72, 40, 6, SPRFLAG_SCENE_CLIPPED);
+ _data[121] = DrawStruct(0, 168, 40, 0);
+ _data[122] = DrawStruct(0, -72, 40, 6);
_data[123] = DrawStruct(0, 32, 40, 6, 0);
- _data[124] = DrawStruct(0, 137, 40, 6, SPRFLAG_SCENE_CLIPPED);
+ _data[124] = DrawStruct(0, 137, 40, 6);
_data[125] = DrawStruct(0, -7, 25, 7, 0);
- _data[126] = DrawStruct(0, -112, 25, 7, SPRFLAG_SCENE_CLIPPED);
- _data[127] = DrawStruct(0, 98, 25, 7, SPRFLAG_SCENE_CLIPPED);
- _data[128] = DrawStruct(0, -112, 29, 8, SPRFLAG_SCENE_CLIPPED);
- _data[129] = DrawStruct(0, 98, 29, 8, SPRFLAG_SCENE_CLIPPED);
+ _data[126] = DrawStruct(0, -112, 25, 7);
+ _data[127] = DrawStruct(0, 98, 25, 7);
+ _data[128] = DrawStruct(0, -112, 29, 8);
+ _data[129] = DrawStruct(0, 98, 29, 8);
_data[130] = DrawStruct(0, -38, 29, 8, 0);
_data[131] = DrawStruct(0, 25, 29, 8, 0);
_data[132] = DrawStruct(0, -7, 29, 8, 0);
@@ -339,23 +351,23 @@ IndoorDrawList::IndoorDrawList() :
_data[140] = DrawStruct(0, 55, 41, 4, SPRFLAG_HORIZ_FLIPPED);
_data[141] = DrawStruct(0, 106, 47, 4, 0);
_data[142] = DrawStruct(0, 38, 47, 4, SPRFLAG_HORIZ_FLIPPED);
- _data[143] = DrawStruct(0, -136, 24, 0, SPRFLAG_SCENE_CLIPPED);
+ _data[143] = DrawStruct(0, -136, 24, 0);
_data[144] = DrawStruct(0, 8, 12);
_data[145] = DrawStruct(0, 32, 24);
_data[146] = DrawStruct(0, 200, 12, 0, SPRFLAG_HORIZ_FLIPPED);
- _data[147] = DrawStruct(0, 200, 24, 0, SPRFLAG_SCENE_CLIPPED);
+ _data[147] = DrawStruct(0, 200, 24, 0);
_data[148] = DrawStruct(0, 32, 24);
- _data[149] = DrawStruct(0, -5, 2, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
- _data[150] = DrawStruct(0, -67, 10, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[149] = DrawStruct(0, -5, 2, 0, SPRFLAG_BOTTOM_CLIPPED);
+ _data[150] = DrawStruct(0, -67, 10, 0, SPRFLAG_BOTTOM_CLIPPED);
_data[151] = DrawStruct(0, 44, 73);
_data[152] = DrawStruct(0, 44, 73);
- _data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[153] = DrawStruct(0, 58, 14, 0, SPRFLAG_BOTTOM_CLIPPED);
_data[154] = DrawStruct(0, 169, 73);
_data[155] = DrawStruct(0, 169, 73);
- _data[156] = DrawStruct(0, -5, 14, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[156] = DrawStruct(0, -5, 14, 0, SPRFLAG_BOTTOM_CLIPPED);
_data[157] = DrawStruct(0, 110, 73);
_data[158] = DrawStruct(0, 110, 73);
- _data[159] = DrawStruct(0, -5, 14, 0, SPRFLAG_BOTTOM_CLIPPED | SPRFLAG_SCENE_CLIPPED);
+ _data[159] = DrawStruct(0, -5, 14, 0, SPRFLAG_BOTTOM_CLIPPED);
_data[160] = DrawStruct(0, 110, 73);
_data[161] = DrawStruct(0, 110, 73);
_data[162] = DrawStruct(0, 72, 43);
@@ -368,6 +380,15 @@ IndoorDrawList::IndoorDrawList() :
_data[169] = DrawStruct(0, 26, 42, 0, SPRFLAG_HORIZ_FLIPPED);
}
+void IndoorDrawList::draw() {
+ // Mark all items to be drawn as being clipped to the scene area
+ for (int idx = 0; idx < size(); ++idx)
+ _data[idx]._flags |= SPRFLAG_SCENE_CLIPPED;
+
+ // Draw the list
+ (*g_vm->_windows)[3].drawList(_data, size());
+}
+
/*------------------------------------------------------------------------*/
InterfaceScene::InterfaceScene(XeenEngine *vm): _vm(vm) {
@@ -380,7 +401,7 @@ InterfaceScene::InterfaceScene(XeenEngine *vm): _vm(vm) {
_flipDefaultGround = false;
_isAttacking = false;
_charsShooting = false;
- _objNumber = 0;
+ _objNumber = -1;
_combatFloatCounter = 0;
_thinWall = false;
_isAnimReset = false;
@@ -392,9 +413,8 @@ void InterfaceScene::drawScene() {
Map &map = *_vm->_map;
Scripts &scripts = *_vm->_scripts;
- MazeObject &objObject = map._mobData._objects[_objNumber];
+ MazeObject *obj = (_objNumber == -1) ? nullptr : &map._mobData._objects[_objNumber];
Direction partyDirection = _vm->_party->_mazeDirection;
- int objNum = _objNumber - 1;
// Loop to update the frame numbers for each maze object, applying the animation frame
// limits as specified by the map's _animationInfo listing
@@ -407,9 +427,9 @@ void InterfaceScene::drawScene() {
mazeObject._frame = animEntry._frame1._frames[directionIndex];
} else {
++mazeObject._frame;
- if ((int)idx == objNum && scripts._animCounter > 0 && (
- objObject._spriteId == (_vm->_files->_isDarkCc ? 15 : 16) ||
- objObject._spriteId == 58 || objObject._spriteId == 73)) {
+ if ((int)idx == _objNumber && scripts._animCounter > 0 && (
+ obj->_spriteId == (_vm->_files->_ccNum ? 15 : 16) ||
+ obj->_spriteId == 58 || obj->_spriteId == 73)) {
if (mazeObject._frame > 4 || mazeObject._spriteId == 58)
mazeObject._frame = 1;
} else if (mazeObject._frame >= animEntry._frame2._frames[directionIndex]) {
@@ -570,7 +590,7 @@ void InterfaceScene::drawIndoorsScene() {
_indoorList[idx]._frame = -1;
if (combat._monstersAttacking) {
- for (int idx = 0; idx < 96; ++idx) {
+ for (int idx = 0; idx < 8; ++idx) {
if (_indoorList[79 + idx]._sprites != nullptr) {
_indoorList[79 + idx]._frame = 0;
} else if (_indoorList[111 + idx]._sprites != nullptr) {
@@ -599,7 +619,7 @@ void InterfaceScene::drawIndoorsScene() {
_isAnimReset = false;
// Code in the original that's not being used
- //MazeObject &objObject = map._mobData._objects[_objNumber - 1];
+ //MazeObject &objObject = map._mobData._objects[_objNumber];
// Only the front rank of pow points result in a Pow splatter effect
for (int idx = 0; idx < 3; ++idx) {
@@ -2652,7 +2672,7 @@ void InterfaceScene::setIndoorsObjects() {
Common::Point mazePos = _vm->_party->_mazePosition;
Direction dir = _vm->_party->_mazeDirection;
Common::Point pt;
- _objNumber = 0;
+ _objNumber = -1;
Common::Array<MazeObject> &objects = _vm->_map->_mobData._objects;
for (uint idx = 0; idx < objects.size(); ++idx) {
@@ -2660,7 +2680,7 @@ void InterfaceScene::setIndoorsObjects() {
// Determine which half of the X/Y lists to use
int listOffset;
- if (_vm->_files->_isDarkCc) {
+ if (_vm->_files->_ccNum) {
listOffset = mazeObject._spriteId == 47 ? 1 : 0;
} else {
listOffset = mazeObject._spriteId == 113 ? 1 : 0;
@@ -3361,11 +3381,12 @@ void InterfaceScene::setOutdoorsObjects() {
const Common::Point &pt = party._mazePosition;
Direction dir = party._mazeDirection;
int posIndex;
+ _objNumber = -1;
for (uint idx = 0; idx < map._mobData._objects.size(); ++idx) {
MazeObject &obj = map._mobData._objects[idx];
- if (_vm->_files->_isDarkCc) {
+ if (_vm->_files->_ccNum) {
posIndex = obj._spriteId == 47 ? 1 : 0;
} else {
posIndex = obj._spriteId == 113 ? 1 : 0;
@@ -3544,7 +3565,6 @@ void InterfaceScene::setOutdoorsObjects() {
void InterfaceScene::drawIndoors() {
Map &map = *_vm->_map;
- Windows &windows = *_vm->_windows;
int surfaceId;
// Draw any surface tiles on top of the default ground
@@ -3667,8 +3687,9 @@ void InterfaceScene::drawIndoors() {
_indoorList._fwl_4F4R._frame = 9;
else if (_wo[35])
_indoorList._fwl_4F4R._frame = 0;
+ /* TODO: Duplicated switch in the original executable.. original bug meant to check some other index?
else if (_wo[79])
- _indoorList._fwl_4F4R._frame = 15;
+ _indoorList._fwl_4F4R._frame = 15;*/
else if (_wo[213])
_indoorList._fwl_4F4R._frame = 14;
else if (_wo[233])
@@ -3930,7 +3951,9 @@ void InterfaceScene::drawIndoors() {
_indoorList._fwl_4F1R._frame = 13;
}
- if (_wo[27] || _wo[22] || _wo[15] || _wo[96]) {
+ if (_wo[27] || _wo[22] || _wo[15]) {
+ } else if (_wo[96]) {
+ _indoorList._fwl_4F._frame = 7;
} else if (_wo[50]) {
_indoorList._fwl_4F._frame = 16;
} else if (_wo[156]) {
@@ -4377,7 +4400,7 @@ void InterfaceScene::drawIndoors() {
_indoorList._horizon._frame = 7;
// Finally draw the darn indoor scene
- windows[3].drawList(&_indoorList[0], _indoorList.size());
+ _indoorList.draw();
// Check for any character shooting
_isAttacking = false;
@@ -4392,7 +4415,6 @@ void InterfaceScene::drawIndoors() {
void InterfaceScene::drawOutdoors() {
Map &map = *_vm->_map;
Party &party = *_vm->_party;
- Windows &windows = *_vm->_windows;
int surfaceId;
// Draw any surface tiles on top of the default ground
@@ -4458,7 +4480,7 @@ void InterfaceScene::drawOutdoors() {
_outdoorList._groundSprite._flags = _flipWater ? SPRFLAG_HORIZ_FLIPPED : 0;
// Finally render the outdoor scene
- windows[3].drawList(&_outdoorList[0], _outdoorList.size());
+ _outdoorList.draw();
// Check for any character shooting
_isAttacking = false;
diff --git a/engines/xeen/interface_scene.h b/engines/xeen/interface_scene.h
index 0c181522bb..18f1f58a36 100644
--- a/engines/xeen/interface_scene.h
+++ b/engines/xeen/interface_scene.h
@@ -42,14 +42,28 @@ public:
DrawStruct * const _attackImgs3;
DrawStruct * const _attackImgs4;
public:
+ /**
+ * Constructor
+ */
OutdoorDrawList();
+ /**
+ * Get a draw list entry
+ */
DrawStruct &operator[](int idx) {
assert(idx < size());
return _data[idx];
}
+ /**
+ * Return the size of the list
+ */
int size() const { return 132; }
+
+ /**
+ * Draw the list to the scene
+ */
+ void draw();
};
class IndoorDrawList {
@@ -80,12 +94,23 @@ public:
public:
IndoorDrawList();
+ /**
+ * Get a draw list entry
+ */
DrawStruct &operator[](int idx) {
assert(idx < size());
return _data[idx];
}
+ /**
+ * Return the size of the list
+ */
int size() const { return 170; }
+
+ /**
+ * Draw the list to the scene
+ */
+ void draw();
};
class InterfaceScene {
diff --git a/engines/xeen/item.cpp b/engines/xeen/item.cpp
index 7a4b459d41..a364dad928 100644
--- a/engines/xeen/item.cpp
+++ b/engines/xeen/item.cpp
@@ -27,25 +27,50 @@
namespace Xeen {
+void ItemState::synchronize(Common::Serializer &s) {
+ byte b = _counter | (_cursed ? 0x40 : 0) | (_broken ? 0x80 : 0);
+ s.syncAsByte(b);
+
+ if (s.isLoading()) {
+ _counter = b & 63;
+ _cursed = (b & 0x40) != 0;
+ _broken = (b & 0x80) != 0;
+ }
+}
+
+void ItemState::operator=(byte val) {
+ _counter = val & 63;
+ _cursed = (val & 0x40) != 0;
+ _broken = (val & 0x80) != 0;
+}
+
+/*------------------------------------------------------------------------*/
+
XeenItem::XeenItem() {
clear();
}
void XeenItem::clear() {
- _material = _id = _bonusFlags = 0;
+ _material = _id = 0;
+ _state.clear();
_frame = 0;
}
void XeenItem::synchronize(Common::Serializer &s) {
s.syncAsByte(_material);
s.syncAsByte(_id);
- s.syncAsByte(_bonusFlags);
+ _state.synchronize(s);
s.syncAsByte(_frame);
}
ElementalCategory XeenItem::getElementalCategory() const {
+ assert(_material < 36);
+ return getElementalCategory(_material);
+}
+
+ElementalCategory XeenItem::getElementalCategory(int material) {
int idx;
- for (idx = 0; Res.ELEMENTAL_CATEGORIES[idx] < _material; ++idx)
+ for (idx = 0; Res.ELEMENTAL_CATEGORIES[idx] < material; ++idx)
;
return (ElementalCategory)idx;
@@ -61,21 +86,36 @@ AttributeCategory XeenItem::getAttributeCategory() const {
}
const char *XeenItem::getItemName(ItemCategory category, uint id) {
- if (id < 82)
- return Res.ITEM_NAMES[category][id];
-
- switch (category) {
- case CATEGORY_WEAPON:
- return Res.QUEST_ITEM_NAMES[id - 82];
-
- case CATEGORY_ARMOR:
- return Res.QUEST_ITEM_NAMES[id - 82 + 35];
-
- case CATEGORY_ACCESSORY:
- return Res.QUEST_ITEM_NAMES[id - 82 + 35 + 14];
-
- default:
- return Res.QUEST_ITEM_NAMES[id - 82 + 35 + 14 + 11];
+ const char **questItems = (g_vm->getGameID() == GType_Swords) ? Res.QUEST_ITEM_NAMES_SWORDS : Res.QUEST_ITEM_NAMES;
+ const uint QUEST_OFFSET = g_vm->getGameID() == GType_Swords ? 88 : 82;
+
+ if (id < QUEST_OFFSET) {
+ switch (category) {
+ case CATEGORY_WEAPON:
+ assert(id < 41);
+ return Res.WEAPON_NAMES[id];
+ case CATEGORY_ARMOR:
+ assert(id < 14);
+ return Res.ARMOR_NAMES[id];
+ case CATEGORY_ACCESSORY:
+ assert(id < 11);
+ return Res.ACCESSORY_NAMES[id];
+ default:
+ assert(id < 22);
+ return Res.MISC_NAMES[id];
+ }
+ } else {
+ switch (category) {
+ case CATEGORY_WEAPON:
+ return questItems[id - QUEST_OFFSET];
+ case CATEGORY_ARMOR:
+ return questItems[id - QUEST_OFFSET + 35];
+ case CATEGORY_ACCESSORY:
+ return questItems[id - QUEST_OFFSET + 35 + 14];
+ default:
+ assert(g_vm->getGameID() != GType_Swords);
+ return questItems[id - QUEST_OFFSET + 35 + 14 + 11];
+ }
}
}
@@ -93,6 +133,14 @@ void InventoryItems::clear() {
operator[](idx).clear();
}
+InventoryItems &InventoryItems::operator=(const InventoryItems &src) {
+ Common::Array<XeenItem>::clear();
+ assert(src.size() == INV_ITEMS_TOTAL);
+ for (uint idx = 0; idx < INV_ITEMS_TOTAL; ++idx)
+ push_back(src[idx]);
+ return *this;
+}
+
bool InventoryItems::passRestrictions(int itemId, bool suppressError) const {
CharacterClass charClass = _character->_class;
@@ -156,7 +204,7 @@ bool InventoryItems::discardItem(int itemIndex) {
XeenItem &item = operator[](itemIndex);
XeenEngine *vm = Party::_vm;
- if (item._bonusFlags & ITEMFLAG_CURSED) {
+ if (item._state._cursed) {
ErrorScroll::show(vm, Res.CANNOT_DISCARD_CURSED_ITEM);
} else {
Common::String itemDesc = getFullDescription(itemIndex, 4);
@@ -175,7 +223,7 @@ bool InventoryItems::discardItem(int itemIndex) {
void InventoryItems::sort() {
for (uint idx = 0; idx < size(); ++idx) {
- if (operator[](idx)._id == 0) {
+ if (operator[](idx).empty()) {
// Found empty slot
operator[](idx).clear();
@@ -196,7 +244,7 @@ void InventoryItems::removeItem(int itemIndex) {
XeenItem &item = operator[](itemIndex);
XeenEngine *vm = Party::_vm;
- if (item._bonusFlags & ITEMFLAG_CURSED)
+ if (item._state._cursed)
ErrorScroll::show(vm, Res.CANNOT_REMOVE_CURSED_ITEM);
else
item._frame = 0;
@@ -215,7 +263,7 @@ void InventoryItems::equipError(int itemIndex1, ItemCategory category1, int item
Common::String itemName2 = _character->_items[category2].getName(itemIndex2);
MessageDialog::show(vm, Common::String::format(Res.REMOVE_X_TO_EQUIP_Y,
- itemName1.c_str(), itemName2.c_str()));
+ itemName2.c_str(), itemName1.c_str()));
} else {
MessageDialog::show(vm, Common::String::format(Res.EQUIPPED_ALL_YOU_CAN,
(itemIndex1 == -1) ? Res.RING : Res.MEDAL));
@@ -230,7 +278,14 @@ void InventoryItems::enchantItem(int itemIndex, int amount) {
bool InventoryItems::isFull() const {
assert(size() == INV_ITEMS_TOTAL);
- return operator[](size() - 1)._id != 0;
+ return !operator[](size() - 1).empty();
+}
+
+void InventoryItems::capitalizeItem(Common::String &name) {
+ if (name[3] == '\f')
+ name.setChar(toupper(name[6]), 6);
+ else
+ name.setChar(toupper(name[3]), 3);
}
/*------------------------------------------------------------------------*/
@@ -289,16 +344,17 @@ Common::String WeaponItems::getFullDescription(int itemIndex, int displayNum) {
XeenItem &i = operator[](itemIndex);
Resources &res = *getVm()->_resources;
- return Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
- !i._bonusFlags ? res._maeNames[i._material].c_str() : "",
- (i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
- (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
+ Common::String desc = Common::String::format("\f%02u%s%s%s\f%02u%s%s%s", displayNum,
+ i._state._cursed || i._state._broken ? "" : res._maeNames[i._material].c_str(),
+ i._state._broken ? Res.ITEM_BROKEN : "",
+ i._state._cursed ? Res.ITEM_CURSED : "",
displayNum,
Res.WEAPON_NAMES[i._id],
- !i._bonusFlags ? "" : Res.BONUS_NAMES[i._bonusFlags & ITEMFLAG_BONUS_MASK],
- (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
- !i._bonusFlags ? "\b " : ""
+ !i._state._counter ? "" : Res.BONUS_NAMES[i._state._counter],
+ (i._state._cursed || i._state._broken) || !i._id ? "\b " : ""
);
+ capitalizeItem(desc);
+ return desc;
}
void WeaponItems::enchantItem(int itemIndex, int amount) {
@@ -306,12 +362,12 @@ void WeaponItems::enchantItem(int itemIndex, int amount) {
XeenItem &item = operator[](itemIndex);
Character tempCharacter;
- if (item._material == 0 && item._bonusFlags == 0 && item._id != 34) {
+ if (item._material == 0 && item._state.empty() && item._id < XEEN_SLAYER_SWORD) {
tempCharacter.makeItem(amount, 0, 1);
XeenItem &tempItem = tempCharacter._weapons[0];
item._material = tempItem._material;
- item._bonusFlags = tempItem._bonusFlags;
+ item._state = tempItem._state;
sound.playFX(19);
} else {
InventoryItems::enchantItem(itemIndex, amount);
@@ -350,10 +406,9 @@ Common::String WeaponItems::getAttributes(XeenItem &item, const Common::String &
}
// Handle weapon effective against
- int effective = item._bonusFlags & ITEMFLAG_BONUS_MASK;
+ Effectiveness effective = (Effectiveness)item._state._counter;
if (effective) {
- specialPower = Common::String::format(Res.EFFECTIVE_AGAINST,
- Res.EFFECTIVENESS_NAMES[effective]);
+ specialPower = Common::String::format(Res.EFFECTIVE_AGAINST, Res.EFFECTIVENESS_NAMES[effective]);
}
return Common::String::format(Res.ITEM_DETAILS, classes.c_str(),
@@ -362,6 +417,17 @@ Common::String WeaponItems::getAttributes(XeenItem &item, const Common::String &
);
}
+bool WeaponItems::hasElderWeapon() const {
+ if (g_vm->getGameID() == GType_Swords) {
+ for (uint idx = 0; idx < size(); ++idx) {
+ if ((*this)[idx]._id >= 34)
+ return true;
+ }
+ }
+
+ return false;
+}
+
/*------------------------------------------------------------------------*/
void ArmorItems::equipItem(int itemIndex) {
@@ -371,7 +437,7 @@ void ArmorItems::equipItem(int itemIndex) {
if (passRestrictions(item._id)) {
for (uint idx = 0; idx < size(); ++idx) {
XeenItem &i = operator[](idx);
- if (i._frame == 9) {
+ if (i._frame == 3) {
equipError(itemIndex, CATEGORY_ARMOR, idx, CATEGORY_ARMOR);
return;
}
@@ -446,15 +512,16 @@ Common::String ArmorItems::getFullDescription(int itemIndex, int displayNum) {
XeenItem &i = operator[](itemIndex);
Resources &res = *getVm()->_resources;
- return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
- !i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
- (i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
- (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
+ Common::String desc = Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+ i._state._cursed || i._state._broken ? "" : res._maeNames[i._material].c_str(),
+ i._state._broken ? Res.ITEM_BROKEN : "",
+ i._state._cursed ? Res.ITEM_CURSED : "",
displayNum,
Res.ARMOR_NAMES[i._id],
- (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
- !i._bonusFlags ? "\b " : ""
+ (i._state._cursed || i._state._broken) || !i._id ? "\b " : ""
);
+ capitalizeItem(desc);
+ return desc;
}
void ArmorItems::enchantItem(int itemIndex, int amount) {
@@ -462,12 +529,12 @@ void ArmorItems::enchantItem(int itemIndex, int amount) {
XeenItem &item = operator[](itemIndex);
Character tempCharacter;
- if (item._material == 0 && item._bonusFlags == 0) {
+ if (item._material == 0 && item._state.empty()) {
tempCharacter.makeItem(amount, 0, 2);
XeenItem &tempItem = tempCharacter._armor[0];
item._material = tempItem._material;
- item._bonusFlags = tempItem._bonusFlags;
+ item._state = tempItem._state;
sound.playFX(19);
} else {
InventoryItems::enchantItem(itemIndex, amount);
@@ -529,6 +596,8 @@ void AccessoryItems::equipItem(int itemIndex) {
return;
}
}
+
+ item._frame = 12;
} else if (item._id <= 7) {
int count = 0;
for (uint idx = 0; idx < size(); ++idx) {
@@ -558,15 +627,16 @@ Common::String AccessoryItems::getFullDescription(int itemIndex, int displayNum)
XeenItem &i = operator[](itemIndex);
Resources &res = *getVm()->_resources;
- return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
- !i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
- (i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
- (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
+ Common::String desc = Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
+ i._state._cursed || i._state._broken ? "" : res._maeNames[i._material].c_str(),
+ i._state._broken ? Res.ITEM_BROKEN : "",
+ i._state._cursed ? Res.ITEM_CURSED : "",
displayNum,
- Res.ARMOR_NAMES[i._id],
- (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
- !i._bonusFlags ? "\b " : ""
+ Res.ACCESSORY_NAMES[i._id],
+ (i._state._cursed || i._state._broken) || !i._id ? "\b " : ""
);
+ capitalizeItem(desc);
+ return desc;
}
/*
@@ -602,17 +672,18 @@ Common::String AccessoryItems::getAttributes(XeenItem &item, const Common::Strin
Common::String MiscItems::getFullDescription(int itemIndex, int displayNum) {
XeenItem &i = operator[](itemIndex);
- Resources &res = *getVm()->_resources;
- return Common::String::format("\f%02u%s%s%s\f%02u%s%s", displayNum,
- !i._bonusFlags ? "" : res._maeNames[i._material].c_str(),
- (i._bonusFlags & ITEMFLAG_BROKEN) ? Res.ITEM_BROKEN : "",
- (i._bonusFlags & ITEMFLAG_CURSED) ? Res.ITEM_CURSED : "",
+ Common::String desc = Common::String::format("\f%02u%s%s\f%02u%s%s%s%s", displayNum,
+ i._state._broken ? Res.ITEM_BROKEN : "",
+ i._state._cursed ? Res.ITEM_CURSED : "",
displayNum,
- Res.ARMOR_NAMES[i._id],
- (i._bonusFlags & (ITEMFLAG_BROKEN | ITEMFLAG_CURSED)) ||
- !i._id ? "\b " : ""
+ Res.MISC_NAMES[i._material],
+ (i._state._cursed || i._state._broken) || !i._id ? "" : Res.ITEM_OF,
+ (i._state._cursed || i._state._broken) ? "" : Res.SPECIAL_NAMES[i._id],
+ (i._state._cursed || i._state._broken) || !i._id ? "\b " : ""
);
+ capitalizeItem(desc);
+ return desc;
}
Common::String MiscItems::getAttributes(XeenItem &item, const Common::String &classes) {
@@ -629,31 +700,65 @@ Common::String MiscItems::getAttributes(XeenItem &item, const Common::String &cl
}
/*------------------------------------------------------------------------*/
-InventoryItemsGroup::InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
- InventoryItems &accessories, InventoryItems &misc) {
- _itemSets[0] = &weapons;
- _itemSets[1] = &armor;
- _itemSets[2] = &accessories;
- _itemSets[3] = &misc;
+InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) {
+ switch (category) {
+ case CATEGORY_WEAPON:
+ return _owner->_weapons;
+ case CATEGORY_ARMOR:
+ return _owner->_armor;
+ case CATEGORY_ACCESSORY:
+ return _owner->_accessories;
+ default:
+ return _owner->_misc;
+ }
}
-InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) {
- return *_itemSets[category];
+const InventoryItems &InventoryItemsGroup::operator[](ItemCategory category) const {
+ switch (category) {
+ case CATEGORY_WEAPON:
+ return _owner->_weapons;
+ case CATEGORY_ARMOR:
+ return _owner->_armor;
+ case CATEGORY_ACCESSORY:
+ return _owner->_accessories;
+ default:
+ return _owner->_misc;
+ }
}
void InventoryItemsGroup::breakAllItems() {
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
- if ((*_itemSets[0])[idx]._id != 34) {
- (*_itemSets[0])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
- (*_itemSets[0])[idx]._frame = 0;
+ if (_owner->_weapons[idx]._id < XEEN_SLAYER_SWORD) {
+ _owner->_weapons[idx]._state._broken = true;
+ _owner->_weapons[idx]._frame = 0;
}
- (*_itemSets[1])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
- (*_itemSets[2])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
- (*_itemSets[3])[idx]._bonusFlags |= ITEMFLAG_BROKEN;
- (*_itemSets[1])[idx]._frame = 0;
- (*_itemSets[2])[idx]._frame = 0;
+ _owner->_armor[idx]._state._broken = true;
+ _owner->_accessories[idx]._state._broken = true;
+ _owner->_misc[idx]._state._broken = true;
+ _owner->_armor[idx]._frame = 0;
+ _owner->_accessories[idx]._frame = 0;
+ }
+}
+
+void InventoryItemsGroup::curseUncurse(bool curse) {
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ _owner->_weapons[idx]._state._cursed = curse && _owner->_weapons[idx]._id < XEEN_SLAYER_SWORD;
+ _owner->_armor[idx]._state._cursed = curse;
+ _owner->_accessories[idx]._state._cursed = curse;
+ _owner->_misc[idx]._state._cursed = curse;
}
}
+bool InventoryItemsGroup::hasCursedItems() const {
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ for (ItemCategory cat = CATEGORY_WEAPON; cat <= CATEGORY_MISC; cat = (ItemCategory)((int)cat + 1)) {
+ if ((*this)[cat][idx]._state._cursed)
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/item.h b/engines/xeen/item.h
index 871bd1c919..df13456cd7 100644
--- a/engines/xeen/item.h
+++ b/engines/xeen/item.h
@@ -52,11 +52,54 @@ enum ElementalCategory {
ELEM_ENERGY = 4, ELEM_MAGIC = 5
};
+enum WeaponId {
+ XEEN_SLAYER_SWORD = 34
+};
+
+enum Effectiveness {
+ EFFECTIVE_NONE = 0, EFFECTIVE_DRAGON = 1, EFFECTIVE_UNDEAD = 2, EFFECTIVE_GOLEM = 3,
+ EFFECTIVE_INSECT = 4, EFFEctIVE_MONSTERS = 5, EFFECTIVE_ANIMAL = 6
+};
+
+struct ItemState {
+ byte _counter : 6; // Stores charges for Misc items, and the effective against for weapons
+ bool _cursed : 1;
+ bool _broken : 1;
+
+ /**
+ * Constructor
+ */
+ ItemState() : _counter(0), _cursed(false), _broken(false) {}
+
+ /**
+ * Clear the state
+ */
+ void clear() {
+ _counter = 0;
+ _cursed = _broken = false;
+ }
+
+ /**
+ * Returns true if the state is empty
+ */
+ bool empty() const { return !_counter && !_cursed && !_broken; }
+
+ /**
+ * Synchronizes the item's state
+ */
+ void synchronize(Common::Serializer &s);
+
+ /**
+ * Set the entire state value
+ */
+ void operator=(byte val);
+};
+
class XeenItem {
public:
int _material;
uint _id;
- int _bonusFlags;
+ ItemState _state;
int _frame;
public:
/**
@@ -64,6 +107,9 @@ public:
*/
static const char *getItemName(ItemCategory category, uint id);
public:
+ /**
+ * Constructor
+ */
XeenItem();
/**
@@ -77,6 +123,16 @@ public:
bool empty() const { return _id == 0; }
/**
+ * Returns true if the item is cursed or broken
+ */
+ bool isBad() const { return _state._cursed || _state._broken; }
+
+ /**
+ * Returns true for weapons if it's equipped
+ */
+ bool isEquipped() const { return _frame != 0; }
+
+ /**
* Synchronizes the data for the item
*/
void synchronize(Common::Serializer &s);
@@ -87,6 +143,11 @@ public:
ElementalCategory getElementalCategory() const;
/**
+ * Gets the elemental category for a given material
+ */
+ static ElementalCategory getElementalCategory(int material);
+
+ /**
* Gets the attribute category for the item
*/
AttributeCategory getAttributeCategory() const;
@@ -106,6 +167,11 @@ protected:
* Returns a text string listing all the stats/attributes of a given item
*/
virtual Common::String getAttributes(XeenItem &item, const Common::String &classes) = 0;
+
+ /**
+ * Capitalizes a passed description string that includes embedded formatting for the Items dialog
+ */
+ void capitalizeItem(Common::String &name);
public:
InventoryItems(Character *character, ItemCategory category);
virtual ~InventoryItems() {}
@@ -116,6 +182,11 @@ public:
void clear();
/**
+ * Handles copying items from one character to another
+ */
+ InventoryItems &operator=(const InventoryItems &src);
+
+ /**
* Return whether a given item passes class-based usage restrictions
* @param itemId Item Index
* @param suppressError If true, no dialog is shown if the item doesn't pass restrictions
@@ -190,6 +261,11 @@ public:
* Enchants a weapon
*/
virtual void enchantItem(int itemIndex, int amount);
+
+ /**
+ * Returns true if the character has an Elder weapon in Swords of Xeen
+ */
+ bool hasElderWeapon() const;
};
class ArmorItems : public InventoryItems {
@@ -259,10 +335,9 @@ public:
class InventoryItemsGroup {
private:
- InventoryItems *_itemSets[4];
+ Character *_owner;
public:
- InventoryItemsGroup(InventoryItems &weapons, InventoryItems &armor,
- InventoryItems &accessories, InventoryItems &misc);
+ InventoryItemsGroup(Character *owner) : _owner(owner) {}
/**
* Returns the inventory items for a given category
@@ -270,9 +345,24 @@ public:
InventoryItems &operator[](ItemCategory category);
/**
+ * Returns the inventory items for a given category
+ */
+ const InventoryItems &operator[](ItemCategory category) const;
+
+ /**
* Breaks all the items in a given character's inventory
*/
void breakAllItems();
+
+ /**
+ * Curses or curses all the items
+ */
+ void curseUncurse(bool curse);
+
+ /**
+ * Returns true if the character has any cursed items
+ */
+ bool hasCursedItems() const;
};
} // End of namespace Xeen
diff --git a/engines/xeen/locations.cpp b/engines/xeen/locations.cpp
index 2690bf1ebc..7cbfc2bab3 100644
--- a/engines/xeen/locations.cpp
+++ b/engines/xeen/locations.cpp
@@ -35,12 +35,12 @@ namespace Xeen {
namespace Locations {
BaseLocation::BaseLocation(LocationAction action) : ButtonContainer(g_vm),
- _locationActionId(action), _isDarkCc(g_vm->_files->_isDarkCc),
+ _locationActionId(action), _ccNum(g_vm->_files->_ccNum),
_vocName("hello1.voc"), _exitToUi(false) {
- _townMaxId = (action >= SPHINX) ? 0 : Res.TOWN_MAXES[_isDarkCc][action];
+ _townMaxId = (action >= SPHINX) ? 0 : Res.TOWN_MAXES[_ccNum][action];
if (action < NO_ACTION) {
- _songName = Res.TOWN_ACTION_MUSIC[_isDarkCc][action];
- _townSprites.resize(Res.TOWN_ACTION_FILES[_isDarkCc][action]);
+ _songName = Res.TOWN_ACTION_MUSIC[_ccNum][action];
+ _townSprites.resize(Res.TOWN_ACTION_FILES[_ccNum][action]);
}
_animFrame = 0;
@@ -149,7 +149,7 @@ void BaseLocation::drawAnim(bool flag) {
// TODO: Figure out a clean way to split method into individual location classes
if (_locationActionId == BLACKSMITH) {
if (sound.isSoundPlaying()) {
- if (_isDarkCc) {
+ if (_ccNum) {
_townSprites[_drawFrameIndex / 8].draw(0, _drawFrameIndex % 8, _animPos);
_townSprites[2].draw(0, _vm->getRandomNumber(11) == 1 ? 9 : 10,
Common::Point(34, 33));
@@ -158,20 +158,20 @@ void BaseLocation::drawAnim(bool flag) {
}
} else {
_townSprites[_drawFrameIndex / 8].draw(0, _drawFrameIndex % 8, _animPos);
- if (_isDarkCc) {
+ if (_ccNum) {
_townSprites[2].draw(0, _vm->getRandomNumber(11) == 1 ? 9 : 10,
Common::Point(34, 33));
}
}
- } else if (!_isDarkCc || _locationActionId != TRAINING) {
+ } else if (!_ccNum || _locationActionId != TRAINING) {
if (!_townSprites[_drawFrameIndex / 8].empty())
_townSprites[_drawFrameIndex / 8].draw(0, _drawFrameIndex % 8, _animPos);
}
switch (_locationActionId) {
case BANK:
- if (sound.isSoundPlaying() || (_isDarkCc && _animFrame)) {
- if (_isDarkCc) {
+ if (sound.isSoundPlaying() || (_ccNum && _animFrame)) {
+ if (_ccNum) {
if (sound.isSoundPlaying() || _animFrame == 1) {
_townSprites[4].draw(0, _vm->getRandomNumber(13, 18),
Common::Point(8, 30));
@@ -189,7 +189,7 @@ void BaseLocation::drawAnim(bool flag) {
case GUILD:
if (!sound.isSoundPlaying()) {
- if (_isDarkCc) {
+ if (_ccNum) {
if (_animFrame) {
_animFrame ^= 1;
_townSprites[6].draw(0, _animFrame, Common::Point(8, 106));
@@ -201,7 +201,7 @@ void BaseLocation::drawAnim(bool flag) {
break;
case TAVERN:
- if (sound.isSoundPlaying() && _isDarkCc) {
+ if (sound.isSoundPlaying() && _ccNum) {
_townSprites[4].draw(0, _vm->getRandomNumber(7), Common::Point(153, 49));
}
break;
@@ -215,11 +215,11 @@ void BaseLocation::drawAnim(bool flag) {
case TRAINING:
if (sound.isSoundPlaying()) {
- if (_isDarkCc) {
+ if (_ccNum) {
_townSprites[_drawFrameIndex / 8].draw(0, _drawFrameIndex % 8, _animPos);
}
} else {
- if (_isDarkCc) {
+ if (_ccNum) {
_townSprites[0].draw(0, ++_animFrame % 8, Common::Point(8, 8));
_townSprites[5].draw(0, _vm->getRandomNumber(5), Common::Point(61, 74));
} else {
@@ -257,7 +257,7 @@ void BaseLocation::drawAnim(bool flag) {
_drawFrameIndex = (_drawFrameIndex + 1) % _townMaxId;
}
- if (_isDarkCc) {
+ if (_ccNum) {
if (_locationActionId == BLACKSMITH && (_drawFrameIndex == 4 || _drawFrameIndex == 13))
sound.playFX(45);
@@ -307,7 +307,7 @@ BankLocation::BankLocation() : BaseLocation(BANK) {
addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_icons1);
_animFrame = 1;
- _vocName = _isDarkCc ? "bank1.voc" : "banker.voc";
+ _vocName = _ccNum ? "bank1.voc" : "banker.voc";
}
Common::String BankLocation::createLocationText(Character &ch) {
@@ -320,7 +320,7 @@ Common::String BankLocation::createLocationText(Character &ch) {
}
void BankLocation::drawBackground() {
- if (_isDarkCc) {
+ if (_ccNum) {
_townSprites[4].draw(0, _vm->getRandomNumber(13, 18),
Common::Point(8, 30));
}
@@ -342,6 +342,7 @@ void BankLocation::depositWithdrawl(PartyBank whereId) {
Party &party = *g_vm->_party;
Sound &sound = *g_vm->_sound;
Windows &windows = *g_vm->_windows;
+ Window &w = windows[35];
int gold, gems;
if (whereId == WHERE_BANK) {
@@ -363,26 +364,24 @@ void BankLocation::depositWithdrawl(PartyBank whereId) {
XeenEngine::printMil(gold).c_str(),
XeenEngine::printMil(gems).c_str());
- windows[35].open();
- windows[35].writeString(msg);
- drawButtons(&windows[35]);
- windows[35].update();
+ w.open();
+ w.writeString(msg);
+ drawButtons(&w);
+ w.update();
sound.stopSound();
File voc("coina.voc");
ConsumableType consType = CONS_GOLD;
do {
- switch (wait()) {
- case Common::KEYCODE_o:
+ wait();
+ if (_buttonValue == Common::KEYCODE_o) {
consType = CONS_GOLD;
- break;
- case Common::KEYCODE_e:
+ } else if (_buttonValue == Common::KEYCODE_e) {
consType = CONS_GEMS;
+ } else if (_buttonValue == Common::KEYCODE_ESCAPE) {
break;
- case Common::KEYCODE_ESCAPE:
- break;
- default:
+ } else {
continue;
}
@@ -392,7 +391,7 @@ void BankLocation::depositWithdrawl(PartyBank whereId) {
(whereId == WHERE_PARTY && !party._gold && consType == CONS_GOLD)) {
party.notEnough(consType, whereId, WHERE_BANK, WT_LOC_WAIT);
} else {
- windows[35].writeString(Res.AMOUNT);
+ w.writeString(Res.AMOUNT);
int amount = NumericInput::show(_vm, 35, 10, 77);
if (amount) {
@@ -426,16 +425,19 @@ void BankLocation::depositWithdrawl(PartyBank whereId) {
sound.playSound(voc);
msg = Common::String::format(Res.GOLD_GEMS_2, Res.DEPOSIT_WITHDRAWL[whereId],
XeenEngine::printMil(gold).c_str(), XeenEngine::printMil(gems).c_str());
- windows[35].writeString(msg);
- windows[35].update();
+ w.writeString(msg);
+ w.update();
}
- } while (!g_vm->shouldExit() && _buttonValue != Common::KEYCODE_ESCAPE);
+ } while (!g_vm->shouldExit());
for (uint idx = 0; idx < _buttons.size(); ++idx)
_buttons[idx]._sprites = &_icons1;
_buttons[0]._value = Common::KEYCODE_d;
_buttons[1]._value = Common::KEYCODE_w;
_buttons[2]._value = Common::KEYCODE_ESCAPE;
+
+ w.close();
+ clearEvents();
}
/*------------------------------------------------------------------------*/
@@ -448,7 +450,7 @@ BlacksmithLocation::BlacksmithLocation() : BaseLocation(BLACKSMITH) {
addButton(Common::Rect(234, 74, 308, 82), 0);
addButton(Common::Rect(234, 84, 308, 92), 0);
- _vocName = _isDarkCc ? "see2.voc" : "whaddayo.voc";
+ _vocName = _ccNum ? "see2.voc" : "whaddayo.voc";
}
Common::String BlacksmithLocation::createLocationText(Character &ch) {
@@ -469,7 +471,7 @@ Character *BlacksmithLocation::doOptions(Character *c) {
intf.highlightChar(_buttonValue);
}
} else if (_buttonValue == Common::KEYCODE_b) {
- c = ItemsDialog::show(_vm, c, ITEMMODE_BLACKSMITH);
+ c = ItemsDialog::show(_vm, c, ITEMMODE_BUY);
_buttonValue = 0;
}
@@ -479,7 +481,7 @@ Character *BlacksmithLocation::doOptions(Character *c) {
void BlacksmithLocation::farewell() {
Sound &sound = *g_vm->_sound;
- if (_isDarkCc) {
+ if (_ccNum) {
sound.stopSound();
sound.playVoice("come1.voc", 1);
}
@@ -495,9 +497,9 @@ GuildLocation::GuildLocation() : BaseLocation(GUILD) {
addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b);
addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_s);
addButton(Common::Rect(234, 84, 308, 92), 0);
- g_vm->_mode = MODE_17;
+ g_vm->_mode = MODE_INTERACTIVE7;
- _vocName = _isDarkCc ? "parrot1.voc" : "guild10.voc";
+ _vocName = _ccNum ? "parrot1.voc" : "guild10.voc";
}
Common::String GuildLocation::createLocationText(Character &ch) {
@@ -524,17 +526,17 @@ Character *GuildLocation::doOptions(Character *c) {
if (!c->guildMember()) {
sound.stopSound();
_animFrame = 5;
- sound.playSound(_isDarkCc ? "skull1.voc" : "guild11.voc", 1);
+ sound.playSound(_ccNum ? "skull1.voc" : "guild11.voc", 1);
}
}
} else if (_buttonValue == Common::KEYCODE_s) {
if (c->guildMember())
- c = SpellsDialog::show(_vm, nullptr, c, 0x80);
+ c = SpellsDialog::show(_vm, this, c, SPELLS_DIALOG_INFO);
_buttonValue = 0;
- } else if (_buttonValue == Common::KEYCODE_c) {
+ } else if (_buttonValue == Common::KEYCODE_b) {
if (!c->noActions()) {
if (c->guildMember())
- c = SpellsDialog::show(_vm, nullptr, c, 0);
+ c = SpellsDialog::show(_vm, this, c, SPELLS_DIALOG_BUY);
_buttonValue = 0;
}
}
@@ -558,9 +560,9 @@ TavernLocation::TavernLocation() : BaseLocation(TAVERN) {
addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_f);
addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_t);
addButton(Common::Rect(234, 84, 308, 92), Common::KEYCODE_r);
- g_vm->_mode = MODE_17;
+ g_vm->_mode = MODE_INTERACTIVE7;
- _vocName = _isDarkCc ? "hello1.voc" : "hello.voc";
+ _vocName = _ccNum ? "hello1.voc" : "hello.voc";
}
Common::String TavernLocation::createLocationText(Character &ch) {
@@ -570,6 +572,7 @@ Common::String TavernLocation::createLocationText(Character &ch) {
}
Character *TavernLocation::doOptions(Character *c) {
+ EventsManager &events = *g_vm->_events;
Interface &intf = *g_vm->_interface;
Map &map = *g_vm->_map;
Party &party = *g_vm->_party;
@@ -620,19 +623,19 @@ Character *TavernLocation::doOptions(Character *c) {
case Common::KEYCODE_f: {
// Food
- if (party._mazeId == (_isDarkCc ? 29 : 28)) {
+ if (party._mazeId == (_ccNum ? 29 : 28)) {
_v22 = party._activeParty.size() * 15;
_v23 = 10;
idx = 0;
- } else if (_isDarkCc && party._mazeId == 31) {
+ } else if (_ccNum && party._mazeId == 31) {
_v22 = party._activeParty.size() * 60;
_v23 = 100;
idx = 1;
- } else if (!_isDarkCc && party._mazeId == 30) {
+ } else if (!_ccNum && party._mazeId == 30) {
_v22 = party._activeParty.size() * 50;
_v23 = 50;
idx = 1;
- } else if (_isDarkCc) {
+ } else if (_ccNum) {
_v22 = party._activeParty.size() * 120;
_v23 = 250;
idx = 2;
@@ -646,7 +649,7 @@ Character *TavernLocation::doOptions(Character *c) {
idx = 0;
}
- Common::String msg = _textStrings[(_isDarkCc ? 60 : 75) + idx];
+ Common::String msg = _textStrings[(_ccNum ? 60 : 75) + idx];
windows[10].close();
windows[12].open();
windows[12].writeString(msg);
@@ -658,7 +661,7 @@ Character *TavernLocation::doOptions(Character *c) {
} else if (party.subtract(CONS_GOLD, _v23, WHERE_PARTY, WT_LOC_WAIT)) {
party._food = _v22;
sound.stopSound();
- sound.playSound(_isDarkCc ? "thanks2.voc" : "thankyou.voc", 1);
+ sound.playSound(_ccNum ? "thanks2.voc" : "thankyou.voc", 1);
}
}
@@ -670,11 +673,11 @@ Character *TavernLocation::doOptions(Character *c) {
case Common::KEYCODE_r: {
// Rumors
- if (party._mazeId == (_isDarkCc ? 29 : 28)) {
+ if (party._mazeId == (_ccNum ? 29 : 28)) {
idx = 0;
- } else if (party._mazeId == (_isDarkCc ? 31 : 30)) {
+ } else if (party._mazeId == (_ccNum ? 31 : 30)) {
idx = 10;
- } else if (_isDarkCc || party._mazeId == 49) {
+ } else if (_ccNum || party._mazeId == 49) {
idx = 20;
}
@@ -693,12 +696,12 @@ Character *TavernLocation::doOptions(Character *c) {
case Common::KEYCODE_s: {
// Sign In
// Set location and position for afterwards
- idx = _isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28;
+ idx = _ccNum ? (party._mazeId - 29) >> 1 : party._mazeId - 28;
assert(idx >= 0);
- party._mazePosition.x = Res.TAVERN_EXIT_LIST[_isDarkCc ? 1 : 0][_locationActionId][idx][0];
- party._mazePosition.y = Res.TAVERN_EXIT_LIST[_isDarkCc ? 1 : 0][_locationActionId][idx][1];
+ party._mazePosition.x = Res.TAVERN_EXIT_LIST[_ccNum][_locationActionId][idx][0];
+ party._mazePosition.y = Res.TAVERN_EXIT_LIST[_ccNum][_locationActionId][idx][1];
- if (!_isDarkCc || party._mazeId == 29)
+ if (!_ccNum || party._mazeId == 29)
party._mazeDirection = DIR_WEST;
else if (party._mazeId == 31)
party._mazeDirection = DIR_EAST;
@@ -708,13 +711,22 @@ Character *TavernLocation::doOptions(Character *c) {
party._priorMazeId = party._mazeId;
for (idx = 0; idx < (int)party._activeParty.size(); ++idx) {
party._activeParty[idx]._savedMazeId = party._mazeId;
- party._activeParty[idx]._xeenSide = map._loadDarkSide;
+ party._activeParty[idx]._xeenSide = map._loadCcNum;
}
- g_vm->_mode = MODE_17;
+ g_vm->_mode = MODE_INTERACTIVE7;
party.addTime(1440);
party._mazeId = 0;
+ // Say farewell
+ farewell();
+ while (sound.isSoundPlaying())
+ events.wait(1);
+
+ // Animate closing a scroll
+ doScroll(true, false);
+ sound.stopAllAudio();
+
// Show the party dialog
PartyDialog::show(g_vm);
@@ -744,23 +756,23 @@ Character *TavernLocation::doOptions(Character *c) {
wait();
} else if (party.subtract(CONS_GOLD, 1, WHERE_PARTY, WT_LOC_WAIT)) {
sound.stopSound();
- sound.playSound(_isDarkCc ? "thanks2.voc" : "thankyou.voc", 1);
+ sound.playSound(_ccNum ? "thanks2.voc" : "thankyou.voc", 1);
- if (party._mazeId == (_isDarkCc ? 29 : 28)) {
+ if (party._mazeId == (_ccNum ? 29 : 28)) {
_v24 = 30;
- } else if (_isDarkCc && party._mazeId == 31) {
+ } else if (_ccNum && party._mazeId == 31) {
_v24 = 40;
- } else if (!_isDarkCc && party._mazeId == 45) {
+ } else if (!_ccNum && party._mazeId == 45) {
_v24 = 45;
- } else if (!_isDarkCc && party._mazeId == 49) {
+ } else if (!_ccNum && party._mazeId == 49) {
_v24 = 60;
- } else if (_isDarkCc) {
+ } else if (_ccNum) {
_v24 = 50;
}
Common::String msg = _textStrings[map.mazeData()._tavernTips + _v24];
map.mazeData()._tavernTips = (map.mazeData()._tavernTips + 1) /
- (_isDarkCc ? 10 : 15);
+ (_ccNum ? 10 : 15);
Window &w = windows[12];
w.open();
@@ -786,7 +798,7 @@ void TavernLocation::farewell() {
Sound &sound = *g_vm->_sound;
sound.stopSound();
- sound.playVoice(_isDarkCc ? "gdluck1.voc" : "goodbye.voc", 1);
+ sound.playVoice(_ccNum ? "gdluck1.voc" : "goodbye.voc");
map.mazeData()._mazeNumber = party._mazeId;
}
@@ -802,7 +814,7 @@ TempleLocation::TempleLocation() : BaseLocation(TEMPLE) {
_v10 = _v11 = 0;
_v12 = _v13 = 0;
_v14 = 0;
- _flag1 = false;
+ _blessed = false;
_v5 = _v6 = 0;
_icons1.load("esc.icn");
@@ -812,28 +824,32 @@ TempleLocation::TempleLocation() : BaseLocation(TEMPLE) {
addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_u);
addButton(Common::Rect(234, 84, 308, 92), 0);
- _vocName = _isDarkCc ? "help2.voc" : "maywe2.voc";
+ _vocName = _ccNum ? "help2.voc" : "maywe2.voc";
}
Common::String TempleLocation::createLocationText(Character &ch) {
Party &party = *g_vm->_party;
+ _donation = 0;
+ _uncurseCost = 0;
+ _healCost = 0;
+ _v5 = _v6 = 0;
- if (party._mazeId == (_isDarkCc ? 29 : 28)) {
+ if (party._mazeId == (_ccNum ? 29 : 28)) {
_v10 = _v11 = _v12 = _v13 = 0;
_v14 = 10;
- } else if (party._mazeId == (_isDarkCc ? 31 : 30)) {
+ } else if (party._mazeId == (_ccNum ? 31 : 30)) {
_v13 = 10;
_v12 = 50;
_v11 = 500;
_v10 = 100;
_v14 = 25;
- } else if (party._mazeId == (_isDarkCc ? 37 : 73)) {
+ } else if (party._mazeId == (_ccNum ? 37 : 73)) {
_v13 = 20;
_v12 = 100;
_v11 = 1000;
_v10 = 200;
_v14 = 50;
- } else if (_isDarkCc || party._mazeId == 49) {
+ } else if (_ccNum || party._mazeId == 49) {
_v13 = 100;
_v12 = 500;
_v11 = 5000;
@@ -862,17 +878,11 @@ Common::String TempleLocation::createLocationText(Character &ch) {
_v5 = (_currentCharLevel * 1000) + (ch._conditions[ERADICATED] * 500) + _v11;
}
- for (int idx = 0; idx < 9; ++idx) {
- _uncurseCost |= ch._weapons[idx]._bonusFlags & 0x40;
- _uncurseCost |= ch._armor[idx]._bonusFlags & 0x40;
- _uncurseCost |= ch._accessories[idx]._bonusFlags & 0x40;
- _uncurseCost |= ch._misc[idx]._bonusFlags & 0x40;
- }
-
- if (_uncurseCost || ch._conditions[CURSED])
- _v5 = (_currentCharLevel * 20) + _v10;
+ bool isCursed = ch._items.hasCursedItems();
+ if (isCursed || ch._conditions[CURSED])
+ _uncurseCost = (_currentCharLevel * 20) + _v10;
- _donation = _flag1 ? 0 : _v14;
+ _donation = _blessed ? 0 : _v14;
_healCost += _v6 + _v5;
return Common::String::format(Res.TEMPLE_TEXT, ch._name.c_str(),
@@ -905,9 +915,9 @@ Character *TempleLocation::doOptions(Character *c) {
if (_donation && party.subtract(CONS_GOLD, _donation, WHERE_PARTY, WT_LOC_WAIT)) {
sound.stopSound();
sound.playSound("coina.voc", 1);
- _dayOfWeek = (_dayOfWeek + 1) / 10;
+ _dayOfWeek = (_dayOfWeek + 1) % 10;
- if (_dayOfWeek == (party._day / 10)) {
+ if (_dayOfWeek == (party._day % 10)) {
party._clairvoyanceActive = true;
party._lightCount = 1;
@@ -920,7 +930,7 @@ Character *TempleLocation::doOptions(Character *c) {
intf.drawParty(true);
sound.stopSound();
sound.playSound("ahh.voc");
- _flag1 = true;
+ _blessed = true;
_donation = 0;
}
}
@@ -955,13 +965,8 @@ Character *TempleLocation::doOptions(Character *c) {
case Common::KEYCODE_u:
if (_uncurseCost && party.subtract(CONS_GOLD, _uncurseCost, WHERE_PARTY, WT_LOC_WAIT)) {
- for (int idx = 0; idx < 9; ++idx) {
- c->_weapons[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
- c->_armor[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
- c->_accessories[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
- c->_misc[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
- }
-
+ c->_items.curseUncurse(false);
+ c->_conditions[CURSED] = 0;
_farewellTime = 1440;
intf.drawParty(true);
sound.stopSound();
@@ -988,12 +993,12 @@ TrainingLocation::TrainingLocation() : BaseLocation(TRAINING) {
addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1);
addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_icons1);
- _vocName = _isDarkCc ? "youtrn1.voc" : "training.voc";
+ _vocName = _ccNum ? "youtrn1.voc" : "training.voc";
}
Common::String TrainingLocation::createLocationText(Character &ch) {
Party &party = *g_vm->_party;
- if (_isDarkCc) {
+ if (_ccNum) {
switch (party._mazeId) {
case 29:
// Castleview
@@ -1040,11 +1045,12 @@ Common::String TrainingLocation::createLocationText(Character &ch) {
} else if (ch._level._permanent >= _maxLevel) {
// At maximum level
_experienceToNextLevel = 1;
- msg = Common::String::format(Res.LEARNED_ALL, ch._name.c_str());
+ msg = Common::String::format(Res.TRAINING_LEARNED_ALL, ch._name.c_str());
} else {
// Eligble for level increase
+ uint cost = ch._level._permanent * ch._level._permanent * 10;
msg = Common::String::format(Res.ELIGIBLE_FOR_LEVEL,
- ch._name.c_str(), ch._level._permanent + 1);
+ ch._name.c_str(), ch._level._permanent + 1, cost);
}
return Common::String::format(Res.TRAINING_TEXT, msg.c_str(),
@@ -1079,9 +1085,9 @@ Character *TrainingLocation::doOptions(Character *c) {
Common::String name;
if (c->_level._permanent >= _maxLevel) {
- name = _isDarkCc ? "gtlost.voc" : "trainin1.voc";
+ name = _ccNum ? "gtlost.voc" : "trainin1.voc";
} else {
- name = _isDarkCc ? "gtlost.voc" : "trainin0.voc";
+ name = _ccNum ? "gtlost.voc" : "trainin0.voc";
}
sound.playSound(name);
@@ -1090,7 +1096,7 @@ Character *TrainingLocation::doOptions(Character *c) {
if (party.subtract(CONS_GOLD, (c->_level._permanent * c->_level._permanent) * 10, WHERE_PARTY, WT_LOC_WAIT)) {
_drawFrameIndex = 0;
sound.stopSound();
- sound.playSound(_isDarkCc ? "prtygd.voc" : "trainin2.voc", 1);
+ sound.playSound(_ccNum ? "prtygd.voc" : "trainin2.voc", 1);
c->_experience -= c->nextExperienceLevel() -
(c->getCurrentExperience() - c->_experience);
@@ -1147,10 +1153,10 @@ int ArenaLocation::show() {
}
Common::String format = map._events._text[3];
- Common::String count = Common::String::format("%05u", party._activeParty[0]._awards[WARZONE_AWARD]);
- int numIdx = count[3] == '1' ? 0 : count[4] - '0';
- Common::String msg = Common::String::format(format.c_str(), count.c_str(), SUFFIXES[numIdx]);
-
+ int count = party._activeParty[0]._awards[WARZONE_AWARD];
+ int suffixNum = (count < 10) ? count : 0;
+ Common::String msg = Common::String::format(format.c_str(), count, SUFFIXES[suffixNum]);
+
LocationMessage::show(27, Res.WARZONE_BATTLE_MASTER, msg, 1);
map.load(28);
@@ -1165,8 +1171,7 @@ int ArenaLocation::show() {
}
}
- check = LocationMessage::show(27, Res.WARZONE_BATTLE_MASTER,
- map._events._text[0].c_str(), 300);
+ check = LocationMessage::show(27, Res.WARZONE_BATTLE_MASTER, map._events._text[0].c_str(), 0);
if (!check) {
LocationMessage::show(27, Res.WARZONE_BATTLE_MASTER,
map._events._text[1].c_str(), 300);
@@ -1191,7 +1196,7 @@ int ArenaLocation::show() {
if (howMany == 0)
goto exit;
- LocationMessage::show(27, Res.WARZONE_BATTLE_MASTER, map._events._text[2], 300);
+ LocationMessage::show(27, Res.WARZONE_BATTLE_MASTER, map._events._text[2], 1);
// Clear monsters array
party._mazeDirection = DIR_EAST;
@@ -1236,7 +1241,7 @@ exit:
/*------------------------------------------------------------------------*/
-CutsceneLocation::CutsceneLocation(LocationAction action) : BaseLocation(action), _mazeFlag(false) {
+CutsceneLocation::CutsceneLocation(LocationAction action) : BaseLocation(action), _keyFound(false) {
Party &party = *g_vm->_party;
_mazeId = party._mazeId;
_mazePos = party._mazePosition;
@@ -1279,16 +1284,17 @@ int ReaperCutscene::show() {
Sound &sound = *g_vm->_sound;
Windows &windows = *g_vm->_windows;
- SpriteResource sprites1(_isDarkCc ? "tower1.zom" : "tower.vga", _isDarkCc);
- SpriteResource sprites2(_isDarkCc ? "tower2.zom" : "freap.vga", _isDarkCc);
+ SpriteResource sprites1(_ccNum ? "tower1.zom" : "tower.vga", _ccNum);
+ SpriteResource sprites2(_ccNum ? "tower2.zom" : "freap.vga", _ccNum);
Graphics::ManagedSurface savedBg;
savedBg.copyFrom(screen);
+ getNewLocation();
for (int idx = 13; idx >= 0; --idx) {
events.updateGameCounter();
- sprites1.draw(0, 0, Common::Point(REAPER_X1[_isDarkCc][idx], REAPER_Y1[_isDarkCc][idx]), 0, idx);
- if (_isDarkCc) {
+ sprites1.draw(0, 0, Common::Point(REAPER_X1[_ccNum][idx], REAPER_Y1[_ccNum][idx]), 0, idx);
+ if (_ccNum) {
sprites1.draw(0, 1, Common::Point(REAPER_X2[idx], REAPER_Y1[1][idx]), 0, idx);
sprites1.draw(0, party._isNight ? 3 : 2, Common::Point(REAPER_X3[idx], REAPER_Y1[1][idx]), 0, idx);
}
@@ -1296,7 +1302,7 @@ int ReaperCutscene::show() {
WAIT(1);
}
- if (_isDarkCc) {
+ if (_ccNum) {
for (int idx = -200; idx < 0; idx += 16) {
events.updateGameCounter();
sprites1.draw(0, 0, Common::Point(0, 0));
@@ -1319,18 +1325,23 @@ int ReaperCutscene::show() {
sound.setMusicPercent(38);
sprites1.draw(0, 0, Common::Point(0, 0));
- if (_isDarkCc) {
+ if (_ccNum) {
sprites1.draw(0, 1, Common::Point(160, 0));
sprites1.draw(0, party._isNight ? 3 : 2);
}
- _subtitles.setLine(_mazeFlag ? 5 : 6);
- sound.playVoice(_mazeFlag ? "reaper12.voc" : "reaper14.voc");
+ if (!_ccNum) {
+ _subtitles.setLine(_keyFound ? 5 : 6);
+ sound.playVoice(_keyFound ? "reaper12.voc" : "reaper14.voc");
+ } else if (_keyFound) {
+ _subtitles.setLine(2);
+ sound.playVoice("howdid1.voc");
+ }
do {
events.updateGameCounter();
int frame = g_vm->getRandomNumber(4);
- if (_isDarkCc) {
+ if (_ccNum) {
sprites2.draw(0, frame);
sprites2.draw(0, frame + 5, Common::Point(160, 0));
} else {
@@ -1344,21 +1355,23 @@ int ReaperCutscene::show() {
} while (sound.isSoundPlaying());
sprites2.draw(0, 0, Common::Point(0, 0));
- if (_isDarkCc)
+ if (_ccNum)
sprites2.draw(0, 5, Common::Point(160, 0));
windows[0].update();
WAIT(7);
- sound.playVoice(_mazeFlag ? "reaper12.voc" : "reaper14.voc");
- if (_mazeFlag)
- sound.playVoice(_isDarkCc ? "goin1.voc" : "reaper13.voc");
- else
- sound.playVoice(_isDarkCc ? "needkey1.voc" : "reaper15.voc");
+ if (_keyFound) {
+ sound.playVoice(_ccNum ? "goin1.voc" : "reaper13.voc");
+ } else {
+ if (_ccNum)
+ _subtitles.setLine(3);
+ sound.playVoice(_ccNum ? "needkey1.voc" : "reaper15.voc");
+ }
do {
events.updateGameCounter();
int frame = g_vm->getRandomNumber(4);
- if (_isDarkCc) {
+ if (_ccNum) {
sprites2.draw(0, frame, Common::Point(0, 0));
sprites2.draw(0, frame + 5, Common::Point(160, 0));
} else {
@@ -1370,18 +1383,18 @@ int ReaperCutscene::show() {
} while (_subtitles.lineActive());
sprites2.draw(0, 0, Common::Point(0, 0));
- if (_isDarkCc)
+ if (_ccNum)
sprites2.draw(0, 5, Common::Point(160, 0));
windows[0].update();
WAIT(1);
- if (_mazeFlag) {
+ if (_keyFound) {
for (int idx = 0; idx < 14; ++idx) {
events.updateGameCounter();
screen.blitFrom(savedBg);
- sprites1.draw(0, 0, Common::Point(REAPER_X1[_isDarkCc][idx], REAPER_Y1[_isDarkCc][idx]), 0, idx);
-
- if (_isDarkCc) {
+ sprites1.draw(0, 0, Common::Point(REAPER_X1[_ccNum][idx], REAPER_Y1[_ccNum][idx]), 0, idx);
+
+ if (_ccNum) {
sprites1.draw(0, 1, Common::Point(REAPER_X2[idx], REAPER_Y1[1][idx]), 0, idx);
sprites1.draw(0, party._isNight ? 3 : 2, Common::Point(REAPER_X3[idx], REAPER_Y1[1][idx]), 0, idx);
}
@@ -1415,14 +1428,14 @@ void ReaperCutscene::getNewLocation() {
Map &map = *g_vm->_map;
Party &party = *g_vm->_party;
- if (_isDarkCc) {
+ if (_ccNum) {
switch (party._mazeId) {
case 3:
if (party._questItems[40]) {
_mazeId = 57;
_mazePos = Common::Point(11, 8);
_mazeDir = DIR_WEST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1431,7 +1444,7 @@ void ReaperCutscene::getNewLocation() {
_mazeId = 55;
_mazePos = Common::Point(3, 8);
_mazeDir = DIR_EAST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1440,7 +1453,16 @@ void ReaperCutscene::getNewLocation() {
_mazeId = 69;
_mazePos = Common::Point(7, 4);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
+ }
+ break;
+
+ case 16:
+ if (party._questItems[41]) {
+ _mazeId = 61;
+ _mazePos = Common::Point(7, 12);
+ _mazeDir = DIR_SOUTH;
+ _keyFound = true;
}
break;
@@ -1449,7 +1471,7 @@ void ReaperCutscene::getNewLocation() {
_mazeId = 65;
_mazePos = Common::Point(3, 8);
_mazeDir = DIR_EAST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1458,7 +1480,7 @@ void ReaperCutscene::getNewLocation() {
_mazeId = 53;
_mazePos = Common::Point(11, 8);
_mazeDir = DIR_WEST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1468,12 +1490,12 @@ void ReaperCutscene::getNewLocation() {
} else {
switch (party._mazeId) {
case 7:
- if (party._questItems[30]) {
- map._loadDarkSide = true;
+ if (party._questItems[46]) {
+ map._loadCcNum = 1;
_mazeId = 113;
_mazePos = Common::Point(7, 4);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1482,17 +1504,17 @@ void ReaperCutscene::getNewLocation() {
_mazeId = 55;
_mazePos = Common::Point(3, 8);
_mazeDir = DIR_EAST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
case 13:
- if (party._questItems[29]) {
- map._loadDarkSide = true;
+ if (party._questItems[45]) {
+ map._loadCcNum = 1;
_mazeId = 117;
_mazePos = Common::Point(7, 4);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1501,7 +1523,7 @@ void ReaperCutscene::getNewLocation() {
_mazeId = 59;
_mazePos = Common::Point(11, 8);
_mazeDir = DIR_WEST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1510,7 +1532,7 @@ void ReaperCutscene::getNewLocation() {
_mazeId = 51;
_mazePos = Common::Point(7, 12);
_mazeDir = DIR_SOUTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1545,28 +1567,29 @@ int GolemCutscene::show() {
Sound &sound = *g_vm->_sound;
Windows &windows = *g_vm->_windows;
SpriteResource sprites1, sprites2[2];
- sprites1.load(_isDarkCc ? "dung1.zom" : "golmback.vga");
- sprites2[0].load(_isDarkCc ? "dung2.zom" : "golem.vga");
- if (_isDarkCc)
+ sprites1.load(_ccNum ? "dung1.zom" : "golmback.vga");
+ sprites2[0].load(_ccNum ? "dung2.zom" : "golem.vga");
+ if (_ccNum)
sprites2[1].load("dung3.zom");
// Save the screen
Graphics::ManagedSurface savedBg;
savedBg.copyFrom(screen);
+ getNewLocation();
- for (int idx = (_isDarkCc ? 8 : 11); idx >= 0; --idx) {
+ for (int idx = (_ccNum ? 8 : 11); idx >= 0; --idx) {
events.updateGameCounter();
screen.blitFrom(savedBg);
sprites1.draw(0, 0,
- Common::Point(GOLEM_X1[_isDarkCc][idx], GOLEM_Y1[_isDarkCc][idx]), 0, idx);
+ Common::Point(GOLEM_X1[_ccNum][idx], GOLEM_Y1[_ccNum][idx]), 0, idx);
sprites1.draw(0, 1,
- Common::Point(GOLEM_X2[_isDarkCc][idx], GOLEM_Y1[_isDarkCc][idx]), 0, idx);
+ Common::Point(GOLEM_X2[_ccNum][idx], GOLEM_Y1[_ccNum][idx]), 0, idx);
windows[0].update();
WAIT(1);
}
- if (_isDarkCc)
+ if (!_ccNum)
sound.playSound("ogre.voc");
for (int idx = -200; idx < 0; idx += 16) {
@@ -1574,13 +1597,13 @@ int GolemCutscene::show() {
sprites1.draw(0, 0, Common::Point(0, 0));
sprites1.draw(0, 1, Common::Point(160, 0));
sprites2[0].draw(0, 0, Common::Point(idx, 0), SPRFLAG_800);
- sprites2[_isDarkCc].draw(0, 1, Common::Point(idx + 160, 0), SPRFLAG_800);
+ sprites2[_ccNum].draw(0, 1, Common::Point(idx + 160, 0), SPRFLAG_800);
- if (!_isDarkCc)
+ if (!_ccNum)
sprites2[0].draw(0, 2, Common::Point(idx + g_vm->getRandomNumber(9) - 5,
g_vm->getRandomNumber(9) - 5), SPRFLAG_800);
-
- if (!_isDarkCc && !sound.isSoundPlaying())
+
+ if (!_ccNum && !sound.isSoundPlaying())
sound.playSound("ogre.voc");
WAIT(1);
@@ -1589,28 +1612,34 @@ int GolemCutscene::show() {
sprites1.draw(0, 0, Common::Point(0, 0));
sprites1.draw(0, 1, Common::Point(160, 0));
sprites2[0].draw(0, 0, Common::Point(0, 0));
- sprites2[_isDarkCc].draw(0, _isDarkCc ? 0 : 1, Common::Point(160, 0));
- if (!_isDarkCc)
+ sprites2[_ccNum].draw(0, 1 - _ccNum, Common::Point(160, 0));
+ if (!_ccNum)
sprites2[0].draw(0, 2);
windows[0].update();
while (sound.isSoundPlaying()) {
+ _subtitles.show();
WAIT(1);
}
sound.setMusicPercent(38);
- _subtitles.setLine(_mazeFlag ? 8 : 7);
- sound.playVoice(_mazeFlag ? "golem15.voc" : "golem13.voc");
+ if (_ccNum) {
+ _subtitles.setLine(_keyFound ? 5 : 4);
+ sound.playVoice("what2.voc");
+ } else {
+ _subtitles.setLine(_keyFound ? 8 : 7);
+ sound.playVoice(_keyFound ? "golem15.voc" : "golem13.voc");
+ }
do {
events.updateGameCounter();
sprites1.draw(0, 0, Common::Point(0, 0));
sprites1.draw(0, 1, Common::Point(160, 0));
- if (_isDarkCc) {
+ if (_ccNum) {
int frame = g_vm->getRandomNumber(6);
sprites2[0].draw(0, frame, Common::Point(0, 0));
- sprites2[1].draw(1, frame, Common::Point(160, 0));
+ sprites2[1].draw(0, frame, Common::Point(160, 0));
} else {
sprites2[0].draw(0, 0, Common::Point(0, 0));
sprites2[0].draw(0, 1, Common::Point(160, 0));
@@ -1618,28 +1647,30 @@ int GolemCutscene::show() {
g_vm->getRandomNumber(9) - 3));
}
+ _subtitles.show();
WAIT(1);
} while (sound.isSoundPlaying());
sprites1.draw(0, 0, Common::Point(0, 0));
sprites1.draw(0, 1, Common::Point(160, 0));
sprites2[0].draw(0, 0, Common::Point(0, 0));
- sprites2[_isDarkCc].draw(0, _isDarkCc ? 0 : 1, Common::Point(160, 0));
- if (!_isDarkCc)
+ sprites2[_ccNum].draw(0, 1 - _ccNum, Common::Point(160, 0));
+ if (!_ccNum)
sprites2[0].draw(0, 2);
windows[0].update();
events.updateGameCounter();
- events.wait(_isDarkCc ? 10 : 1);
+ if (_subtitles.wait(_ccNum ? 10 : 1))
+ goto exit;
- if (!_isDarkCc) {
+ if (_ccNum) {
+ sound.playVoice(_keyFound ? "go2.voc" : "key2.voc");
+ } else {
sound.playVoice("ogre.voc");
while (sound.isSoundPlaying())
events.pollEventsAndWait();
- sound.playVoice(_mazeFlag ? "golem16.voc" : "golem14.voc");
- } else {
- sound.playVoice(_mazeFlag ? "go2.voc" : "key2.voc");
+ sound.playVoice(_keyFound ? "golem16.voc" : "golem14.voc");
}
do {
@@ -1647,10 +1678,10 @@ int GolemCutscene::show() {
sprites1.draw(0, 0, Common::Point(0, 0));
sprites1.draw(0, 1, Common::Point(160, 0));
- if (_isDarkCc) {
+ if (_ccNum) {
int frame = g_vm->getRandomNumber(6);
sprites2[0].draw(0, frame, Common::Point(0, 0));
- sprites2[1].draw(1, frame, Common::Point(160, 0));
+ sprites2[1].draw(0, frame, Common::Point(160, 0));
} else {
sprites2[0].draw(0, 0, Common::Point(0, 0));
sprites2[0].draw(0, 1, Common::Point(160, 0));
@@ -1659,31 +1690,28 @@ int GolemCutscene::show() {
}
windows[0].update();
+ _subtitles.show();
WAIT(1);
- } while (sound.isSoundPlaying());
+ } while (_subtitles.lineActive());
sprites1.draw(0, 0, Common::Point(0, 0));
sprites1.draw(0, 1, Common::Point(160, 0));
sprites2[0].draw(0, 0, Common::Point(0, 0));
- sprites2[_isDarkCc].draw(0, _isDarkCc ? 0 : 1, Common::Point(160, 0));
- if (!_isDarkCc)
+ sprites2[_ccNum].draw(0, 1 - _ccNum, Common::Point(160, 0));
+ if (!_ccNum)
sprites2[0].draw(0, 2);
-
windows[0].update();
- while (_subtitles.lineActive()) {
- WAIT(1);
- }
sound.setMusicPercent(75);
- if (!_mazeFlag) {
- for (int idx = 0; !g_vm->shouldExit() && idx < (_isDarkCc ? 9 : 12); ++idx) {
+ if (!_keyFound) {
+ for (int idx = 0; !g_vm->shouldExit() && idx < (_ccNum ? 9 : 12); ++idx) {
events.updateGameCounter();
screen.blitFrom(savedBg);
sprites1.draw(0, 0,
- Common::Point(GOLEM_X1[_isDarkCc][idx], GOLEM_Y1[_isDarkCc][idx]), 0, idx);
+ Common::Point(GOLEM_X1[_ccNum][idx], GOLEM_Y1[_ccNum][idx]), 0, idx);
sprites1.draw(0, 1,
- Common::Point(GOLEM_X2[_isDarkCc][idx], GOLEM_Y1[_isDarkCc][idx]), 0, idx);
+ Common::Point(GOLEM_X2[_ccNum][idx], GOLEM_Y1[_ccNum][idx]), 0, idx);
windows[0].update();
WAIT(1);
@@ -1712,14 +1740,14 @@ void GolemCutscene::getNewLocation() {
Map &map = *g_vm->_map;
Party &party = *g_vm->_party;
- if (_isDarkCc) {
+ if (_ccNum) {
switch (party._mazeId) {
case 12:
if (party._questItems[47]) {
_mazeId = 73;
_mazePos = Common::Point(0, 7);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1728,7 +1756,7 @@ void GolemCutscene::getNewLocation() {
_mazeId = 83;
_mazePos = Common::Point(11, 1);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1737,7 +1765,7 @@ void GolemCutscene::getNewLocation() {
_mazeId = 121;
_mazePos = Common::Point(18, 0);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1746,7 +1774,7 @@ void GolemCutscene::getNewLocation() {
_mazeId = 78;
_mazePos = Common::Point(8, 14);
_mazeDir = DIR_SOUTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1760,7 +1788,7 @@ void GolemCutscene::getNewLocation() {
_mazeId = 81;
_mazePos = Common::Point(1, 17);
_mazeDir = DIR_EAST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1769,17 +1797,17 @@ void GolemCutscene::getNewLocation() {
_mazeId = 80;
_mazePos = Common::Point(29, 16);
_mazeDir = DIR_WEST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
case 19:
if (party._questItems[50]) {
- map._loadDarkSide = true;
+ map._loadCcNum = 1;
_mazeId = 121;
_mazePos = Common::Point(18, 0);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1788,7 +1816,7 @@ void GolemCutscene::getNewLocation() {
_mazeId = 79;
_mazePos = Common::Point(5, 16);
_mazeDir = DIR_EAST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1833,9 +1861,9 @@ int DwarfCutscene::show() {
Sound &sound = *g_vm->_sound;
Windows &windows = *g_vm->_windows;
- SpriteResource sprites1(_isDarkCc ? "town1.zom" : "dwarf1.vga");
- SpriteResource sprites2(_isDarkCc ? "town2.zom" : "dwarf3.vga");
- SpriteResource sprites3(_isDarkCc ? "town3.zom" : "dwarf2.vga");
+ SpriteResource sprites1(_ccNum ? "town1.zom" : "dwarf1.vga");
+ SpriteResource sprites2(_ccNum ? "town2.zom" : "dwarf3.vga");
+ SpriteResource sprites3(_ccNum ? "town3.zom" : "dwarf2.vga");
getNewLocation();
// Save the screen contents
@@ -1843,17 +1871,17 @@ int DwarfCutscene::show() {
savedBg.copyFrom(screen);
// Zoom in on the mine entrance
- for (int idx = (_isDarkCc ? 10 : 12); idx >= 0; --idx) {
+ for (int idx = (_ccNum ? 10 : 12); idx >= 0; --idx) {
events.updateGameCounter();
screen.blitFrom(savedBg);
sprites1.draw(0, 0,
- Common::Point(DWARF_X0[_isDarkCc][idx], DWARF_Y[_isDarkCc][idx]), 0, idx);
+ Common::Point(DWARF_X0[_ccNum][idx], DWARF_Y[_ccNum][idx]), 0, idx);
sprites1.draw(0, 1,
- Common::Point(DWARF_X1[_isDarkCc][idx], DWARF_Y[_isDarkCc][idx]), 0, idx);
- if (_isDarkCc)
+ Common::Point(DWARF_X1[_ccNum][idx], DWARF_Y[_ccNum][idx]), 0, idx);
+ if (_ccNum)
sprites1.draw(0, 2,
- Common::Point(DWARF_X2[idx], DWARF_Y[_isDarkCc][idx]), 0, idx);
+ Common::Point(DWARF_X2[idx], DWARF_Y[_ccNum][idx]), 0, idx);
windows[0].update();
WAIT(1);
@@ -1867,7 +1895,7 @@ int DwarfCutscene::show() {
events.updateGameCounter();
screen.blitFrom(savedBg);
- sprites2.draw(0, 0, Common::Point(DWARF2_X[_isDarkCc][idx], DWARF2_Y[_isDarkCc][idx]), 0, idx);
+ sprites2.draw(0, 0, Common::Point(DWARF2_X[_ccNum][idx], DWARF2_Y[_ccNum][idx]), 0, idx);
windows[0].update();
WAIT(1);
}
@@ -1876,16 +1904,19 @@ int DwarfCutscene::show() {
screen.blitFrom(savedBg);
sprites2.draw(0, 0);
windows[0].update();
- _subtitles.setLine(_isDarkCc ? 0 : 4);
+ if (_ccNum)
+ _subtitles.setLine(_keyFound ? 7 : 8);
+ else
+ _subtitles.setLine(4);
- for (int idx = 0; idx < (_isDarkCc ? 2 : 3); ++idx) {
+ for (int idx = 0; idx < (_ccNum ? 2 : 3); ++idx) {
switch (idx) {
case 0:
- sound.playSound(_isDarkCc ? "pass2.voc" : "dwarf10.voc");
+ sound.playSound(_ccNum ? "pass2.voc" : "dwarf10.voc");
break;
case 1:
- if (_isDarkCc) {
+ if (_ccNum) {
sprites2.draw(0, 0);
sprites3.draw(0, 0);
_subtitles.show();
@@ -1895,7 +1926,7 @@ int DwarfCutscene::show() {
WAIT(1);
}
- sound.playSound(_mazeFlag ? "ok2.voc" : "back2.voc");
+ sound.playSound(_keyFound ? "ok2.voc" : "back2.voc");
} else {
sound.playSound("dwarf11.voc");
}
@@ -1909,7 +1940,7 @@ int DwarfCutscene::show() {
events.updateGameCounter();
do {
sprites2.draw(0, 0);
- sprites3.draw(0, g_vm->getRandomNumber(_isDarkCc ? 8 : 9));
+ sprites3.draw(0, g_vm->getRandomNumber(_ccNum ? 8 : 9));
_subtitles.show();
events.timeMark5();
@@ -1923,7 +1954,7 @@ int DwarfCutscene::show() {
exit:
sprites2.draw(0, 0);
- if (!_isDarkCc)
+ if (!_ccNum)
sprites3.draw(0, 1);
windows[0].update();
@@ -1944,14 +1975,37 @@ exit:
void DwarfCutscene::getNewLocation() {
Party &party = *g_vm->_party;
- if (_isDarkCc) {
+ if (g_vm->getGameID() == GType_Swords) {
+ switch (party._mazeId) {
+ case 1:
+ if (party._questItems[0]) {
+ _mazeId = 53;
+ _mazePos = Common::Point(8, 1);
+ _mazeDir = DIR_NORTH;
+ _keyFound = true;
+ }
+ break;
+
+ case 7:
+ if (party._questItems[1]) {
+ _mazeId = 92;
+ _mazePos = Common::Point(8, 1);
+ _mazeDir = DIR_NORTH;
+ _keyFound = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ } else if (_ccNum) {
switch (party._mazeId) {
case 4:
if (party._questItems[35]) {
_mazeId = 29;
_mazePos = Common::Point(15, 31);
_mazeDir = DIR_SOUTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1960,7 +2014,7 @@ void DwarfCutscene::getNewLocation() {
_mazeId = 35;
_mazePos = Common::Point(15, 8);
_mazeDir = DIR_WEST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1969,7 +2023,7 @@ void DwarfCutscene::getNewLocation() {
_mazeId = 31;
_mazePos = Common::Point(31, 16);
_mazeDir = DIR_WEST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1978,7 +2032,7 @@ void DwarfCutscene::getNewLocation() {
_mazeId = 33;
_mazePos = Common::Point(0, 3);
_mazeDir = DIR_EAST;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -1987,7 +2041,7 @@ void DwarfCutscene::getNewLocation() {
_mazeId = 37;
_mazePos = Common::Point(7, 0);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -2000,7 +2054,7 @@ void DwarfCutscene::getNewLocation() {
_mazeId = 37;
_mazePos = Common::Point(1, 4);
_mazeDir = DIR_EAST;
- _mazeFlag = true;
+ _keyFound = true;
break;
case 18:
@@ -2013,7 +2067,7 @@ void DwarfCutscene::getNewLocation() {
_mazePos = Common::Point(7, 1);
_mazeDir = DIR_NORTH;
}
- _mazeFlag = true;
+ _keyFound = true;
break;
case 23:
@@ -2026,7 +2080,7 @@ void DwarfCutscene::getNewLocation() {
_mazePos = Common::Point(7, 30);
_mazeDir = DIR_SOUTH;
}
- _mazeFlag = true;
+ _keyFound = true;
break;
default:
@@ -2057,7 +2111,7 @@ int SphinxCutscene::show() {
// Save background
Graphics::ManagedSurface bgSurface;
bgSurface.copyFrom(screen);
-
+
for (int idx = 8; idx >= 0; --idx) {
events.updateGameCounter();
screen.blitFrom(bgSurface);
@@ -2069,14 +2123,14 @@ int SphinxCutscene::show() {
sound.setMusicPercent(38);
- for (int idx = 0; idx < (_mazeFlag ? 3 : 2); ++idx) {
+ for (int idx = 0; idx < (_keyFound ? 3 : 2); ++idx) {
switch (idx) {
case 0:
- _subtitles.setLine(_mazeFlag ? 9 : 10);
- sound.playSound(_mazeFlag ? "sphinx10.voc" : "sphinx13.voc");
+ _subtitles.setLine(_keyFound ? 9 : 10);
+ sound.playSound(_keyFound ? "sphinx10.voc" : "sphinx13.voc");
break;
case 1:
- sound.playSound(_mazeFlag ? "sphinx11.voc" : "sphinx14.voc");
+ sound.playSound(_keyFound ? "sphinx11.voc" : "sphinx14.voc");
break;
case 2:
sound.playSound("sphinx12.voc");
@@ -2100,7 +2154,7 @@ int SphinxCutscene::show() {
sound.setMusicPercent(75);
- if (!_mazeFlag) {
+ if (!_keyFound) {
for (int idx = 0; idx < 8; ++idx) {
screen.blitFrom(bgSurface);
sprites1.draw(0, 0, Common::Point(SPHINX_X1[idx], SPHINX_Y1[idx]), 0, idx);
@@ -2135,11 +2189,11 @@ void SphinxCutscene::getNewLocation() {
switch (party._mazeId) {
case 2:
if (party._questItems[51]) {
- map._loadDarkSide = true;
+ map._loadCcNum = 1;
_mazeId = 125;
_mazePos = Common::Point(7, 6);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -2148,7 +2202,7 @@ void SphinxCutscene::getNewLocation() {
_mazeId = 82;
_mazePos = Common::Point(7, 5);
_mazeDir = DIR_NORTH;
- _mazeFlag = true;
+ _keyFound = true;
}
break;
@@ -2172,7 +2226,7 @@ int PyramidLocation::show() {
Common::Point pt;
if (g_vm->getGameID() == GType_WorldOfXeen) {
- if (_isDarkCc) {
+ if (_ccNum) {
if (party._mazeId == 52) {
mapId = 49;
pt = Common::Point(7, 14);
@@ -2192,7 +2246,7 @@ int PyramidLocation::show() {
}
// Load the destination map and set position and direction
- map._loadDarkSide = !_isDarkCc;
+ map._loadCcNum = _ccNum ? 0 : 1;
map.load(mapId);
party._mazePosition = pt;
party._mazeDirection = dir;
@@ -2200,7 +2254,7 @@ int PyramidLocation::show() {
// Playing Clouds or Dark Side on it's own, so can't switch sides
Window &win = windows[12];
Common::String msg = Common::String::format(Res.MOONS_NOT_ALIGNED,
- _isDarkCc ? "Clouds" : "Darkside");
+ _ccNum ? "Clouds" : "Darkside");
win.open();
win.writeString(msg);
win.update();
@@ -2219,9 +2273,12 @@ int PyramidLocation::show() {
LocationManager::LocationManager() : _location(nullptr) {
}
-int LocationManager::doAction(LocationAction actionId) {
+int LocationManager::doAction(int actionId) {
+ LocationAction action = (g_vm->getGameID() == GType_Swords && actionId > 13 && actionId < 18) ?
+ BLACKSMITH : (LocationAction)actionId;
+
// Create the desired location
- switch (actionId) {
+ switch (action) {
case BANK:
_location = new Locations::BankLocation();
break;
@@ -2264,6 +2321,7 @@ int LocationManager::doAction(LocationAction actionId) {
}
// Show the location
+ g_vm->_events->clearEvents();
int result = _location->show();
delete _location;
_location = nullptr;
@@ -2355,21 +2413,18 @@ bool LocationMessage::execute(int portrait, const Common::String &name, const Co
do {
events.clearEvents();
- events.updateGameCounter();
- if (msgEnd)
- clearButtons();
+ clearEvents();
do {
- events.pollEventsAndWait();
- checkEvents(_vm);
-
- if (_vm->shouldExit())
- return false;
-
- while (events.timeElapsed() >= 3) {
- drawAnim(false);
- events.updateGameCounter();
+ events.updateGameCounter();
+ while (!_buttonValue && events.timeElapsed() < 3) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ if (g_vm->shouldExit())
+ return false;
}
+
+ drawAnim(false);
} while (!_buttonValue);
if (msgEnd)
diff --git a/engines/xeen/locations.h b/engines/xeen/locations.h
index 9b3e36eed7..ad0a8e2cee 100644
--- a/engines/xeen/locations.h
+++ b/engines/xeen/locations.h
@@ -47,7 +47,7 @@ protected:
Common::Array<SpriteResource> _townSprites;
SpriteResource _icons1, _icons2;
int _townMaxId;
- const bool &_isDarkCc;
+ const int &_ccNum;
int _animFrame;
Common::String _vocName, _songName;
Common::Point _animPos;
@@ -198,7 +198,7 @@ private:
int _dayOfWeek;
int _v10, _v11, _v12;
int _v13, _v14;
- bool _flag1;
+ bool _blessed;
int _v5, _v6;
protected:
/**
@@ -253,7 +253,7 @@ protected:
int _mazeId;
Direction _mazeDir;
Common::Point _mazePos;
- bool _mazeFlag;
+ bool _keyFound;
protected:
/**
* Sets the new location
@@ -364,7 +364,7 @@ public:
/**
* Show a given location, and return any result
*/
- int doAction(LocationAction actionId);
+ int doAction(int actionId);
/**
* Returns true if a town location (bank, blacksmith, etc.) is currently active
diff --git a/engines/xeen/map.cpp b/engines/xeen/map.cpp
index d8afa4d2a3..9d384c7c8f 100644
--- a/engines/xeen/map.cpp
+++ b/engines/xeen/map.cpp
@@ -52,7 +52,7 @@ MonsterStruct::MonsterStruct() {
_specialAttack = SA_NONE;
_hitChance = 0;
_rangeAttack = 0;
- _monsterType = MONSTER_0;
+ _monsterType = MONSTER_MONSTERS;
_fireResistence = 0;
_electricityResistence = 0;
_coldResistence = 0;
@@ -463,8 +463,6 @@ void MonsterObjectData::synchronize(XeenSerializer &s, MonsterData &monsterData)
if (obj._id < (int)_objectSprites.size()) {
obj._spriteId = _objectSprites[obj._id]._spriteId;
obj._sprites = &_objectSprites[obj._id]._sprites;
- } else {
- assert(!obj._id);
}
_objects.push_back(obj);
@@ -525,7 +523,8 @@ void MonsterObjectData::clearMonsterSprites() {
void MonsterObjectData::addMonsterSprites(MazeMonster &monster) {
Map &map = *g_vm->_map;
- int imgNumber = map._monsterData[monster._spriteId]._imageNumber;
+ monster._monsterData = &map._monsterData[monster._spriteId];
+ int imgNumber = monster._monsterData->_imageNumber;
uint idx;
// Find the sprites for the monster, loading them in if necessary
@@ -604,12 +603,11 @@ void AnimationInfo::load(const Common::String &name) {
/*------------------------------------------------------------------------*/
Map::Map(XeenEngine *vm) : _vm(vm), _mobData(vm) {
- _loadDarkSide = false;
+ _loadCcNum = 0;
_sideTownPortal = 0;
_sideObjects = 0;
_sideMonsters = 0;
_sidePictures = 0;
- _sideMusic = 0;
_isOutdoors = false;
_mazeDataIndex = 0;
_currentSteppedOn = false;
@@ -629,6 +627,7 @@ void Map::load(int mapId) {
FileManager &files = *g_vm->_files;
Interface &intf = *g_vm->_interface;
Party &party = *g_vm->_party;
+ Patcher &patcher = *g_vm->_patcher;
Sound &sound = *g_vm->_sound;
IndoorDrawList &indoorList = intf._indoorList;
OutdoorDrawList &outdoorList = intf._outdoorList;
@@ -636,7 +635,7 @@ void Map::load(int mapId) {
PleaseWait waitMsg(intf._falling);
waitMsg.show();
- intf._objNumber = 0;
+ intf._objNumber = -1;
party._stepped = true;
party._mazeId = mapId;
saveMaze();
@@ -648,12 +647,12 @@ void Map::load(int mapId) {
if (mapId >= 113 && mapId <= 127) {
_sideTownPortal = 0;
} else {
- _sideTownPortal = _loadDarkSide ? 1 : 0;
+ _sideTownPortal = _loadCcNum;
}
if (_vm->getGameID() == GType_Swords || _vm->getGameID() == GType_DarkSide) {
_animationInfo.load("dark.dat");
- _monsterData.load("dark.mon");
+ _monsterData.load((_vm->getGameID() == GType_Swords) ? "monsters.swd" : "dark.mon");
_wallPicSprites.load("darkpic.dat");
} else if (_vm->getGameID() == GType_Clouds) {
_animationInfo.load("animinfo.cld");
@@ -662,7 +661,7 @@ void Map::load(int mapId) {
} else if (_vm->getGameID() == GType_WorldOfXeen) {
files.setGameCc(1);
- if (!_loadDarkSide) {
+ if (!_loadCcNum) {
_animationInfo.load("clouds.dat");
_monsterData.load("xeen.mon");
_wallPicSprites.load("xeenpic.dat");
@@ -709,15 +708,15 @@ void Map::load(int mapId) {
}
}
- files.setGameCc(_loadDarkSide);
+ files.setGameCc(_loadCcNum);
}
// Load any events for the new map
- loadEvents(mapId);
+ loadEvents(mapId, _loadCcNum);
// Iterate through loading the given maze as well as the two successive
// mazes in each of the four cardinal directions
- bool isDarkCc = files._isDarkCc;
+ int ccNum = files._ccNum;
MazeData *mazeDataP = &_mazeData[0];
bool textLoaded = false;
@@ -735,9 +734,9 @@ void Map::load(int mapId) {
mazeDataP->synchronize(datSer);
datFile.close();
- if (isDarkCc && mapId == 50)
+ if (ccNum && mapId == 50)
mazeDataP->setAllTilesStepped();
- if (!isDarkCc && party._gameFlags[0][25] &&
+ if (!ccNum && party._gameFlags[0][25] &&
(mapId == 42 || mapId == 43 || mapId == 4)) {
mazeDataP->clearCellSurfaces();
}
@@ -747,20 +746,7 @@ void Map::load(int mapId) {
// Handle loading text data
if (!textLoaded) {
textLoaded = true;
-
- if (g_vm->getGameID() == GType_Clouds) {
- _mazeName = Res._cloudsMapNames[mapId];
- } else {
- Common::String txtName = Common::String::format("%s%c%03d.txt",
- isDarkCc ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId);
- File fText(txtName, 1);
- char mazeName[33];
- fText.read(mazeName, 33);
- mazeName[32] = '\0';
-
- _mazeName = Common::String(mazeName);
- fText.close();
- }
+ _mazeName = getMazeName(mapId, ccNum);
// Load the monster/object data
Common::String mobName = Common::String::format("maze%c%03d.mob",
@@ -776,7 +762,7 @@ void Map::load(int mapId) {
_headData.synchronize(headFile);
headFile.close();
- if (!isDarkCc && mapId == 15) {
+ if (!ccNum && mapId == 15) {
if ((_mobData._monsters[0]._position.x > 31 || _mobData._monsters[0]._position.y > 31) &&
(_mobData._monsters[1]._position.x > 31 || _mobData._monsters[1]._position.y > 31) &&
(_mobData._monsters[2]._position.x > 31 || _mobData._monsters[2]._position.y > 31)) {
@@ -808,13 +794,13 @@ void Map::load(int mapId) {
for (uint i = 0; i < _mobData._objectSprites.size(); ++i) {
files.setGameCc(_sideObjects);
- if (party._cloudsEnd && _mobData._objectSprites[i]._spriteId == 85 &&
- mapId == 27 && isDarkCc) {
+ if (party._cloudsCompleted && _mobData._objectSprites[i]._spriteId == 85 &&
+ mapId == 27 && ccNum) {
_mobData._objects[29]._spriteId = 0;
_mobData._objects[29]._id = 8;
_mobData._objectSprites[i]._sprites.clear();
} else if (mapId == 12 && party._gameFlags[0][43] &&
- _mobData._objectSprites[i]._spriteId == 118 && !isDarkCc) {
+ _mobData._objectSprites[i]._spriteId == 118 && !ccNum) {
filename = "085.obj";
_mobData._objectSprites[0]._spriteId = 85;
} else {
@@ -847,15 +833,15 @@ void Map::load(int mapId) {
_mobData._wallItemSprites[i]._sprites.load(filename, _sidePictures);
}
- files.setGameCc(isDarkCc);
+ files.setGameCc(ccNum);
// Handle loading miscellaneous sprites for the map
if (_isOutdoors) {
// Start playing relevant music
- sound._musicSide = isDarkCc;
+ sound._musicSide = ccNum;
Common::String musName;
- if (_vm->_files->_isDarkCc) {
+ if (_vm->_files->_ccNum) {
int randIndex = _vm->getRandomNumber(6);
musName = Res.MUSIC_FILES2[_mazeData->_wallKind][randIndex];
} else {
@@ -884,16 +870,15 @@ void Map::load(int mapId) {
_surfaceSprites[i].load(Res.SURFACE_NAMES[_mazeData[0]._surfaceTypes[i]]);
}
} else {
- if (files._isDarkCc && (mapId == 125 || mapId == 126 || mapId == 127))
+ if (files._ccNum && (mapId == 125 || mapId == 126 || mapId == 127))
files.setGameCc(0);
- sound._musicSide = files._isDarkCc;
+ sound._musicSide = files._ccNum;
// Start playing relevant music
const int MUS_INDEXES[] = { 1, 2, 3, 4, 3, 5 };
Common::String musName;
- _sideMusic = isDarkCc;
- if (isDarkCc) {
+ if (files._ccNum) {
int randIndex = _vm->getRandomNumber(6);
musName = Res.MUSIC_FILES2[MUS_INDEXES[_mazeData->_wallKind]][randIndex];
} else {
@@ -987,7 +972,7 @@ void Map::load(int mapId) {
indoorList._ground._sprites = &_groundSprites;
// Don't show horizon for certain maps
- if (_vm->_files->_isDarkCc) {
+ if (_vm->_files->_ccNum) {
if ((mapId >= 89 && mapId <= 112) || mapId == 128 || mapId == 129)
indoorList._horizon._sprites = nullptr;
} else {
@@ -996,9 +981,10 @@ void Map::load(int mapId) {
}
}
+ patcher.patch();
loadSky();
- files.setGameCc(isDarkCc);
+ files.setGameCc(ccNum);
}
void Map::findMap(int mapId) {
@@ -1066,7 +1052,8 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) {
_currentSurfaceId = _mazeData[_mazeDataIndex]._cells[pos.y][pos.x]._surfaceId;
}
- if (_currentSurfaceId == SURFTYPE_SPACE || _currentSurfaceId == SURFTYPE_SKY) {
+ if (mazeData()._surfaceTypes[_currentSurfaceId] == SURFTYPE_SPACE ||
+ mazeData()._surfaceTypes[_currentSurfaceId] == SURFTYPE_SKY) {
_currentSteppedOn = true;
} else {
_currentSteppedOn = _mazeData[_mazeDataIndex]._steppedOnTiles[pos.y][pos.x];
@@ -1080,11 +1067,11 @@ int Map::mazeLookup(const Common::Point &pt, int layerShift, int wallMask) {
}
}
-void Map::loadEvents(int mapId) {
+void Map::loadEvents(int mapId, int ccNum) {
// Load events
Common::String filename = Common::String::format("maze%c%03d.evt",
(mapId >= 100) ? 'x' : '0', mapId);
- File fEvents(filename);
+ File fEvents(filename, ccNum);
XeenSerializer sEvents(&fEvents, nullptr);
_events.synchronize(sEvents);
fEvents.close();
@@ -1092,7 +1079,7 @@ void Map::loadEvents(int mapId) {
// Load text data
filename = Common::String::format("aaze%c%03d.txt",
(mapId >= 100) ? 'x' : '0', mapId);
- File fText(filename);
+ File fText(filename, ccNum);
_events._text.clear();
while (fText.pos() < fText.size())
_events._text.push_back(fText.readString());
@@ -1114,7 +1101,7 @@ void Map::saveMap() {
FileManager &files = *g_vm->_files;
Party &party = *g_vm->_party;
int mapId = _mazeData[0]._mazeId;
- if (!files._isDarkCc && mapId == 85)
+ if (!files._ccNum && mapId == 85)
return;
// Save the primary maze
@@ -1124,7 +1111,7 @@ void Map::saveMap() {
_mazeData[0].synchronize(datSer);
datFile.finalize();
- if (!files._isDarkCc && mapId == 15) {
+ if (!files._ccNum && mapId == 15) {
for (uint idx = 0; idx < MIN(_mobData._monsters.size(), (uint)3); ++idx) {
MazeMonster &mon = _mobData._monsters[idx];
if (mon._position.x > 31 || mon._position.y > 31) {
@@ -1162,7 +1149,7 @@ void Map::saveMonsters() {
void Map::saveMaze() {
int mazeNum = _mazeData[0]._mazeNumber;
- if (!mazeNum || (mazeNum == 85 && !_vm->_files->_isDarkCc))
+ if (!mazeNum || (mazeNum == 85 && !_vm->_files->_ccNum))
return;
saveEvents();
@@ -1236,7 +1223,8 @@ void Map::setWall(const Common::Point &pt, Direction dir, int v) {
}
int Map::getCell(int idx) {
- int mapId = _vm->_party->_mazeId;
+ Party &party = *g_vm->_party;
+ int mapId = party._mazeId;
Direction dir = _vm->_party->_mazeDirection;
Common::Point pt(
_vm->_party->_mazePosition.x + Res.SCREEN_POSITIONING_X[_vm->_party->_mazeDirection][idx],
@@ -1244,7 +1232,7 @@ int Map::getCell(int idx) {
);
if (pt.x > 31 || pt.y > 31) {
- if (_vm->_files->_isDarkCc) {
+ if (_vm->_files->_ccNum) {
if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) ||
mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) {
_currentSurfaceId = SURFTYPE_DESERT;
@@ -1270,12 +1258,14 @@ int Map::getCell(int idx) {
}
if (!mapId) {
+ mapId = party._mazeId;
+
if (_isOutdoors) {
_currentSurfaceId = SURFTYPE_SPACE;
_currentWall = 0;
return 0;
} else {
- if (_vm->_files->_isDarkCc) {
+ if (_vm->_files->_ccNum) {
if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) ||
mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) {
_currentSurfaceId = 6;
@@ -1304,12 +1294,14 @@ int Map::getCell(int idx) {
}
if (!mapId) {
+ mapId = party._mazeId;
+
if (_isOutdoors) {
_currentSurfaceId = SURFTYPE_SPACE;
_currentWall = 0;
return 0;
} else {
- if (_vm->_files->_isDarkCc) {
+ if (_vm->_files->_ccNum) {
if ((mapId >= 53 && mapId <= 88 && mapId != 73) || (mapId >= 74 && mapId <= 120) ||
mapId == 125 || mapId == 126 || mapId == 128 || mapId == 129) {
_currentSurfaceId = 6;
@@ -1404,4 +1396,24 @@ void Map::getNewMaze() {
load(mapId);
}
+Common::String Map::getMazeName(int mapId, int ccNum) {
+ if (ccNum == -1)
+ ccNum = g_vm->_files->_ccNum;
+
+ if (g_vm->getGameID() == GType_Clouds) {
+ return Res._cloudsMapNames[mapId];
+ } else {
+ Common::String txtName = Common::String::format("%s%c%03d.txt",
+ ccNum ? "dark" : "xeen", mapId >= 100 ? 'x' : '0', mapId);
+ File fText(txtName, 1);
+ char mazeName[33];
+ fText.read(mazeName, 33);
+ mazeName[32] = '\0';
+
+ Common::String name = Common::String(mazeName);
+ fText.close();
+ return name;
+ }
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/map.h b/engines/xeen/map.h
index a0bc77a7ec..1c00e549c3 100644
--- a/engines/xeen/map.h
+++ b/engines/xeen/map.h
@@ -42,11 +42,15 @@ namespace Xeen {
class XeenEngine;
enum MonsterType {
- MONSTER_0 = 0, MONSTER_ANIMAL = 1, MONSTER_INSECT = 2,
+ MONSTER_MONSTERS = 0, MONSTER_ANIMAL = 1, MONSTER_INSECT = 2,
MONSTER_HUMANOID = 3, MONSTER_UNDEAD = 4, MONSTER_GOLEM = 5,
MONSTER_DRAGON = 6
};
+enum MapId {
+ XEEN_CASTLE1 = 75, XEEN_CASTLE4 = 78
+};
+
class MonsterStruct {
public:
Common::String _name;
@@ -165,16 +169,16 @@ enum SurfaceType {
union MazeWallLayers {
struct MazeWallIndoors {
- int _wallNorth : 4;
- int _wallEast : 4;
- int _wallSouth : 4;
- int _wallWest : 4;
+ uint _wallNorth : 4;
+ uint _wallEast : 4;
+ uint _wallSouth : 4;
+ uint _wallWest : 4;
} _indoors;
struct MazeWallOutdoors {
- SurfaceType _surfaceId : 4;
- int _iMiddle : 4;
- int _iTop : 4;
- int _iOverlay : 4;
+ uint _surfaceId : 4; // SurfaceType, but needs to be unsigned
+ uint _iMiddle : 4;
+ uint _iTop : 4;
+ uint _iOverlay : 4;
} _outdoors;
uint16 _data;
};
@@ -318,7 +322,6 @@ public:
};
private:
XeenEngine *_vm;
- Common::Array<SpriteResourceEntry> _objectSprites;
Common::Array<SpriteResourceEntry> _monsterSprites;
Common::Array<SpriteResourceEntry> _monsterAttackSprites;
Common::Array<SpriteResourceEntry> _wallItemSprites;
@@ -326,6 +329,7 @@ public:
Common::Array<MazeObject> _objects;
Common::Array<MazeMonster> _monsters;
Common::Array<MazeWallItem> _wallItems;
+ Common::Array<SpriteResourceEntry> _objectSprites;
public:
MonsterObjectData(XeenEngine *vm);
@@ -403,13 +407,12 @@ private:
int _sidePictures;
int _sideObjects;
int _sideMonsters;
- int _sideMusic;
int _mazeDataIndex;
/**
* Load the events for a new map
*/
- void loadEvents(int mapId);
+ void loadEvents(int mapId, int ccNum);
/**
* Save the events for a map
@@ -454,7 +457,7 @@ public:
int _currentTile;
int _currentSurfaceId;
bool _currentSteppedOn;
- bool _loadDarkSide;
+ int _loadCcNum;
int _sideTownPortal;
public:
Map(XeenEngine *vm);
@@ -516,6 +519,13 @@ public:
* position to the relative position on the new map
*/
void getNewMaze();
+
+ /**
+ * Return the name of a specified maze
+ * @param mapId Map Id
+ * @param ccNum Cc file number. If -1, uses the current C
+ */
+ static Common::String getMazeName(int mapId, int ccNum = -1);
};
} // End of namespace Xeen
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 0154b8533b..5b3f69710f 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -6,7 +6,6 @@ MODULE_OBJS := \
worldofxeen/worldofxeen_cutscenes.o \
worldofxeen/worldofxeen_menu.o \
worldofxeen/worldofxeen.o \
- worldofxeen/worldofxeen_resources.o \
swordsofxeen/swordsofxeen.o \
swordsofxeen/swordsofxeen_menu.o \
dialogs/credits_screen.o \
@@ -14,6 +13,7 @@ MODULE_OBJS := \
dialogs/dialogs_awards.o \
dialogs/dialogs_char_info.o \
dialogs/dialogs_control_panel.o \
+ dialogs/dialogs_copy_protection.o \
dialogs/dialogs_create_char.o \
dialogs/dialogs_difficulty.o \
dialogs/dialogs_dismiss.o \
@@ -46,6 +46,7 @@ MODULE_OBJS := \
locations.o \
map.o \
party.o \
+ patcher.o \
resources.o \
saves.o \
screen.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 3f0cdf0433..1fee0980d2 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -54,6 +54,14 @@ Roster::Roster() {
}
void Roster::synchronize(Common::Serializer &s) {
+ Party &party = *g_vm->_party;
+
+ if (s.isSaving()) {
+ // Copy out the party's characters back to the roster
+ for (uint idx = 0; idx < party._activeParty.size(); ++idx)
+ (*this)[party._activeParty[idx]._rosterId] = party._activeParty[idx];
+ }
+
for (uint i = 0; i < TOTAL_CHARACTERS; ++i)
(*this)[i].synchronize(s);
}
@@ -70,6 +78,21 @@ Treasure::Treasure() {
_categories[3] = &_misc[0];
}
+void Treasure::clear() {
+ for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
+ _weapons[idx].clear();
+ _armor[idx].clear();
+ _accessories[idx].clear();
+ _misc[idx].clear();
+ }
+}
+
+void Treasure::reset() {
+ clear();
+ _hasItems = false;
+ _gold = _gems = 0;
+}
+
/*------------------------------------------------------------------------*/
const int BLACKSMITH_DATA1[4][4] = {
@@ -104,9 +127,7 @@ void BlacksmithWares::regenerate() {
ItemCategory itemCat = tempChar.makeItem(idx2 + 1, 0, 0);
if (catCount[itemCat] < 8) {
XeenItem &item = (*this)[itemCat][0][slotNum][catCount[itemCat]];
- item._id = tempChar._weapons[0]._id;
- item._material = tempChar._weapons[0]._material;
- item._bonusFlags = tempChar._weapons[0]._bonusFlags;
+ item = tempChar._items[itemCat][0];
++catCount[itemCat];
}
@@ -123,9 +144,7 @@ void BlacksmithWares::regenerate() {
ItemCategory itemCat = tempChar.makeItem(idx2 + (slotNum >= 2 ? 3 : 1), 0, 0);
if (catCount[itemCat] < 8) {
XeenItem &item = (*this)[itemCat][1][slotNum][catCount[itemCat]];
- item._id = tempChar._misc[0]._id;
- item._material = tempChar._misc[0]._material;
- item._bonusFlags = tempChar._misc[0]._bonusFlags;
+ item = tempChar._items[itemCat][0];
++catCount[itemCat];
}
@@ -135,21 +154,21 @@ void BlacksmithWares::regenerate() {
}
void BlacksmithWares::blackData2CharData(Character &c) {
- bool isDarkCc = g_vm->_files->_isDarkCc;
+ int ccNum = g_vm->_files->_ccNum;
int slotIndex = getSlotIndex();
for (ItemCategory cat = CATEGORY_WEAPON; cat <= CATEGORY_MISC; cat = (ItemCategory)((int)cat + 1))
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx)
- c._items[cat][idx] = (*this)[cat][isDarkCc][slotIndex][idx];
+ c._items[cat][idx] = (*this)[cat][ccNum][slotIndex][idx];
}
void BlacksmithWares::charData2BlackData(Character &c) {
- bool isDarkCc = g_vm->_files->_isDarkCc;
+ int ccNum = g_vm->_files->_ccNum;
int slotIndex = getSlotIndex();
for (ItemCategory cat = CATEGORY_WEAPON; cat <= CATEGORY_MISC; cat = (ItemCategory)((int)cat + 1))
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx)
- (*this)[cat][isDarkCc][slotIndex][idx] = c._items[cat][idx];
+ (*this)[cat][ccNum][slotIndex][idx] = c._items[cat][idx];
}
BlacksmithItems &BlacksmithWares::operator[](ItemCategory category) {
@@ -163,10 +182,10 @@ BlacksmithItems &BlacksmithWares::operator[](ItemCategory category) {
uint BlacksmithWares::getSlotIndex() const {
Party &party = *g_vm->_party;
- bool isDarkCc = g_vm->_files->_isDarkCc;
+ int ccNum = g_vm->_files->_ccNum;
int slotIndex = 0;
- while (slotIndex < 4 && party._mazeId != (int)Res.BLACKSMITH_MAP_IDS[isDarkCc][slotIndex])
+ while (slotIndex < 4 && party._mazeId != (int)Res.BLACKSMITH_MAP_IDS[ccNum][slotIndex])
++slotIndex;
if (slotIndex == 4)
slotIndex = 0;
@@ -199,9 +218,9 @@ Party::Party(XeenEngine *vm) {
_holyBonus = 0;
_heroism = 0;
_difficulty = ADVENTURER;
- _cloudsEnd = false;
- _darkSideEnd = false;
- _worldEnd = false;
+ _cloudsCompleted = false;
+ _darkSideCompleted = false;
+ _worldCompleted = false;
_ctr24 = 0;
_day = 0;
_year = 0;
@@ -226,14 +245,12 @@ Party::Party(XeenEngine *vm) {
Common::fill(&_gameFlags[0][0], &_gameFlags[0][256], false);
Common::fill(&_gameFlags[1][0], &_gameFlags[1][256], false);
Common::fill(&_worldFlags[0], &_worldFlags[128], false);
- Common::fill(&_questFlags[0][0], &_questFlags[0][30], false);
- Common::fill(&_questFlags[1][0], &_questFlags[1][30], false);
+ Common::fill(&_questFlags[0], &_questFlags[60], false);
Common::fill(&_questItems[0], &_questItems[85], 0);
for (int i = 0; i < TOTAL_CHARACTERS; ++i)
Common::fill(&_characterFlags[i][0], &_characterFlags[i][24], false);
- _partyDead = false;
_newDay = false;
_isNight = false;
_stepped = false;
@@ -287,9 +304,9 @@ void Party::synchronize(Common::Serializer &s) {
_blacksmithWares.synchronize(s, 0);
- s.syncAsUint16LE(_cloudsEnd);
- s.syncAsUint16LE(_darkSideEnd);
- s.syncAsUint16LE(_worldEnd);
+ s.syncAsUint16LE(_cloudsCompleted);
+ s.syncAsUint16LE(_darkSideCompleted);
+ s.syncAsUint16LE(_worldCompleted);
s.syncAsUint16LE(_ctr24);
s.syncAsUint16LE(_day);
s.syncAsUint16LE(_year);
@@ -313,8 +330,7 @@ void Party::synchronize(Common::Serializer &s) {
File::syncBitFlags(s, &_gameFlags[0][0], &_gameFlags[0][256]);
File::syncBitFlags(s, &_gameFlags[1][0], &_gameFlags[1][256]);
File::syncBitFlags(s, &_worldFlags[0], &_worldFlags[128]);
- File::syncBitFlags(s, &_questFlags[0][0], &_questFlags[0][30]);
- File::syncBitFlags(s, &_questFlags[1][0], &_questFlags[1][30]);
+ File::syncBitFlags(s, &_questFlags[0], &_questFlags[60]);
for (int i = 0; i < 85; ++i)
s.syncAsByte(_questItems[i]);
@@ -324,6 +340,10 @@ void Party::synchronize(Common::Serializer &s) {
for (int i = 0; i < TOTAL_CHARACTERS; ++i)
File::syncBitFlags(s, &_characterFlags[i][0], &_characterFlags[i][24]);
s.syncBytes(&dummy[0], 30);
+
+ if (s.isLoading())
+ _newDay = _minutes < 300;
+ _dead = false;
}
void Party::loadActiveParty() {
@@ -444,8 +464,12 @@ void Party::changeTime(int numMinutes) {
}
}
- player._conditions[WEAK] = player._conditions[DRUNK];
- player._conditions[DRUNK] = 0;
+ // WORKAROUND: Original incorrectly reset weakness (due to lack of sleep) even when party
+ // wasn't drunk. We now have any resetting drunkness add to, rather than replace, weakness
+ if (player._conditions[WEAK] != -1) {
+ player._conditions[WEAK] += player._conditions[DRUNK];
+ player._conditions[DRUNK] = 0;
+ }
if (player._conditions[DEPRESSED]) {
player._conditions[DEPRESSED] = (player._conditions[DEPRESSED] + 1) % 4;
@@ -502,7 +526,7 @@ void Party::addTime(int numMinutes) {
_newDay = true;
if (_newDay && _minutes >= 300) {
- if (_vm->_mode != MODE_RECORD_EVENTS && _vm->_mode != MODE_17) {
+ if (_vm->_mode != MODE_SCRIPT_IN_PROGRESS && _vm->_mode != MODE_INTERACTIVE7) {
resetTemps();
if (_rested || _vm->_mode == MODE_SLEEPING) {
_rested = false;
@@ -673,11 +697,8 @@ void Party::giveTreasure() {
if (!_treasure._hasItems && !_treasure._gold && !_treasure._gems)
return;
- bool monstersPresent = false;
- for (int idx = 0; idx < 26 && !monstersPresent; ++idx)
- monstersPresent = combat._attackMonsters[idx] != -1;
-
- if (_vm->_mode != MODE_RECORD_EVENTS && monstersPresent)
+ bool monstersPresent = combat.areMonstersPresent();
+ if (_vm->_mode != MODE_SCRIPT_IN_PROGRESS && monstersPresent)
return;
combat.clearShooting();
@@ -702,18 +723,13 @@ void Party::giveTreasure() {
for (int categoryNum = 0; categoryNum < NUM_ITEM_CATEGORIES; ++categoryNum) {
for (int itemNum = 0; itemNum < MAX_TREASURE_ITEMS; ++itemNum) {
if (arePacksFull()) {
- if (_treasure._weapons[itemNum]._id == 34) {
- // Important item, so clear a slot for it
+ if (_treasure._weapons[itemNum]._id >= XEEN_SLAYER_SWORD) {
+ // Xeen Slayer Sword, so clear a slot for it
_activeParty[0]._weapons[INV_ITEMS_TOTAL - 1].clear();
} else {
// Otherwise, clear all the remaining treasure items,
// since all the party's packs are full
- for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- _treasure._weapons[idx].clear();
- _treasure._armor[idx].clear();
- _treasure._accessories[idx].clear();
- _treasure._armor[idx].clear();
- }
+ _treasure.clear();
}
}
@@ -767,7 +783,7 @@ void Party::giveTreasure() {
events.clearEvents();
if (_vm->_mode != MODE_COMBAT)
- _vm->_mode = MODE_1;
+ _vm->_mode = MODE_INTERACTIVE;
w.close();
_gold += _treasure._gold;
@@ -776,13 +792,7 @@ void Party::giveTreasure() {
_treasure._gems = 0;
_treasure._hasItems = false;
- for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- _treasure._weapons[idx].clear();
- _treasure._armor[idx].clear();
- _treasure._accessories[idx].clear();
- _treasure._armor[idx].clear();
- }
-
+ _treasure.clear();
combat._combatTarget = 1;
}
@@ -790,10 +800,10 @@ bool Party::arePacksFull() const {
uint total = 0;
for (uint idx = 0; idx < _activeParty.size(); ++idx) {
const Character &c = _activeParty[idx];
- total += (c._weapons[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0)
- + (c._armor[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0)
- + (c._accessories[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0)
- + (c._misc[INV_ITEMS_TOTAL - 1]._id != 0 ? 1 : 0);
+ total += (c._weapons[INV_ITEMS_TOTAL - 1].empty() ? 0 : 1)
+ + (c._armor[INV_ITEMS_TOTAL - 1].empty() ? 0 : 1)
+ + (c._accessories[INV_ITEMS_TOTAL - 1].empty() ? 0 : 1)
+ + (c._misc[INV_ITEMS_TOTAL - 1].empty() ? 0 : 1);
}
return total == (_activeParty.size() * NUM_ITEM_CATEGORIES);
@@ -816,11 +826,20 @@ void Party::giveTreasureToCharacter(Character &c, ItemCategory category, int ite
w.update();
events.ipause(5);
- const char *itemName = XeenItem::getItemName(category, treasureItem._id);
- w.writeString(Common::String::format(Res.X_FOUND_Y, c._name.c_str(), itemName));
+ int index = (category == CATEGORY_MISC) ? treasureItem._material : treasureItem._id;
+ const char *itemName = XeenItem::getItemName(category, index);
+
+ if (index >= (_vm->getGameID() == GType_Swords ? 88 : 82)) {
+ // Quest item, give an extra '*' prefix
+ Common::String format = Common::String::format("\f04 * \fd%s", itemName);
+ w.writeString(Common::String::format(Res.X_FOUND_Y, c._name.c_str(), format.c_str()));
+ } else {
+ w.writeString(Common::String::format(Res.X_FOUND_Y, c._name.c_str(), itemName));
+ }
+
w.update();
c._items[category].sort();
- events.ipause(5);
+ events.ipause(8);
}
bool Party::canShoot() const {
@@ -880,7 +899,7 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
ps._tempAge -= takeVal;
break;
case 13:
- ps._skills[THIEVERY] = 0;
+ ps._skills[takeVal] = 0;
break;
case 15:
ps.setAward(takeVal, false);
@@ -895,26 +914,11 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
ps._conditions[takeVal] = 0;
break;
case 19: {
- int idx2 = 0;
- switch (ps._class) {
- case CLASS_PALADIN:
- case CLASS_CLERIC:
- idx2 = 0;
- break;
- case CLASS_ARCHER:
- case CLASS_SORCERER:
- idx2 = 1;
- break;
- case CLASS_DRUID:
- case CLASS_RANGER:
- idx2 = 2;
- break;
- default:
- break;
- }
+ SpellsCategory category = ps.getSpellsCategory();
+ assert(category != SPELLCAT_INVALID);
- for (int idx = 0; idx < 39; ++idx) {
- if (Res.SPELLS_ALLOWED[idx2][idx] == (int)takeVal) {
+ for (int idx = 0; idx < SPELLS_PER_CLASS; ++idx) {
+ if (Res.SPELLS_ALLOWED[category][idx] == (int)takeVal) {
ps._spells[idx] = false;
break;
}
@@ -922,45 +926,53 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
break;
}
case 20:
- _gameFlags[files._isDarkCc][takeVal] = false;
+ assert(takeVal < 256);
+ _gameFlags[_vm->getGameID() == GType_Swords ? 0 : files._ccNum][takeVal] = false;
break;
case 21: {
- bool found = false;
- for (int idx = 0; idx < 9; ++idx) {
- if (takeVal < 35) {
- if (ps._weapons[idx]._id == takeVal) {
- ps._weapons[idx].clear();
- ps._weapons.sort();
- found = true;
- break;
- }
- } else if (takeVal < 49) {
- if (ps._armor[idx]._id == (takeVal - 35)) {
- ps._armor[idx].clear();
- ps._armor.sort();
- found = true;
- break;
- }
- } else if (takeVal < 60) {
- if (ps._accessories[idx]._id == (takeVal - 49)) {
- ps._accessories[idx].clear();
- ps._accessories.sort();
- found = true;
- break;
- }
- } else if (takeVal < 82) {
- if (ps._misc[idx]._material == ((int)takeVal - 60)) {
- ps._misc[idx].clear();
- ps._misc.sort();
- found = true;
- break;
+ const uint WEAPONS_END = _vm->getGameID() != GType_Swords ? 35 : 41;
+ const uint ARMOR_END = _vm->getGameID() != GType_Swords ? 49 : 55;
+ const uint ACCESSORIES_END = _vm->getGameID() != GType_Swords ? 60 : 66;
+ const uint MISC_END = _vm->getGameID() != GType_Swords ? 82 : 88;
+
+ if (takeVal >= MISC_END) {
+ _questItems[takeVal - MISC_END]--;
+ } else {
+ bool found = false;
+ for (int idx = 0; idx < 9; ++idx) {
+ if (takeVal < WEAPONS_END) {
+ if (ps._weapons[idx]._id == takeVal) {
+ ps._weapons[idx].clear();
+ ps._weapons.sort();
+ found = true;
+ break;
+ }
+ } else if (takeVal < ARMOR_END) {
+ if (ps._armor[idx]._id == (takeVal - WEAPONS_END)) {
+ ps._armor[idx].clear();
+ ps._armor.sort();
+ found = true;
+ break;
+ }
+ } else if (takeVal < ACCESSORIES_END) {
+ if (ps._accessories[idx]._id == (takeVal - ARMOR_END)) {
+ ps._accessories[idx].clear();
+ ps._accessories.sort();
+ found = true;
+ break;
+ }
+ } else {
+ if (ps._misc[idx]._material == (int)(takeVal - ACCESSORIES_END)) {
+ ps._misc[idx].clear();
+ ps._misc.sort();
+ found = true;
+ break;
+ }
}
- } else {
- _questItems[takeVal - 82]--;
}
+ if (!found)
+ return true;
}
- if (!found)
- return true;
break;
}
case 25:
@@ -1099,7 +1111,7 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
_worldFlags[takeVal] = false;
break;
case 104:
- _questFlags[files._isDarkCc][takeVal] = false;
+ _questFlags[(_vm->getGameID() == GType_Swords ? 0 : files._ccNum * 30) + takeVal] = false;
break;
case 107:
_characterFlags[ps._rosterId][takeVal] = false;
@@ -1137,6 +1149,7 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
case 13:
assert(giveVal < 18);
ps._skills[giveVal]++;
+ intf.spellFX(&ps);
break;
case 15:
ps.setAward(giveVal, true);
@@ -1164,66 +1177,59 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
ps._currentHp = 0;
break;
case 19: {
- int idx2 = 0;
- switch (ps._class) {
- case CLASS_PALADIN:
- case CLASS_CLERIC:
- idx2 = 0;
- break;
- case CLASS_ARCHER:
- case CLASS_SORCERER:
- idx2 = 1;
- break;
- case CLASS_DRUID:
- case CLASS_RANGER:
- idx2 = 2;
- break;
- default:
- break;
- }
-
- for (int idx = 0; idx < 39; ++idx) {
- if (Res.SPELLS_ALLOWED[idx2][idx] == (int)giveVal) {
- ps._spells[idx] = true;
- intf.spellFX(&ps);
- break;
+ // Give spell to character
+ SpellsCategory category = ps.getSpellsCategory();
+
+ if (category != SPELLCAT_INVALID) {
+ for (int idx = 0; idx < SPELLS_PER_CLASS; ++idx) {
+ if (Res.SPELLS_ALLOWED[category][idx] == (int)giveVal) {
+ ps._spells[idx] = true;
+ intf.spellFX(&ps);
+ break;
+ }
}
}
break;
}
case 20:
- _gameFlags[files._isDarkCc][giveVal] = true;
+ assert(giveVal < 256);
+ _gameFlags[_vm->getGameID() == GType_Swords ? 0 : files._ccNum][giveVal] = true;
break;
case 21: {
+ const uint WEAPONS_END = _vm->getGameID() != GType_Swords ? 35 : 41;
+ const uint ARMOR_END = _vm->getGameID() != GType_Swords ? 49 : 55;
+ const uint ACCESSORIES_END = _vm->getGameID() != GType_Swords ? 60 : 66;
+ const uint MISC_END = _vm->getGameID() != GType_Swords ? 82 : 88;
+
int idx;
- if (giveVal >= 82) {
- _questItems[giveVal - 82]++;
+ if (giveVal >= MISC_END) {
+ _questItems[giveVal - MISC_END]++;
}
- if (giveVal < 35 || giveVal >= 82) {
- for (idx = 0; idx < 10 && _treasure._weapons[idx]._id; ++idx);
- if (idx < 10) {
+ if (giveVal < WEAPONS_END || giveVal >= MISC_END) {
+ for (idx = 0; idx < MAX_TREASURE_ITEMS && !_treasure._weapons[idx].empty(); ++idx) {}
+ if (idx < MAX_TREASURE_ITEMS) {
_treasure._weapons[idx]._id = giveVal;
_treasure._hasItems = true;
return false;
}
- } else if (giveVal < 49) {
- for (idx = 0; idx < 10 && _treasure._armor[idx]._id; ++idx);
- if (idx < 10) {
- _treasure._armor[idx]._id = giveVal - 35;
+ } else if (giveVal < ARMOR_END) {
+ for (idx = 0; idx < MAX_TREASURE_ITEMS && !_treasure._armor[idx].empty(); ++idx) {}
+ if (idx < MAX_TREASURE_ITEMS) {
+ _treasure._armor[idx]._id = giveVal - WEAPONS_END;
_treasure._hasItems = true;
return false;
}
- } else if (giveVal < 60) {
- for (idx = 0; idx < 10 && _treasure._accessories[idx]._id; ++idx);
- if (idx < 10) {
- _treasure._accessories[idx]._id = giveVal - 49;
+ } else if (giveVal < ACCESSORIES_END) {
+ for (idx = 0; idx < MAX_TREASURE_ITEMS && !_treasure._accessories[idx].empty(); ++idx) {}
+ if (idx < MAX_TREASURE_ITEMS) {
+ _treasure._accessories[idx]._id = giveVal - ARMOR_END;
_treasure._hasItems = true;
return false;
}
} else {
- for (idx = 0; idx < 10 && _treasure._misc[idx]._material; ++idx);
- if (idx < 10) {
- _treasure._accessories[idx]._material = giveVal - 60;
+ for (idx = 0; idx < MAX_TREASURE_ITEMS && _treasure._misc[idx]._material; ++idx) {}
+ if (idx < MAX_TREASURE_ITEMS) {
+ _treasure._accessories[idx]._material = giveVal - ACCESSORIES_END;
_treasure._hasItems = true;
return false;
}
@@ -1355,7 +1361,7 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
Character &tempChar = _itemsCharacter;
int idx = -1;
if (scripts._itemType != 0) {
- for (idx = 0; idx < 10 && _treasure._misc[idx]._material; ++idx);
+ for (idx = 0; idx < 10 && _treasure._misc[idx]._material; ++idx) {}
if (idx == 10)
return true;
}
@@ -1366,14 +1372,14 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
XeenItem *trItems = _treasure[itemCat];
// Check for a free treasure slot
- for (idx = 0; idx < 10 && trItems[idx]._id; ++idx);
+ for (idx = 0; idx < 10 && trItems[idx]._id; ++idx) {}
if (idx == 10)
return true;
// Found a free slot, so copy the created item into it
trItems[idx]._material = srcItem._material;
trItems[idx]._id = srcItem._id;
- trItems[idx]._bonusFlags = srcItem._bonusFlags;
+ trItems[idx]._state = srcItem._state;
_treasure._hasItems = true;
break;
}
@@ -1435,16 +1441,16 @@ bool Party::giveTake(int takeMode, uint takeVal, int giveMode, uint giveVal, int
_gold += _vm->getRandomNumber(1, giveVal);
break;
case 103:
- assert(takeVal < 128);
- _worldFlags[takeVal] = true;
+ assert(giveVal < (uint)(_vm->getGameID() == GType_Swords ? 49 : 128));
+ _worldFlags[giveVal] = true;
break;
case 104:
- assert(giveVal < 30);
- _questFlags[files._isDarkCc][giveVal] = true;
+ assert(giveVal < (uint)(_vm->getGameID() == GType_Swords ? 60 : 30));
+ _questFlags[(_vm->getGameID() == GType_Swords ? 0 : files._ccNum * 30) + giveVal] = true;
break;
case 107:
- assert(takeVal < 24);
- _characterFlags[ps._rosterId][takeVal] = true;
+ assert(giveVal < 24);
+ _characterFlags[ps._rosterId][giveVal] = true;
break;
default:
break;
@@ -1460,19 +1466,21 @@ bool Party::giveExt(int mode1, uint val1, int mode2, uint val2, int mode3, uint
Map &map = *g_vm->_map;
Scripts &scripts = *g_vm->_scripts;
Sound &sound = *g_vm->_sound;
- Character &c = _itemsCharacter;
- if (intf._objNumber && !scripts._animCounter) {
- MazeObject &obj = map._mobData._objects[intf._objNumber - 1];
+ // WORKAROUND: Ali Baba's chest in Dark Side requires the character in the first slot to have Lockpicking.
+ // This is obviously a mistake, since the chest is meant to be opened via a password
+ if (intf._objNumber != -1 && !scripts._animCounter && !(files._ccNum && _mazeId == 63 && intf._objNumber == 15)) {
+ MazeObject &obj = map._mobData._objects[intf._objNumber];
switch (obj._spriteId) {
case 15:
- if (!files._isDarkCc)
+ if (!files._ccNum)
break;
// Intentional fall-through
case 16:
case 58:
- case 73:
+ case 73: {
+ Character &c = _activeParty[charId];
obj._frame = 1;
if (obj._position.x != 20) {
@@ -1490,19 +1498,24 @@ bool Party::giveExt(int mode1, uint val1, int mode2, uint val2, int mode3, uint
sound.playFX(10);
intf.draw3d(true, false);
Common::String msg = Common::String::format(Res.PICKS_THE_LOCK, c._name.c_str());
- ErrorScroll::show(g_vm, msg);
+ ErrorScroll::show(g_vm, msg, WT_NONFREEZED_WAIT);
} else {
sound.playFX(21);
obj._frame = 0;
scripts._animCounter = 0;
Common::String msg = Common::String::format(Res.UNABLE_TO_PICK_LOCK, c._name.c_str());
- ErrorScroll::show(g_vm, msg);
+ ErrorScroll::show(g_vm, msg, WT_NONFREEZED_WAIT);
scripts._animCounter = 255;
return true;
}
}
+ break;
+ }
+
+ default:
+ break;
}
}
@@ -1520,7 +1533,7 @@ bool Party::giveExt(int mode1, uint val1, int mode2, uint val2, int mode3, uint
break;
case 66:
- c.clear();
+ _itemsCharacter.clear();
if (giveTake(0, 0, mode, val, charId))
return true;
@@ -1590,7 +1603,7 @@ uint Party::getScore() {
uint time = _vm->_events->playTime() / GAME_FRAME_RATE;
int minutes = (time % 3600) / 60;
int hours = time / 3600;
-
+
score += minutes + (hours * 100);
return score;
}
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 881b1502c5..fde6defeee 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -53,6 +53,7 @@ enum PartyBank {
#define MAX_PARTY_COUNT 8
#define TOTAL_STATS 7
#define TOTAL_QUEST_ITEMS 85
+#define TOTAL_QUEST_ITEMS_SWORDS 51
#define TOTAL_QUEST_FLAGS 56
#define MAX_TREASURE_ITEMS 10
@@ -81,6 +82,16 @@ public:
* Returns a particular category's array
*/
XeenItem *operator[](int category) { return _categories[category]; }
+
+ /**
+ * Clears the treasure list
+ */
+ void clear();
+
+ /**
+ * Completely reset the treasure data
+ */
+ void reset();
};
/**
@@ -184,9 +195,9 @@ public:
int _heroism;
Difficulty _difficulty;
BlacksmithWares _blacksmithWares;
- bool _cloudsEnd;
- bool _darkSideEnd;
- bool _worldEnd;
+ bool _cloudsCompleted;
+ bool _darkSideCompleted;
+ bool _worldCompleted;
int _ctr24; // Unused counter
int _day;
uint _year;
@@ -209,14 +220,13 @@ public:
bool _rested;
bool _gameFlags[2][256];
bool _worldFlags[128];
- bool _questFlags[2][30];
+ bool _questFlags[60];
int _questItems[TOTAL_QUEST_ITEMS];
bool _characterFlags[30][24];
public:
// Other party related runtime data
Roster _roster;
- Common::Array<Character> _activeParty;
- bool _partyDead;
+ CharacterArray _activeParty;
bool _newDay;
bool _isNight;
bool _stepped;
diff --git a/engines/xeen/patcher.cpp b/engines/xeen/patcher.cpp
new file mode 100644
index 0000000000..10c8664776
--- /dev/null
+++ b/engines/xeen/patcher.cpp
@@ -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.
+ *
+ */
+
+#include "xeen/patcher.h"
+#include "xeen/xeen.h"
+#include "xeen/map.h"
+#include "xeen/party.h"
+#include "common/memstream.h"
+#include "common/serializer.h"
+
+namespace Xeen {
+
+struct ScriptEntry {
+ uint _gameId;
+ int _mapId;
+ const byte *_data;
+};
+
+const byte DS_MAP54_LINE8[] = { 8, 10, 10, DIR_EAST, 8, OP_MoveWallObj, 20, 100, 100 };
+const byte SW_MAP53_LINE8[] = { 5, 14, 6, DIR_EAST, 8, OP_Exit };
+const byte DS_MAP116[] = { 9, 10, 6, 4, 2, OP_TakeOrGive, 0, 0, 103, 127 };
+
+#define SCRIPT_PATCHES_COUNT 3
+static const ScriptEntry SCRIPT_PATCHES[] = {
+ { GType_DarkSide, 54, DS_MAP54_LINE8 }, // Fix curtain on level 2 of Ellinger's Tower
+ { GType_Swords, 53, SW_MAP53_LINE8 }, // Fix chest in Hart having gems, but saying "Nothing Here"
+ { GType_DarkSide, 116, DS_MAP116 } // Fix statue in Dark Tower setting invalid world flag
+};
+
+/*------------------------------------------------------------------------*/
+
+void Patcher::patch() {
+ patchScripts();
+ patchObjects();
+}
+
+void Patcher::patchScripts() {
+ FileManager &files = *g_vm->_files;
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+
+ uint gameId = g_vm->getGameID();
+ if (gameId == GType_WorldOfXeen)
+ gameId = files._ccNum ? GType_DarkSide : GType_Clouds;
+
+ for (int patchIdx = 0; patchIdx < SCRIPT_PATCHES_COUNT; ++patchIdx) {
+ const ScriptEntry &se = SCRIPT_PATCHES[patchIdx];
+ if (se._gameId != gameId || se._mapId != party._mazeId)
+ continue;
+
+ MazeEvent evt;
+ Common::MemoryReadStream memStream(se._data, se._data[0] + 1);
+ Common::Serializer s(&memStream, nullptr);
+ evt.synchronize(s);
+
+ // Scan through the events to find a matching line
+ int idx = 0;
+ while (idx < (int)map._events.size() && (evt._position != map._events[idx]._position
+ || evt._direction != map._events[idx]._direction || evt._line != map._events[idx]._line))
+ ++idx;
+
+ // Set the event
+ if (idx == (int)map._events.size())
+ map._events.push_back(evt);
+ else
+ map._events[idx] = evt;
+ }
+}
+
+void Patcher::patchObjects() {
+ FileManager &files = *g_vm->_files;
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+
+ if ((g_vm->getGameID() == GType_Clouds || (g_vm->getGameID() == GType_WorldOfXeen && !files._ccNum)) &&
+ party._mazeId == 24) {
+ // Remove floating statue in the distance off SE corner of Clouds of Xeen map
+ map._mobData._objects[15]._position = Common::Point(-128, -128);
+ }
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/worldofxeen/worldofxeen_resources.h b/engines/xeen/patcher.h
index e69f52028d..24d6cd5a8d 100644
--- a/engines/xeen/worldofxeen/worldofxeen_resources.h
+++ b/engines/xeen/patcher.h
@@ -20,29 +20,34 @@
*
*/
-#ifndef XEEN_WORLDOFXEEN_RESOURCES_H
-#define XEEN_WORLDOFXEEN_RESOURCES_H
-
-#include "xeen/resources.h"
+#ifndef XEEN_PATCHER_H
+#define XEEN_PATCHER_H
namespace Xeen {
-namespace WorldOfXeen {
-#ifdef Res
-#undef Res
-#endif
-#define Res (*(WorldOfXeenResources *)g_resources)
+class Patcher {
+private:
+ /**
+ * Patches incorrect script lines
+ */
+ void patchScripts();
-class WorldOfXeenResources : public Resources {
+ /**
+ * Patches incorrect map objects
+ */
+ void patchObjects();
public:
- static const char *const CLOUDS_INTRO1;
- static const char *const DARKSIDE_ENDING1;
- static const char *const DARKSIDE_ENDING2;
- static const char *const PHAROAH_ENDING_TEXT1;
- static const char *const PHAROAH_ENDING_TEXT2;
+ /**
+ * Constructor
+ */
+ Patcher() {}
+
+ /**
+ * Called after a map is loaded to patch any problems
+ */
+ void patch();
};
-} // End of namespace WorldOfXeen
} // End of namespace Xeen
-#endif /* XEEN_RESOURCES_H */
+#endif /* XEEN_PATCHER_H */
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index c2732a9bf9..160c60a7a9 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -24,7 +24,6 @@
#include "xeen/resources.h"
#include "xeen/files.h"
#include "xeen/xeen.h"
-#include "xeen/worldofxeen/worldofxeen_resources.h"
namespace Xeen {
@@ -33,7 +32,7 @@ Resources *g_resources;
Resources::Resources() {
g_resources = this;
g_vm->_files->setGameCc(1);
-
+
_globalSprites.load("global.icn");
if (g_vm->getGameID() == GType_Swords)
_logoSprites.load("logo.int");
@@ -72,6 +71,7 @@ void Resources::loadData() {
file.syncString(WHO_WILL);
file.syncString(HOW_MUCH);
file.syncString(WHATS_THE_PASSWORD);
+ file.syncString(PASSWORD_INCORRECT);
file.syncString(IN_NO_CONDITION);
file.syncString(NOTHING_HERE);
file.syncStrings(TERRAIN_TYPES, 6);
@@ -165,7 +165,7 @@ void Resources::loadData() {
file.syncString(FOOD_AND_DRINK);
file.syncString(TEMPLE_TEXT);
file.syncString(EXPERIENCE_FOR_LEVEL);
- file.syncString(LEARNED_ALL);
+ file.syncString(TRAINING_LEARNED_ALL);
file.syncString(ELIGIBLE_FOR_LEVEL);
file.syncString(TRAINING_TEXT);
file.syncString(GOLD_GEMS);
@@ -182,18 +182,20 @@ void Resources::loadData() {
file.syncString(GUILD_OPTIONS);
file.syncNumbers((int *)MISC_SPELL_INDEX, 74);
file.syncNumbers((int *)SPELL_COSTS, 77);
- file.syncNumbers2D((int *)CLOUDS_SPELL_OFFSETS, 5, 20);
+ file.syncNumbers2D((int *)CLOUDS_GUILD_SPELLS, 5, 20);
file.syncNumbers2D((int *)DARK_SPELL_OFFSETS, 3, 39);
file.syncNumbers2D((int *)DARK_SPELL_RANGES, 12, 2);
+ file.syncNumbers2D((int *)SWORDS_SPELL_RANGES, 12, 2);
file.syncNumbers((int *)SPELL_GEM_COST, 77);
file.syncString(NOT_A_SPELL_CASTER);
+ file.syncString(SPELLS_LEARNED_ALL);
file.syncString(SPELLS_FOR);
file.syncString(SPELL_LINES_0_TO_9);
file.syncString(SPELLS_DIALOG_SPELLS);
file.syncString(SPELL_PTS);
file.syncString(GOLD);
- file.syncString(SPELLS_PRESS_A_KEY);
- file.syncString(SPELLS_PURCHASE);
+ file.syncString(SPELL_INFO);
+ file.syncString(SPELL_PURCHASE);
file.syncString(MAP_TEXT);
file.syncString(LIGHT_COUNT_TEXT);
file.syncString(FIRE_RESISTENCE_TEXT);
@@ -247,15 +249,18 @@ void Resources::loadData() {
file.syncString(BTN_GOLD);
file.syncString(ITEM_BROKEN);
file.syncString(ITEM_CURSED);
+ file.syncString(ITEM_OF);
file.syncStrings(BONUS_NAMES, 7);
- file.syncStrings(WEAPON_NAMES, 35);
+ file.syncStrings(WEAPON_NAMES, 41);
file.syncStrings(ARMOR_NAMES, 14);
file.syncStrings(ACCESSORY_NAMES, 11);
file.syncStrings(MISC_NAMES, 22);
+ file.syncStrings(SPECIAL_NAMES, 74);
file.syncStrings(ELEMENTAL_NAMES, 6);
file.syncStrings(ATTRIBUTE_NAMES, 10);
file.syncStrings(EFFECTIVENESS_NAMES, 7);
file.syncStrings(QUEST_ITEM_NAMES, 85);
+ file.syncStrings(QUEST_ITEM_NAMES_SWORDS, 51);
file.syncNumbers((int *)WEAPON_BASE_COSTS, 35);
file.syncNumbers((int *)ARMOR_BASE_COSTS, 14);
file.syncNumbers((int *)ACCESSORY_BASE_COSTS, 11);
@@ -310,6 +315,7 @@ void Resources::loadData() {
file.syncString(QUESTS_DIALOG_TEXT);
file.syncString(CLOUDS_OF_XEEN_LINE);
file.syncString(DARKSIDE_OF_XEEN_LINE);
+ file.syncString(SWORDS_OF_XEEN_LINE);
file.syncString(NO_QUEST_ITEMS);
file.syncString(NO_CURRENT_QUESTS);
file.syncString(NO_AUTO_NOTES);
@@ -322,6 +328,7 @@ void Resources::loadData() {
file.syncString(TOO_DANGEROUS_TO_REST);
file.syncString(SOME_CHARS_MAY_DIE);
file.syncString(CANT_DISMISS_LAST_CHAR);
+ file.syncString(DELETE_CHAR_WITH_ELDER_WEAPON);
file.syncStrings(REMOVE_DELETE, 2);
file.syncString(REMOVE_OR_DELETE_WHICH);
file.syncString(YOUR_PARTY_IS_FULL);
@@ -333,6 +340,7 @@ void Resources::loadData() {
file.syncString(SELECT_CLASS_BEFORE_SAVING);
file.syncString(EXCHANGE_ATTR_WITH);
file.syncNumbers((int *)NEW_CHAR_SKILLS, 10);
+ file.syncNumbers((int *)NEW_CHAR_SKILLS_OFFSET, 10);
file.syncNumbers((int *)NEW_CHAR_SKILLS_LEN, 10);
file.syncNumbers((int *)NEW_CHAR_RACE_SKILLS, 10);
file.syncNumbers((int *)RACE_MAGIC_RESISTENCES, 5);
@@ -358,7 +366,8 @@ void Resources::loadData() {
file.syncString(LLOYDS_BEACON);
file.syncString(HOW_MANY_SQUARES);
file.syncString(TOWN_PORTAL);
- file.syncNumbers2D((int *)TOWN_MAP_NUMBERS, 2, 5);
+ file.syncString(TOWN_PORTAL_SWORDS);
+ file.syncNumbers2D((int *)TOWN_MAP_NUMBERS, 3, 5);
file.syncString(MONSTER_DETAILS);
file.syncStrings(MONSTER_SPECIAL_ATTACKS, 23);
file.syncString(IDENTIFY_MONSTERS);
@@ -392,6 +401,12 @@ void Resources::loadData() {
file.syncStrings(MUSIC_FILES1, 5);
file.syncStrings2D(&MUSIC_FILES2[0][0], 6, 7);
file.syncString(DIFFICULTY_TEXT);
+ file.syncString(SAVE_OFF_LIMITS);
+ file.syncString(CLOUDS_INTRO1);
+ file.syncString(DARKSIDE_ENDING1);
+ file.syncString(DARKSIDE_ENDING2);
+ file.syncString(PHAROAH_ENDING_TEXT1);
+ file.syncString(PHAROAH_ENDING_TEXT2);
}
} // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 0659de45c9..55f0ed3413 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -126,6 +126,7 @@ public:
const char *WHO_WILL;
const char *HOW_MUCH;
const char *WHATS_THE_PASSWORD;
+ const char *PASSWORD_INCORRECT;
const char *IN_NO_CONDITION;
const char *NOTHING_HERE;
const char *TERRAIN_TYPES[6];
@@ -219,7 +220,7 @@ public:
const char *FOOD_AND_DRINK;
const char *TEMPLE_TEXT;
const char *EXPERIENCE_FOR_LEVEL;
- const char *LEARNED_ALL;
+ const char *TRAINING_LEARNED_ALL;
const char *ELIGIBLE_FOR_LEVEL;
const char *TRAINING_TEXT;
const char *GOLD_GEMS;
@@ -236,19 +237,20 @@ public:
const char *GUILD_OPTIONS;
int MISC_SPELL_INDEX[74];
int SPELL_COSTS[77];
- int CLOUDS_SPELL_OFFSETS[5][20];
+ int CLOUDS_GUILD_SPELLS[5][20];
int DARK_SPELL_OFFSETS[3][39];
int DARK_SPELL_RANGES[12][2];
- int SPELL_LEVEL_OFFSETS[3][39];
+ int SWORDS_SPELL_RANGES[12][2];
int SPELL_GEM_COST[77];
const char *NOT_A_SPELL_CASTER;
+ const char *SPELLS_LEARNED_ALL;
const char *SPELLS_FOR;
const char *SPELL_LINES_0_TO_9;
const char *SPELLS_DIALOG_SPELLS;
const char *SPELL_PTS;
const char *GOLD;
- const char *SPELLS_PRESS_A_KEY;
- const char *SPELLS_PURCHASE;
+ const char *SPELL_INFO;
+ const char *SPELL_PURCHASE;
const char *MAP_TEXT;
const char *LIGHT_COUNT_TEXT;
const char *FIRE_RESISTENCE_TEXT;
@@ -302,15 +304,18 @@ public:
const char *BTN_GOLD;
const char *ITEM_BROKEN;
const char *ITEM_CURSED;
+ const char *ITEM_OF;
const char *BONUS_NAMES[7];
- const char *WEAPON_NAMES[35];
+ const char *WEAPON_NAMES[41];
const char *ARMOR_NAMES[14];
const char *ACCESSORY_NAMES[11];
const char *MISC_NAMES[22];
+ const char *SPECIAL_NAMES[74];
const char *ELEMENTAL_NAMES[6];
const char *ATTRIBUTE_NAMES[10];
const char *EFFECTIVENESS_NAMES[7];
const char *QUEST_ITEM_NAMES[85];
+ const char *QUEST_ITEM_NAMES_SWORDS[51];
int WEAPON_BASE_COSTS[35];
int ARMOR_BASE_COSTS[14];
int ACCESSORY_BASE_COSTS[11];
@@ -365,6 +370,7 @@ public:
const char *QUESTS_DIALOG_TEXT;
const char *CLOUDS_OF_XEEN_LINE;
const char *DARKSIDE_OF_XEEN_LINE;
+ const char *SWORDS_OF_XEEN_LINE;
const char *NO_QUEST_ITEMS;
const char *NO_CURRENT_QUESTS;
const char *NO_AUTO_NOTES;
@@ -377,6 +383,7 @@ public:
const char *TOO_DANGEROUS_TO_REST;
const char *SOME_CHARS_MAY_DIE;
const char *CANT_DISMISS_LAST_CHAR;
+ const char *DELETE_CHAR_WITH_ELDER_WEAPON;
const char *REMOVE_DELETE[2];
const char *REMOVE_OR_DELETE_WHICH;
const char *YOUR_PARTY_IS_FULL;
@@ -388,6 +395,7 @@ public:
const char *SELECT_CLASS_BEFORE_SAVING;
const char *EXCHANGE_ATTR_WITH;
int NEW_CHAR_SKILLS[10];
+ int NEW_CHAR_SKILLS_OFFSET[10];
int NEW_CHAR_SKILLS_LEN[10];
int NEW_CHAR_RACE_SKILLS[10];
int RACE_MAGIC_RESISTENCES[5];
@@ -413,7 +421,8 @@ public:
const char *LLOYDS_BEACON;
const char *HOW_MANY_SQUARES;
const char *TOWN_PORTAL;
- int TOWN_MAP_NUMBERS[2][5];
+ const char *TOWN_PORTAL_SWORDS;
+ int TOWN_MAP_NUMBERS[3][5];
const char *MONSTER_DETAILS;
const char *MONSTER_SPECIAL_ATTACKS[23];
const char *IDENTIFY_MONSTERS;
@@ -447,6 +456,12 @@ public:
const char *MUSIC_FILES1[5];
const char *MUSIC_FILES2[6][7];
const char *DIFFICULTY_TEXT;
+ const char *SAVE_OFF_LIMITS;
+ const char *CLOUDS_INTRO1;
+ const char *DARKSIDE_ENDING1;
+ const char *DARKSIDE_ENDING2;
+ const char *PHAROAH_ENDING_TEXT1;
+ const char *PHAROAH_ENDING_TEXT2;
public:
/**
* Constructor
diff --git a/engines/xeen/saves.cpp b/engines/xeen/saves.cpp
index 7bd938180e..82e294921b 100644
--- a/engines/xeen/saves.cpp
+++ b/engines/xeen/saves.cpp
@@ -48,9 +48,8 @@ SavesManager::~SavesManager() {
const char *const SAVEGAME_STR = "XEEN";
#define SAVEGAME_STR_SIZE 6
-bool SavesManager::readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header) {
+WARN_UNUSED_RESULT bool SavesManager::readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header, bool skipThumbnail) {
char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
- header._thumbnail = nullptr;
// Validate the header Id
in->read(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
@@ -68,9 +67,9 @@ bool SavesManager::readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader
header._saveName += ch;
// Get the thumbnail
- header._thumbnail = Graphics::loadThumbnail(*in);
- if (!header._thumbnail)
+ if (!Graphics::loadThumbnail(*in, header._thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
header._year = in->readSint16LE();
@@ -153,6 +152,7 @@ Common::Error SavesManager::saveGameState(int slot, const Common::String &desc)
}
Common::Error SavesManager::loadGameState(int slot) {
+ Combat &combat = *g_vm->_combat;
EventsManager &events = *g_vm->_events;
FileManager &files = *g_vm->_files;
Map &map = *g_vm->_map;
@@ -168,11 +168,6 @@ Common::Error SavesManager::loadGameState(int slot) {
if (!readSavegameHeader(saveFile, header))
error("Invalid savegame");
- if (header._thumbnail) {
- header._thumbnail->free();
- delete header._thumbnail;
- }
-
// Set the total play time
events.setPlayTime(header._totalFrames);
@@ -182,9 +177,13 @@ Common::Error SavesManager::loadGameState(int slot) {
uint fileSize = saveFile->readUint32LE();
if (archives[idx]) {
- Common::SeekableSubReadStream arcStream(saveFile, saveFile->pos(),
- saveFile->pos() + fileSize);
- archives[idx]->load(arcStream);
+ if (fileSize) {
+ Common::SeekableSubReadStream arcStream(saveFile, saveFile->pos(),
+ saveFile->pos() + fileSize);
+ archives[idx]->load(arcStream);
+ } else {
+ archives[idx]->reset((idx == 1) ? File::_darkCc : File::_xeenCc);
+ }
} else {
assert(!fileSize);
}
@@ -193,9 +192,16 @@ Common::Error SavesManager::loadGameState(int slot) {
// Read in miscellaneous
files.load(*saveFile);
+ // Load the character roster and party
+ File::_currentSave->loadParty();
+
+ // Reset any combat information from the previous game
+ combat.reset();
+ party._treasure.reset();
+
// Load the new map
map.clearMaze();
- map._loadDarkSide = files._isDarkCc;
+ map._loadCcNum = files._ccNum;
map.load(party._mazeId);
delete saveFile;
@@ -212,6 +218,10 @@ void SavesManager::newGame() {
File::_xeenSave = nullptr;
File::_darkSave = nullptr;
+ // Reset any combat information from the previous game
+ g_vm->_combat->reset();
+
+ // Reset the game states
if (g_vm->getGameID() != GType_Clouds) {
File::_darkSave = new SaveArchive(g_vm->_party);
File::_darkSave->reset(File::_darkCc);
@@ -225,6 +235,9 @@ void SavesManager::newGame() {
File::_darkSave : File::_xeenSave;
assert(File::_currentSave);
+ // Load the character roster and party
+ File::_currentSave->loadParty();
+
// Set any final initial values
Party &party = *g_vm->_party;
party.resetBlacksmithWares();
@@ -245,32 +258,37 @@ void SavesManager::newGame() {
}
bool SavesManager::loadGame() {
- if (!g_vm->canLoadGameStateCurrently())
- return false;
-
GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load"), false);
int slotNum = dialog->runModalWithCurrentTarget();
delete dialog;
- if (slotNum != -1)
+ if (slotNum != -1) {
loadGameState(slotNum);
+ g_vm->_interface->drawParty(true);
+ }
return slotNum != -1;
}
bool SavesManager::saveGame() {
- if (!g_vm->canSaveGameStateCurrently())
- return false;
+ Map &map = *g_vm->_map;
- GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
- int slotNum = dialog->runModalWithCurrentTarget();
- Common::String saveName = dialog->getResultString();
- delete dialog;
+ if (map.mazeData()._mazeFlags & RESTRICTION_SAVE) {
+ ErrorScroll::show(g_vm, Res.SAVE_OFF_LIMITS, WT_NONFREEZED_WAIT);
+ return false;
+ } else if (!g_vm->canSaveGameStateCurrently()) {
+ return false;
+ } else {
+ GUI::SaveLoadChooser *dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true);
+ int slotNum = dialog->runModalWithCurrentTarget();
+ Common::String saveName = dialog->getResultString();
+ delete dialog;
- if (slotNum != -1)
- saveGameState(slotNum, saveName);
+ if (slotNum != -1)
+ saveGameState(slotNum, saveName);
- return slotNum != -1;
+ return slotNum != -1;
+ }
}
} // End of namespace Xeen
diff --git a/engines/xeen/saves.h b/engines/xeen/saves.h
index b18e04a822..9b1bea62a3 100644
--- a/engines/xeen/saves.h
+++ b/engines/xeen/saves.h
@@ -65,7 +65,7 @@ public:
/**
* Read in a savegame header
*/
- static bool readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header);
+ WARN_UNUSED_RESULT static bool readSavegameHeader(Common::InSaveFile *in, XeenSavegameHeader &header, bool skipThumbnail = true);
/**
* Write out a savegame header
diff --git a/engines/xeen/screen.cpp b/engines/xeen/screen.cpp
index c9781b3cf1..47735478ed 100644
--- a/engines/xeen/screen.cpp
+++ b/engines/xeen/screen.cpp
@@ -169,7 +169,7 @@ bool Screen::doScroll(bool rollUp, bool fadeInFlag) {
const int SCROLL_L[8] = { 29, 23, 15, -5, -11, -23, -49, -71 };
const int SCROLL_R[8] = { 165, 171, 198, 218, 228, 245, 264, 281 };
- if (_vm->_files->_isDarkCc) {
+ if (_vm->_files->_ccNum) {
if (fadeInFlag)
screen.fadeIn(2);
return _vm->shouldExit();
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp
index 8777cdc6e0..bc0b179d4c 100644
--- a/engines/xeen/scripts.cpp
+++ b/engines/xeen/scripts.cpp
@@ -21,7 +21,10 @@
*/
#include "common/config-manager.h"
+#include "common/textconsole.h"
+#include "backends/audiocd/audiocd.h"
#include "xeen/scripts.h"
+#include "xeen/dialogs/dialogs_copy_protection.h"
#include "xeen/dialogs/dialogs_input.h"
#include "xeen/dialogs/dialogs_whowill.h"
#include "xeen/dialogs/dialogs_query.h"
@@ -138,7 +141,7 @@ int Scripts::checkEvents() {
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
Windows &windows = *_vm->_windows;
- bool isDarkCc = files._isDarkCc;
+ int ccNum = files._ccNum;
_refreshIcons = false;
_itemType = 0;
@@ -182,10 +185,10 @@ int Scripts::checkEvents() {
for (eventIndex = 0; eventIndex < map._events.size() && !_vm->shouldExit(); ++eventIndex) {
MazeEvent &event = map._events[eventIndex];
- if (event._position == _currentPos && party._mazeDirection !=
- (_currentPos.x | _currentPos.y) && event._line == _lineNum) {
+ if (event._position == _currentPos && event._line == _lineNum &&
+ (party._mazeDirection | _currentPos.x | _currentPos.y)) {
if (event._direction == party._mazeDirection || event._direction == DIR_ALL) {
- _vm->_mode = MODE_RECORD_EVENTS;
+ _vm->_mode = MODE_SCRIPT_IN_PROGRESS;
_scriptExecuted = true;
doOpcode(event);
break;
@@ -209,24 +212,27 @@ int Scripts::checkEvents() {
if (party._treasure._hasItems || party._treasure._gold || party._treasure._gems)
party.giveTreasure();
- if (_animCounter > 0 && intf._objNumber) {
- MazeObject &selectedObj = map._mobData._objects[intf._objNumber - 1];
+ if (_animCounter > 0 && intf._objNumber != -1) {
+ MazeObject &selectedObj = map._mobData._objects[intf._objNumber];
- if (selectedObj._spriteId == (isDarkCc ? 15 : 16)) {
- for (uint idx = 0; idx < 16; ++idx) {
- MazeObject &obj = map._mobData._objects[idx];
- if (obj._spriteId == (isDarkCc ? 62 : 57)) {
+ if (selectedObj._spriteId == (ccNum ? 15 : 16)) {
+ // Treasure chests that were opened will be set to be in an open, empty state
+ for (uint idx = 0; idx < map._mobData._objectSprites.size(); ++idx) {
+ MonsterObjectData::SpriteResourceEntry &e = map._mobData._objectSprites[idx];
+ if (e._spriteId == (ccNum ? 57 : 62)) {
selectedObj._id = idx;
- selectedObj._spriteId = isDarkCc ? 62 : 57;
+ selectedObj._spriteId = ccNum ? 57 : 62;
+ selectedObj._sprites = &e._sprites;
break;
}
}
} else if (selectedObj._spriteId == 73) {
- for (uint idx = 0; idx < 16; ++idx) {
- MazeObject &obj = map._mobData._objects[idx];
- if (obj._spriteId == 119) {
+ for (uint idx = 0; idx < map._mobData._objectSprites.size(); ++idx) {
+ MonsterObjectData::SpriteResourceEntry &e = map._mobData._objectSprites[idx];
+ if (e._spriteId == 119) {
selectedObj._id = idx;
selectedObj._spriteId = 119;
+ selectedObj._sprites = &e._sprites;
break;
}
}
@@ -237,8 +243,17 @@ int Scripts::checkEvents() {
_vm->_mode = oldMode;
windows.closeAll();
- if (_scriptExecuted || !intf._objNumber || _dirFlag) {
- if (_dirFlag && !_scriptExecuted && intf._objNumber && !map._currentIsEvent) {
+ if (g_vm->getIsCD() && g_system->getAudioCDManager()->isPlaying())
+ // Stop any playing voice
+ g_system->getAudioCDManager()->stop();
+
+ if (g_vm->shouldExit())
+ return g_vm->_gameMode;
+
+ if (_scriptExecuted)
+ intf.clearEvents();
+ if (_scriptExecuted || intf._objNumber == -1 || _dirFlag) {
+ if (_dirFlag && !_scriptExecuted && intf._objNumber != -1 && !map._currentIsEvent) {
sound.playFX(21);
}
} else {
@@ -269,69 +284,71 @@ int Scripts::checkEvents() {
return _scriptResult;
}
-void Scripts::openGrate(int wallVal, int action) {
+bool Scripts::openGrate(int wallVal, int action) {
Combat &combat = *_vm->_combat;
FileManager &files = *_vm->_files;
Interface &intf = *_vm->_interface;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
- bool isDarkCc = files._isDarkCc;
-
- if ((wallVal != 13 || map._currentGrateUnlocked) && (!isDarkCc || wallVal != 9 ||
- map.mazeData()._wallKind != 2)) {
- if (wallVal != 9 && !map._currentGrateUnlocked) {
- int charIndex = WhoWill::show(_vm, 13, action, false) - 1;
- if (charIndex < 0) {
- intf.draw3d(true);
- return;
- }
+ int ccNum = files._ccNum;
- // There is a 1 in 4 chance the character will receive damage
- if (_vm->getRandomNumber(1, 4) == 1) {
- combat.giveCharDamage(map.mazeData()._trapDamage,
- (DamageType)_vm->getRandomNumber(0, 6), charIndex);
- }
+ if (!((wallVal != 13 || map._currentGrateUnlocked) && (!ccNum || wallVal != 9 ||
+ map.mazeData()._wallKind != 2)))
+ return false;
- // Check whether character can unlock the door
- Character &c = party._activeParty[charIndex];
- if ((c.getThievery() + _vm->getRandomNumber(1, 20)) <
- map.mazeData()._difficulties._unlockDoor)
- return;
+ if (wallVal != 9 && !map._currentGrateUnlocked) {
+ int charIndex = WhoWill::show(_vm, 13, action, false) - 1;
+ if (charIndex < 0) {
+ intf.draw3d(true);
+ return true;
+ }
- c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel();
+ // There is a 1 in 4 chance the character will receive damage
+ if (_vm->getRandomNumber(1, 4) == 1) {
+ combat.giveCharDamage(map.mazeData()._trapDamage,
+ (DamageType)_vm->getRandomNumber(0, 6), charIndex);
}
- // Flag the grate as unlocked, and the wall the grate is on
- map.setCellSurfaceFlags(party._mazePosition, 0x80);
- map.setWall(party._mazePosition, party._mazeDirection, wallVal);
+ // Check whether character can unlock the door
+ Character &c = party._activeParty[charIndex];
+ if ((c.getThievery() + _vm->getRandomNumber(1, 20)) <
+ map.mazeData()._difficulties._unlockDoor)
+ return true;
- // Set the grate as opened and the wall on the other side of the grate
- Common::Point pt = party._mazePosition;
- Direction dir = (Direction)((int)party._mazeDirection ^ 2);
- switch (party._mazeDirection) {
- case DIR_NORTH:
- pt.y++;
- break;
- case DIR_EAST:
- pt.x++;
- break;
- case DIR_SOUTH:
- pt.y--;
- break;
- case DIR_WEST:
- pt.x--;
- break;
- default:
- break;
- }
+ c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel();
+ }
- map.setCellSurfaceFlags(pt, 0x80);
- map.setWall(pt, dir, wallVal);
+ // Flag the grate as unlocked, and the wall the grate is on
+ map.setCellSurfaceFlags(party._mazePosition, 0x80);
+ map.setWall(party._mazePosition, party._mazeDirection, wallVal);
- sound.playFX(10);
- intf.draw3d(true);
+ // Set the grate as opened and the wall on the other side of the grate
+ Common::Point pt = party._mazePosition;
+ Direction dir = (Direction)((int)party._mazeDirection ^ 2);
+ switch (party._mazeDirection) {
+ case DIR_NORTH:
+ pt.y++;
+ break;
+ case DIR_EAST:
+ pt.x++;
+ break;
+ case DIR_SOUTH:
+ pt.y--;
+ break;
+ case DIR_WEST:
+ pt.x--;
+ break;
+ default:
+ break;
}
+
+ map.setCellSurfaceFlags(pt, 0x80);
+ map.setWall(pt, dir, wallVal);
+
+ sound.playFX(10);
+ intf.draw3d(true);
+ return true;
}
bool Scripts::doOpcode(MazeEvent &event) {
@@ -373,7 +390,7 @@ bool Scripts::doOpcode(MazeEvent &event) {
bool result = (this->*COMMAND_LIST[event._opcode])(params);
if (result)
// Move to next line
- _lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1;
+ _lineNum = _vm->_party->_dead ? SCRIPT_ABORT : _lineNum + 1;
return result;
}
@@ -465,7 +482,7 @@ bool Scripts::cmdTeleport(ParamsIterator &params) {
Sound &sound = *_vm->_sound;
windows.closeAll();
-
+
bool restartFlag = _event->_opcode == OP_TeleportAndContinue;
int mapId = params.readByte();
Common::Point pt;
@@ -491,8 +508,7 @@ bool Scripts::cmdTeleport(ParamsIterator &params) {
party._stepped = true;
if (mapId != party._mazeId) {
- int spriteId = (intf._objNumber == 0) ? -1 :
- map._mobData._objects[intf._objNumber - 1]._spriteId;
+ int spriteId = (intf._objNumber == -1) ? -1 : map._mobData._objects[intf._objNumber]._spriteId;
switch (spriteId) {
case 47:
@@ -519,7 +535,7 @@ bool Scripts::cmdTeleport(ParamsIterator &params) {
if (restartFlag) {
// Draw the new location and start any script at that location
- intf.draw3d(true);
+ events.ipause(2);
_lineNum = SCRIPT_RESET;
return false;
} else {
@@ -592,7 +608,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator &params) {
Combat &combat = *_vm->_combat;
Party &party = *_vm->_party;
Windows &windows = *_vm->_windows;
- int mode1, mode2, mode3, param2;
+ int mode1, mode2, mode3;
uint32 val1, val2, val3;
_refreshIcons = true;
@@ -614,7 +630,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator &params) {
break;
}
- param2 = mode2 = params.readByte();
+ mode2 = params.readByte();
switch (mode2) {
case 16:
case 34:
@@ -707,7 +723,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator &params) {
if (_charIndex == 0 || _charIndex == 8) {
for (uint idx = 0; idx < party._activeParty.size(); ++idx) {
if (_charIndex == 0 || (_charIndex == 8 && (int)idx != combat._combatTarget)) {
- party.giveTake(mode1, val1, mode2, val2, idx);
+ bool flag = party.giveTake(mode1, val1, mode2, val2, idx);
switch (mode1) {
case 8:
@@ -715,7 +731,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator &params) {
// fall through
case 21:
case 66:
- if (param2) {
+ if (flag) {
switch (mode2) {
case 82:
mode1 = 0;
@@ -728,13 +744,18 @@ bool Scripts::cmdTakeOrGive(ParamsIterator &params) {
case 100:
case 101:
case 106:
- if (param2)
+ if (flag)
continue;
// Break out of character loop
idx = party._activeParty.size();
break;
+ default:
+ break;
}
+ } else {
+ // Break out of character loop
+ idx = party._activeParty.size();
}
break;
@@ -744,7 +765,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator &params) {
case 100:
case 101:
case 106:
- if (param2) {
+ if (flag) {
_lineNum = -1;
return false;
}
@@ -766,7 +787,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator &params) {
case 100:
case 101:
case 106:
- if (param2)
+ if (flag)
continue;
// Break out of character loop
@@ -793,9 +814,9 @@ bool Scripts::cmdRemove(ParamsIterator &params) {
Interface &intf = *_vm->_interface;
Map &map = *_vm->_map;
- if (intf._objNumber) {
+ if (intf._objNumber != -1) {
// Give the active object a completely way out of bounds position
- MazeObject &obj = map._mobData._objects[intf._objNumber - 1];
+ MazeObject &obj = map._mobData._objects[intf._objNumber];
obj._position = Common::Point(128, 128);
}
@@ -845,7 +866,7 @@ bool Scripts::cmdSpawn(ParamsIterator &params) {
}
bool Scripts::cmdDoTownEvent(ParamsIterator &params) {
- _scriptResult = _vm->_locations->doAction((LocationAction)params.readByte());
+ _scriptResult = _vm->_locations->doAction(params.readByte());
_vm->_party->_stepped = true;
_refreshIcons = true;
@@ -930,40 +951,46 @@ bool Scripts::cmdConfirmWord(ParamsIterator &params) {
int param2 = params.readByte();
int param3 = params.readByte();
- Common::String msg1 = param2 ? map._events._text[param2] : _message;
- Common::String msg2;
+ Common::String expected2;
+ Common::String title;
if (_event->_opcode == OP_ConfirmWord_2) {
- msg2 = "";
+ title = "";
} else if (param3) {
- msg2 = map._events._text[param3];
+ title = map._events._text[param3];
} else {
- msg2 = Res.WHATS_THE_PASSWORD;
+ title = Res.WHATS_THE_PASSWORD;
}
- _mirrorId = StringInput::show(_vm, inputType, msg1, msg2, _event->_opcode);
+ if (!param2) {
+ expected2 = _message;
+ } else if (param2 < (int)map._events._text.size()) {
+ expected2 = map._events._text[param2];
+ }
+
+ _mirrorId = StringInput::show(_vm, inputType, expected2, title, _event->_opcode);
if (_mirrorId) {
- if (_mirrorId == 33 && files._isDarkCc) {
+ if (_mirrorId == 33 && files._ccNum) {
doDarkSideEnding();
- } else if (_mirrorId == 34 && files._isDarkCc) {
+ } else if (_mirrorId == 34 && files._ccNum) {
doWorldEnding();
- } else if (_mirrorId == 35 && files._isDarkCc &&
+ } else if (_mirrorId == 35 && files._ccNum &&
_vm->getGameID() == GType_WorldOfXeen) {
doCloudsEnding();
- } else if (_mirrorId == 40 && !files._isDarkCc) {
+ } else if (_mirrorId == 40 && !files._ccNum) {
doCloudsEnding();
- } else if (_mirrorId == 60 && !files._isDarkCc) {
+ } else if (_mirrorId == 60 && !files._ccNum) {
doDarkSideEnding();
- } else if (_mirrorId == 61 && !files._isDarkCc) {
+ } else if (_mirrorId == 61 && !files._ccNum) {
doWorldEnding();
} else {
- if (_mirrorId == 59 && !files._isDarkCc) {
+ if (_mirrorId == 59 && !files._ccNum) {
for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
XeenItem &item = party._treasure._weapons[idx];
if (!item._id) {
- item._id = 34;
+ item._id = XEEN_SLAYER_SWORD;
item._material = 0;
- item._bonusFlags = 0;
+ item._state.clear();
party._treasure._hasItems = true;
return cmdExit(params);
@@ -990,7 +1017,7 @@ bool Scripts::cmdDamage(ParamsIterator &params) {
int damage = params.readUint16LE();
DamageType damageType = (DamageType)params.readByte();
- combat.giveCharDamage(damage, damageType, _charIndex);
+ combat.giveCharDamage(damage, damageType, _charIndex - 1);
return true;
}
@@ -1033,11 +1060,16 @@ bool Scripts::cmdCallEvent(ParamsIterator &params) {
}
bool Scripts::cmdReturn(ParamsIterator &params) {
- StackEntry &se = _stack.top();
- _currentPos = se;
- _lineNum = se.line;
+ if (_stack.empty()) {
+ // WORKAROUND: Some scripts in Swords of Xeen use cmdReturn as a substitute for cmdExit
+ return cmdExit(params);
+ } else {
+ StackEntry se = _stack.pop();
+ _currentPos = se;
+ _lineNum = se.line;
- return true;
+ return true;
+ }
}
bool Scripts::cmdSetVar(ParamsIterator &params) {
@@ -1114,17 +1146,17 @@ bool Scripts::cmdRndDamage(ParamsIterator &params) {
DamageType dmgType = (DamageType)params.readByte();
int max = params.readByte();
- combat.giveCharDamage(_vm->getRandomNumber(1, max), dmgType, _charIndex);
+ combat.giveCharDamage(_vm->getRandomNumber(1, max), dmgType, _charIndex - 1);
return true;
}
bool Scripts::cmdMoveWallObj(ParamsIterator &params) {
Map &map = *_vm->_map;
- int itemNum = params.readByte();
+ int index = params.readByte();
int x = params.readShort();
int y = params.readShort();
- map._mobData._wallItems[itemNum]._position = Common::Point(x, y);
+ map._mobData._wallItems[index]._position = Common::Point(x, y);
return true;
}
@@ -1203,14 +1235,25 @@ bool Scripts::cmdDisplayBottom(ParamsIterator &params) {
bool Scripts::cmdIfMapFlag(ParamsIterator &params) {
Map &map = *_vm->_map;
- MazeMonster &monster = map._mobData._monsters[params.readByte()];
+ int monsterNum = params.readByte();
+ int lineNum = params.readByte();
- if (monster._position.x >= 32 || monster._position.y >= 32) {
- _lineNum = params.readByte();
- return false;
+ if (monsterNum == 0xff) {
+ for (monsterNum = 0; monsterNum < (int)map._mobData._monsters.size(); ++monsterNum) {
+ MazeMonster &monster = map._mobData._monsters[monsterNum];
+
+ if ((uint)monster._position.x < 32 && (uint)monster._position.y < 32)
+ return true;
+ }
+ } else {
+ MazeMonster &monster = map._mobData._monsters[monsterNum];
+
+ if ((uint)monster._position.x < 32 && (uint)monster._position.y < 32)
+ return true;
}
- return true;
+ _lineNum = lineNum;
+ return false;
}
bool Scripts::cmdSelectRandomChar(ParamsIterator &params) {
@@ -1220,64 +1263,47 @@ bool Scripts::cmdSelectRandomChar(ParamsIterator &params) {
bool Scripts::cmdGiveEnchanted(ParamsIterator &params) {
Party &party = *_vm->_party;
-
+ int itemOffset = _vm->getGameID() == GType_Swords ? 6 : 0;
+ XeenItem *item;
+ int invIndex;
int id = params.readByte();
- int material = params.readByte();
- int flags = params.readByte();
-
- if (id >= 35) {
- if (id < 49) {
- for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- XeenItem &item = party._treasure._armor[idx];
- if (!item.empty()) {
- item._id = id - 35;
- item._material = material;
- item._bonusFlags = flags;
- party._treasure._hasItems = true;
- break;
- }
- }
- return true;
- } else if (id < 60) {
- for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- XeenItem &item = party._treasure._accessories[idx];
- if (!item.empty()) {
- item._id = id - 49;
- item._material = material;
- item._bonusFlags = flags;
- party._treasure._hasItems = true;
- break;
- }
- }
+ // Get category of item to add
+ ItemCategory cat = CATEGORY_WEAPON;
+ if (id < (35 + itemOffset)) {
+ } else if (id < (49 + itemOffset)) {
+ cat = CATEGORY_ARMOR;
+ id -= 35 + itemOffset;
+ } else if (id < (60 + itemOffset)) {
+ cat = CATEGORY_ACCESSORY;
+ id -= 49 + itemOffset;
+ } else if (id < (82 + itemOffset)) {
+ cat = CATEGORY_MISC;
+ id -= 60 + itemOffset;
+ } else {
+ party._questItems[id - (82 + itemOffset)]++;
+ }
- return true;
- } else if (id < 82) {
- for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- XeenItem &item = party._treasure._misc[idx];
- if (!item.empty()) {
- item._id = id;
- item._material = material;
- item._bonusFlags = flags;
- party._treasure._hasItems = true;
- break;
- }
- }
+ // Check for an empty slot
+ for (invIndex = 0, item = party._treasure[cat]; invIndex < MAX_TREASURE_ITEMS && !item->empty(); ++invIndex, ++item)
+ ;
- return true;
- } else {
- party._questItems[id - 82]++;
- }
- }
+ if (invIndex == MAX_TREASURE_ITEMS) {
+ // Treasure category entirely full. Should never happen
+ warning("Treasure category was completely filled up");
+ } else {
+ party._treasure._hasItems = true;
- for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) {
- XeenItem &item = party._treasure._weapons[idx];
- if (!item.empty()) {
- item._id = id;
- item._material = material;
- item._bonusFlags = flags;
- party._treasure._hasItems = true;
- break;
+ if (cat == CATEGORY_MISC) {
+ // Handling of misc items. Note that for them, id actually specifies the material field
+ item->_material = id;
+ item->_id = params.readByte();
+ item->_state._counter = (item->_material == 10 || item->_material == 11) ? 1 : _vm->getRandomNumber(3, 10);
+ } else {
+ // Weapons, armor, and accessories
+ item->_id = id;
+ item->_material = params.readByte();
+ item->_state = params.readByte();
}
}
@@ -1391,6 +1417,8 @@ bool Scripts::cmdFallToMap(ParamsIterator &params) {
}
bool Scripts::cmdDisplayMain(ParamsIterator &params) {
+ _windowIndex = 11;
+
display(false, 0);
return true;
}
@@ -1415,7 +1443,7 @@ bool Scripts::cmdCutsceneEndDarkside(ParamsIterator &params) {
Party &party = *_vm->_party;
_vm->_saves->_wonDarkSide = true;
party._questItems[53] = 1;
- party._darkSideEnd = true;
+ party._darkSideCompleted = true;
party._mazeId = 29;
party._mazeDirection = DIR_NORTH;
party._mazePosition = Common::Point(25, 21);
@@ -1436,24 +1464,55 @@ bool Scripts::cmdCutsceneEndWorld(ParamsIterator &params) {
g_vm->saveSettings();
_vm->_saves->_wonWorld = true;
- _vm->_party->_worldEnd = true;
+ _vm->_party->_worldCompleted = true;
doWorldEnding();
return false;
}
bool Scripts::cmdFlipWorld(ParamsIterator &params) {
- _vm->_map->_loadDarkSide = params.readByte() != 0;
+ _vm->_map->_loadCcNum = params.readByte();
+ return true;
+}
+
+bool Scripts::cmdPlayCD(ParamsIterator &params) {
+ int trackNum = params.readByte();
+ int start = params.readUint16LE();
+ int finish = params.readUint16LE();
+ debugC(3, kDebugScripts, "cmdPlayCD Track=%d start=%d finish=%d", trackNum, start, finish);
+
+ if (_vm->_files->_ccNum && trackNum < 31)
+ trackNum += 30;
+ assert(trackNum <= 60);
+
+ start = convertCDTime(start);
+ finish = convertCDTime(finish);
+
+ g_system->getAudioCDManager()->play(trackNum, 1, start, finish - start, false, Audio::Mixer::kSpeechSoundType);
return true;
}
-bool Scripts::cmdPlayCD(ParamsIterator &params) { error("TODO"); }
+#define CD_FRAME_RATE 75
+uint Scripts::convertCDTime(uint srcTime) {
+ // Times are encoded as MMSSCC - MM=Minutes, SS=Seconds, CC=Centiseconds (1/100th second)
+ uint mins = srcTime / 10000;
+ uint csec = srcTime % 10000;
+ return (mins * 6000 + csec) * CD_FRAME_RATE / 100;
+}
void Scripts::doCloudsEnding() {
+ g_vm->_party->_cloudsCompleted = true;
doEnding("ENDGAME");
+
+ g_vm->_mode = MODE_INTERACTIVE;
+ g_vm->_saves->saveGame();
+
+ g_vm->_gameMode = GMODE_MENU;
+ g_vm->_mode = MODE_STARTUP;
}
void Scripts::doDarkSideEnding() {
+ g_vm->_party->_darkSideCompleted = true;
doEnding("ENDGAME2");
}
@@ -1487,56 +1546,56 @@ void Scripts::doEnding(const Common::String &endStr) {
bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
FileManager &files = *_vm->_files;
Party &party = *_vm->_party;
- Character &ps = party._activeParty[charIndex];
+ Character *ps = (charIndex == -1) ? nullptr : &party._activeParty[charIndex];
uint v = 0;
switch (action) {
case 3:
// Player sex
- v = (uint)ps._sex;
+ v = (uint)ps->_sex;
break;
case 4:
// Player race
- v = (uint)ps._race;
+ v = (uint)ps->_race;
break;
case 5:
// Player class
- v = (uint)ps._class;
+ v = (uint)ps->_class;
break;
case 8:
// Current health points
- v = (uint)ps._currentHp;
+ v = (uint)ps->_currentHp;
break;
case 9:
// Current spell points
- v = (uint)ps._currentSp;
+ v = (uint)ps->_currentSp;
break;
case 10:
// Get armor class
- v = (uint)ps.getArmorClass(false);
+ v = (uint)ps->getArmorClass(false);
break;
case 11:
// Level bonus (extra beyond base)
- v = ps._level._temporary;
+ v = ps->_level._temporary;
break;
case 12:
// Current age, including unnatural aging
- v = ps.getAge(false);
+ v = ps->getAge(false);
break;
case 13:
assert(val < 18);
- if (ps._skills[val])
+ if (ps->_skills[val])
v = val;
break;
case 15:
// Award
assert(val < AWARDS_TOTAL);
- if (ps.hasAward(val))
+ if (ps->hasAward(val))
v = val;
break;
case 16:
// Experience
- v = ps._experience;
+ v = ps->_experience;
break;
case 17:
// Party poison resistence
@@ -1544,38 +1603,19 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
break;
case 18:
// Condition
- assert(val < 16);
- if (!ps._conditions[val] && !(val & 0x10))
- v = val;
+ assert(val <= NO_CONDITION);
+ v = (ps->_conditions[val] || val == NO_CONDITION) ? val : 0xffffffff;
break;
case 19: {
// Can player cast a given spell
-
- // Get the type of character
- int category;
- switch (ps._class) {
- case CLASS_KNIGHT:
- case CLASS_ARCHER:
- category = 0;
- break;
- case CLASS_PALADIN:
- case CLASS_CLERIC:
- category = 1;
- break;
- case CLASS_BARBARIAN:
- case CLASS_DRUID:
- category = 2;
- break;
- default:
- category = 0;
- break;
- }
+ SpellsCategory category = ps->getSpellsCategory();
+ assert(category != SPELLCAT_INVALID);
// Check if the character class can cast the particular spell
- for (int idx = 0; idx < 39; ++idx) {
+ for (int idx = 0; idx < SPELLS_PER_CLASS; ++idx) {
if (Res.SPELLS_ALLOWED[category][idx] == (int)val) {
// Can cast it. Check if the player has it in their spellbook
- if (ps._spells[idx])
+ if (ps->_spells[idx])
v = val;
break;
}
@@ -1583,42 +1623,44 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
break;
}
case 20:
- if (files._isDarkCc)
+ assert(val < 256);
+ if (files._ccNum && _vm->getGameID() != GType_Swords)
val += 256;
- assert(val < 512);
v = party._gameFlags[val / 256][val % 256] ? val : 0xffffffff;
break;
- case 21:
+ case 21: {
// Scans inventories for given item number
+ uint itemOffset = _vm->getGameID() == GType_Swords ? 6 : 0;
v = 0xFFFFFFFF;
- if (val < 82) {
- for (int idx = 0; idx < 9; ++idx) {
- if (val == 35) {
- if (ps._weapons[idx]._id == val) {
+ if (val < (82 + itemOffset)) {
+ for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
+ if (val < (35 + itemOffset)) {
+ if (ps->_weapons[idx]._id == val) {
v = val;
break;
}
- } else if (val < 49) {
- if (ps._armor[idx]._id == (val - 35)) {
+ } else if (val < (49 + itemOffset)) {
+ if (ps->_armor[idx]._id == (val - 35)) {
v = val;
break;
}
- } else if (val < 60) {
- if (ps._accessories[idx]._id == (val - 49)) {
+ } else if (val < (60 + itemOffset)) {
+ if (ps->_accessories[idx]._id == (val - (49 + itemOffset))) {
v = val;
break;
}
} else {
- if (ps._misc[idx]._id == (val - 60)) {
+ if (ps->_misc[idx]._id == (val - (60 + itemOffset))) {
v = val;
break;
}
}
}
- } else if (party._questItems[val - 82]) {
+ } else if (party._questItems[val - (82 + itemOffset)]) {
v = val;
}
break;
+ }
case 25:
// Returns number of minutes elapsed in the day (0-1440)
v = party._minutes;
@@ -1632,32 +1674,32 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
v = party._gems;
break;
case 37:
- // Might bonus (extra beond base)
- v = ps._might._temporary;
+ // Might bonus (extra beyond base)
+ v = ps->_might._temporary;
break;
case 38:
// Intellect bonus (extra beyond base)
- v = ps._intellect._temporary;
+ v = ps->_intellect._temporary;
break;
case 39:
// Personality bonus (extra beyond base)
- v = ps._personality._temporary;
+ v = ps->_personality._temporary;
break;
case 40:
// Endurance bonus (extra beyond base)
- v = ps._endurance._temporary;
+ v = ps->_endurance._temporary;
break;
case 41:
// Speed bonus (extra beyond base)
- v = ps._speed._temporary;
+ v = ps->_speed._temporary;
break;
case 42:
// Accuracy bonus (extra beyond base)
- v = ps._accuracy._temporary;
+ v = ps->_accuracy._temporary;
break;
case 43:
// Luck bonus (extra beyond base)
- v = ps._luck._temporary;
+ v = ps->_luck._temporary;
break;
case 44:
v = YesNo::show(_vm, val);
@@ -1665,83 +1707,83 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
break;
case 45:
// Might base (before bonus)
- v = ps._might._permanent;
+ v = ps->_might._permanent;
break;
case 46:
// Intellect base (before bonus)
- v = ps._intellect._permanent;
+ v = ps->_intellect._permanent;
break;
case 47:
// Personality base (before bonus)
- v = ps._personality._permanent;
+ v = ps->_personality._permanent;
break;
case 48:
// Endurance base (before bonus)
- v = ps._endurance._permanent;
+ v = ps->_endurance._permanent;
break;
case 49:
// Speed base (before bonus)
- v = ps._speed._permanent;
+ v = ps->_speed._permanent;
break;
case 50:
// Accuracy base (before bonus)
- v = ps._accuracy._permanent;
+ v = ps->_accuracy._permanent;
break;
case 51:
// Luck base (before bonus)
- v = ps._luck._permanent;
+ v = ps->_luck._permanent;
break;
case 52:
// Fire resistence (before bonus)
- v = ps._fireResistence._permanent;
+ v = ps->_fireResistence._permanent;
break;
case 53:
// Elecricity resistence (before bonus)
- v = ps._electricityResistence._permanent;
+ v = ps->_electricityResistence._permanent;
break;
case 54:
// Cold resistence (before bonus)
- v = ps._coldResistence._permanent;
+ v = ps->_coldResistence._permanent;
break;
case 55:
// Poison resistence (before bonus)
- v = ps._poisonResistence._permanent;
+ v = ps->_poisonResistence._permanent;
break;
case 56:
// Energy reistence (before bonus)
- v = ps._energyResistence._permanent;
+ v = ps->_energyResistence._permanent;
break;
case 57:
// Energy resistence (before bonus)
- v = ps._magicResistence._permanent;
+ v = ps->_magicResistence._permanent;
break;
case 58:
// Fire resistence (extra beyond base)
- v = ps._fireResistence._temporary;
+ v = ps->_fireResistence._temporary;
break;
case 59:
// Electricity resistence (extra beyond base)
- v = ps._electricityResistence._temporary;
+ v = ps->_electricityResistence._temporary;
break;
case 60:
// Cold resistence (extra beyond base)
- v = ps._coldResistence._temporary;
+ v = ps->_coldResistence._temporary;
break;
case 61:
// Poison resistence (extra beyod base)
- v = ps._poisonResistence._temporary;
+ v = ps->_poisonResistence._temporary;
break;
case 62:
// Energy resistence (extra beyond base)
- v = ps._energyResistence._temporary;
+ v = ps->_energyResistence._temporary;
break;
case 63:
// Magic resistence (extra beyond base)
- v = ps._magicResistence._temporary;
+ v = ps->_magicResistence._temporary;
break;
case 64:
// Level (before bonus)
- v = ps._level._permanent;
+ v = ps->_level._permanent;
break;
case 65:
// Total party food
@@ -1772,19 +1814,19 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
break;
case 77:
// Armor class (extra beyond base)
- v = ps._ACTemp;
+ v = ps->_ACTemp;
break;
case 78:
- // Test whether current Hp is equal to or exceeds the max HP
- v = ps._currentHp >= ps.getMaxHP() ? 1 : 0;
+ // Test whether current Hp exceeds max HP or not
+ v = ps->_currentHp <= ps->getMaxHP() ? 1 : 0;
break;
case 79:
// Test for Wizard Eye being active
v = party._wizardEyeActive ? 1 : 0;
break;
case 81:
- // Test whether current Sp is equal to or exceeds the max SP
- v = ps._currentSp >= ps.getMaxSP() ? 1 : 0;
+ // Test whether current Sp exceeds the max SP or not
+ v = ps->_currentSp <= ps->getMaxSP() ? 1 : 0;
break;
case 84:
// Current facing direction
@@ -1802,7 +1844,7 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
case 91:
case 92:
// Get a player stat
- v = ps.getStat((Attribute)(action - 86), 0);
+ v = ps->getStat((Attribute)(action - 86), 0);
break;
case 93:
// Current day of the week (10 days per week)
@@ -1818,7 +1860,7 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
break;
case 102:
// Thievery skill
- v = ps.getThievery();
+ v = ps->getThievery();
break;
case 103:
// Get value of world flag
@@ -1826,7 +1868,7 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
break;
case 104:
// Get value of quest flag
- v = party._questFlags[files._isDarkCc][val] ? val : 0xffffffff;
+ v = party._questFlags[(_vm->getGameID() == GType_Swords ? 0 : files._ccNum * 30) + val] ? val : 0xffffffff;
break;
case 105:
// Test number of Megacredits in party. Only used by King's Engineer in Castle Burlock
@@ -1834,7 +1876,7 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) {
break;
case 107:
// Get value of character flag
- error("Unused");
+ v = party._characterFlags[ps->_rosterId][val] ? val : 0xffffffff;
break;
default:
break;
@@ -1857,8 +1899,8 @@ bool Scripts::copyProtectionCheck() {
if (!ConfMan.getBool("copy_protection"))
return true;
- // Currently not implemented
- return true;
+ // Show the copy protection dialog
+ return CopyProtection::show(_vm);
}
void Scripts::display(bool justifyFlag, int var46) {
diff --git a/engines/xeen/scripts.h b/engines/xeen/scripts.h
index 40564f3dda..89b6bda250 100644
--- a/engines/xeen/scripts.h
+++ b/engines/xeen/scripts.h
@@ -220,7 +220,6 @@ private:
MazeEvent *_event;
Common::Point _currentPos;
Common::Stack<StackEntry> _stack;
- Common::String _message;
Common::String _displayMessage;
typedef EventParameters::Iterator ParamsIterator;
@@ -279,7 +278,7 @@ private:
* Moves the position of an object
*/
bool cmdMoveObj(ParamsIterator &params);
-
+
/**
* Take or give amounts from various character or party figures
*/
@@ -320,13 +319,13 @@ private:
* Gives up to three different item/amounts to various character and/or party properties
*/
bool cmdGiveMulti(ParamsIterator &params);
-
+
/**
* Prompts the user to enter a word for passwords or mirror
* teleport destinations
*/
bool cmdConfirmWord(ParamsIterator &params);
-
+
/**
* Deals damage to a character
*/
@@ -545,6 +544,11 @@ private:
* Displays a message
*/
void display(bool justifyFlag, int var46);
+
+ /**
+ * Convert a CD time from the World of Xeen playCD opcodes to ScummVM CD frame number (which is at 75Hz)
+ */
+ uint convertCDTime(uint srcTime);
public:
int _animCounter;
bool _eventSkipped;
@@ -552,6 +556,7 @@ public:
DamageType _nEdamageType;
int _itemType;
Common::Array<MirrorEntry> _mirror;
+ Common::String _message;
public:
Scripts(XeenEngine *vm);
@@ -563,8 +568,9 @@ public:
/**
* Handles opening grates
+ * @returns If true, no further event checking should be done
*/
- void openGrate(int wallVal, int action);
+ bool openGrate(int wallVal, int action);
};
} // End of namespace Xeen
diff --git a/engines/xeen/sound.cpp b/engines/xeen/sound.cpp
index be15028f42..ae70c1f5d8 100644
--- a/engines/xeen/sound.cpp
+++ b/engines/xeen/sound.cpp
@@ -29,7 +29,8 @@
namespace Xeen {
Sound::Sound(Audio::Mixer *mixer) : _mixer(mixer), _fxOn(true), _musicOn(true), _subtitles(false),
- _songData(nullptr), _effectsData(nullptr), _musicSide(0), _musicPercent(100) {
+ _songData(nullptr), _effectsData(nullptr), _musicSide(0), _musicPercent(100),
+ _musicVolume(0), _sfxVolume(0) {
_SoundDriver = new AdlibSoundDriver();
}
@@ -106,44 +107,32 @@ void Sound::setFxOn(bool isOn) {
g_vm->syncSoundSettings();
}
-void Sound::updateSoundSettings() {
- _fxOn = !ConfMan.getBool("sfx_mute");
- if (!_fxOn)
- stopFX();
-
- _musicOn = !ConfMan.getBool("music_mute");
- if (!_musicOn)
- stopSong();
-
- _subtitles = ConfMan.hasKey("subtitles") ? ConfMan.getBool("subtitles") : true;
-}
-
void Sound::loadEffectsData() {
// Stop any prior FX
stopFX();
- delete[] _effectsData;
-
- // Load in an entire driver so we have quick access to the effects data
- // that's hardcoded within it
- File file("blastmus");
- byte *effectsData = new byte[file.size()];
- file.seek(0);
- file.read(effectsData, file.size());
- file.close();
- _effectsData = effectsData;
-
- // Locate the playFX routine
- const byte *fx = effectsData + READ_LE_UINT16(effectsData + 10) + 12;
- assert(READ_BE_UINT16(fx + 28) == 0x81FB);
- uint numEffects = READ_LE_UINT16(fx + 30);
- assert(READ_BE_UINT16(fx + 36) == 0x8B87);
- const byte *table = effectsData + READ_LE_UINT16(fx + 38);
-
- // Extract the effects offsets
- _effectsOffsets.resize(numEffects);
- for (uint idx = 0; idx < numEffects; ++idx)
- _effectsOffsets[idx] = READ_LE_UINT16(&table[idx * 2]);
+ if (!_effectsData) {
+ // Load in an entire driver so we have quick access to the effects data that's hardcoded within it
+ File file("blastmus");
+ byte *effectsData = new byte[file.size()];
+ file.seek(0);
+ file.read(effectsData, file.size());
+ file.close();
+ _effectsData = effectsData;
+
+ // Locate the playFX routine
+ const byte *fx = effectsData + READ_LE_UINT16(effectsData + 10) + 12;
+ assert(READ_BE_UINT16(fx + 28) == 0x81FB);
+ uint numEffects = READ_LE_UINT16(fx + 30);
+
+ assert(READ_BE_UINT16(fx + 36) == 0x8B87);
+ const byte *table = effectsData + READ_LE_UINT16(fx + 38);
+
+ // Extract the effects offsets
+ _effectsOffsets.resize(numEffects);
+ for (uint idx = 0; idx < numEffects; ++idx)
+ _effectsOffsets[idx] = READ_LE_UINT16(&table[idx * 2]);
+ }
}
void Sound::playFX(uint effectId) {
@@ -160,8 +149,8 @@ void Sound::stopFX() {
_SoundDriver->stopFX();
}
-int Sound::songCommand(uint commandId, byte volume) {
- int result = _SoundDriver->songCommand(commandId, volume);
+int Sound::songCommand(uint commandId, byte musicVolume, byte sfxVolume) {
+ int result = _SoundDriver->songCommand(commandId, musicVolume, sfxVolume);
if (commandId == STOP_SONG) {
delete[] _songData;
_songData = nullptr;
@@ -212,8 +201,26 @@ void Sound::setMusicPercent(byte percent) {
assert(percent <= 100);
_musicPercent = percent;
- songCommand(SET_VOLUME, (int)percent * 127 / 100);
+ updateVolume();
}
+void Sound::updateSoundSettings() {
+ _fxOn = !ConfMan.getBool("sfx_mute");
+ if (!_fxOn)
+ stopFX();
+
+ _musicOn = !ConfMan.getBool("music_mute");
+ if (!_musicOn)
+ stopSong();
+
+ _subtitles = ConfMan.hasKey("subtitles") ? ConfMan.getBool("subtitles") : true;
+ _musicVolume = CLIP(ConfMan.getInt("music_volume"), 0, 255);
+ _sfxVolume = CLIP(ConfMan.getInt("sfx_volume"), 0, 255);
+ updateVolume();
+}
+
+void Sound::updateVolume() {
+ songCommand(SET_VOLUME, _musicPercent * _musicVolume / 100, _sfxVolume);
+}
} // End of namespace Xeen
diff --git a/engines/xeen/sound.h b/engines/xeen/sound.h
index 86303f682f..613299c6dc 100644
--- a/engines/xeen/sound.h
+++ b/engines/xeen/sound.h
@@ -40,6 +40,7 @@ private:
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
byte _musicPercent;
+ int _musicVolume, _sfxVolume;
private:
/**
* Loads effects data that was embedded in the music driver
@@ -50,6 +51,11 @@ private:
* Updates any playing music
*/
void update();
+
+ /**
+ * Updates the music and sound effects playing volume
+ */
+ void updateVolume();
public:
bool _fxOn;
bool _musicOn;
@@ -73,7 +79,7 @@ public:
/**
* Executes special music command
*/
- int songCommand(uint commandId, byte volume = 0);
+ int songCommand(uint commandId, byte musicVolume = 0, byte sfxVolume = 0);
/**
* Stops any currently playing music
diff --git a/engines/xeen/sound_driver.cpp b/engines/xeen/sound_driver.cpp
index e79fcdd501..967f53ac49 100644
--- a/engines/xeen/sound_driver.cpp
+++ b/engines/xeen/sound_driver.cpp
@@ -225,7 +225,7 @@ void SoundDriver::playSong(const byte *data) {
debugC(1, kDebugSound, "Starting song");
}
-int SoundDriver::songCommand(uint commandId, byte volume) {
+int SoundDriver::songCommand(uint commandId, byte musicVolume, byte sfxVolume) {
if (commandId == STOP_SONG) {
_musicPlaying = false;
} else if (commandId == RESTART_SONG) {
@@ -262,7 +262,7 @@ const CommandFn SoundDriver::FX_COMMANDS[16] = {
/*------------------------------------------------------------------------*/
AdlibSoundDriver::AdlibSoundDriver() : _field180(0), _field181(0), _field182(0),
- _volume(127) {
+ _musicVolume(0), _sfxVolume(0) {
Common::fill(&_musInstrumentPtrs[0], &_musInstrumentPtrs[16], (const byte *)nullptr);
Common::fill(&_fxInstrumentPtrs[0], &_fxInstrumentPtrs[16], (const byte *)nullptr);
@@ -304,9 +304,9 @@ void AdlibSoundDriver::playSong(const byte *data) {
resetFrequencies();
}
-int AdlibSoundDriver::songCommand(uint commandId, byte volume) {
+int AdlibSoundDriver::songCommand(uint commandId, byte musicVolume, byte sfxVolume) {
Common::StackLock slock(_driverMutex);
- SoundDriver::songCommand(commandId, volume);
+ SoundDriver::songCommand(commandId, musicVolume, sfxVolume);
if (commandId == STOP_SONG) {
_field180 = 0;
@@ -320,7 +320,8 @@ int AdlibSoundDriver::songCommand(uint commandId, byte volume) {
_field182 = 63;
}
} else if (commandId == SET_VOLUME) {
- _volume = volume;
+ _musicVolume = musicVolume;
+ _sfxVolume = sfxVolume;
} else if (commandId == GET_STATUS) {
return _field180;
}
@@ -428,7 +429,7 @@ void AdlibSoundDriver::setOutputLevel(byte channelNum, uint level) {
(_channels[channelNum]._scalingValue & 0xC0));
}
-void AdlibSoundDriver::playInstrument(byte channelNum, const byte *data) {
+void AdlibSoundDriver::playInstrument(byte channelNum, const byte *data, byte volume) {
byte op1 = OPERATOR1_INDEXES[channelNum];
byte op2 = OPERATOR2_INDEXES[channelNum];
debugC(2, kDebugSound, "---START-playInstrument - %d", channelNum);
@@ -441,7 +442,7 @@ void AdlibSoundDriver::playInstrument(byte channelNum, const byte *data) {
int scalingVal = *data++;
_channels[channelNum]._scalingValue = scalingVal;
- scalingVal += (127 - _volume) / 2;
+ scalingVal += (127 - volume) / 2;
if (scalingVal > 63) {
scalingVal = 63;
@@ -535,7 +536,7 @@ bool AdlibSoundDriver::musPlayInstrument(const byte *&srcP, byte param) {
debugC(3, kDebugSound, "musPlayInstrument %d, %d", param, instrument);
if (param < 7)
- playInstrument(param, _musInstrumentPtrs[instrument]);
+ playInstrument(param, _musInstrumentPtrs[instrument], _musicVolume);
return false;
}
@@ -633,7 +634,7 @@ bool AdlibSoundDriver::fxPlayInstrument(const byte *&srcP, byte param) {
debugC(3, kDebugSound, "fxPlayInstrument %d, %d", param, instrument);
if (!_exclude7 || param != 7)
- playInstrument(param, _fxInstrumentPtrs[instrument]);
+ playInstrument(param, _fxInstrumentPtrs[instrument], _sfxVolume);
return false;
}
diff --git a/engines/xeen/sound_driver.h b/engines/xeen/sound_driver.h
index c78408b047..d4edd49c05 100644
--- a/engines/xeen/sound_driver.h
+++ b/engines/xeen/sound_driver.h
@@ -40,8 +40,7 @@ namespace OPL {
namespace Xeen {
enum MusicCommand {
- STOP_SONG = 0, RESTART_SONG = 1, SET_VOLUME = 0x100,
- GET_STATUS = 0xFFE0
+ STOP_SONG = 0, RESTART_SONG = 1, SET_VOLUME = 0x100, GET_STATUS = 0xFFE0
};
class SoundDriver;
@@ -170,7 +169,7 @@ public:
/**
* Executes special music command
*/
- virtual int songCommand(uint commandId, byte volume = 0);
+ virtual int songCommand(uint commandId, byte musicVolume = 0, byte sfxVolume = 0);
/**
* Returns whether music is currently playing
@@ -200,7 +199,7 @@ private:
int _field180;
int _field181;
int _field182;
- int _volume;
+ int _musicVolume, _sfxVolume;
private:
/**
* Initializes the state of the Adlib OPL driver
@@ -246,7 +245,7 @@ private:
/**
* Starts playing an instrument
*/
- void playInstrument(byte channelNum, const byte *data);
+ void playInstrument(byte channelNum, const byte *data, byte volume);
protected:
virtual bool musSetInstrument(const byte *&srcP, byte param);
virtual bool musSetPitchWheel(const byte *&srcP, byte param);
@@ -301,7 +300,7 @@ public:
/**
* Executes special music command
*/
- virtual int songCommand(uint commandId, byte volume = 0);
+ virtual int songCommand(uint commandId, byte musicVolume = 0, byte sfxVolume = 0);
};
} // End of namespace Xeen
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 9ba581249b..04d77e1f66 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -93,47 +93,49 @@ void Spells::spellFailed() {
}
void Spells::castItemSpell(int itemSpellId) {
+ assert(itemSpellId != 0);
+
switch (itemSpellId) {
- case 15:
+ case 16:
if (_vm->_mode == MODE_COMBAT) {
NotWhileEngaged::show(_vm, MS_Jump);
return;
}
break;
- case 20:
+ case 21:
if (_vm->_mode == MODE_COMBAT) {
NotWhileEngaged::show(_vm, MS_WizardEye);
return;
}
break;
- case 27:
+ case 28:
if (_vm->_mode == MODE_COMBAT) {
NotWhileEngaged::show(_vm, MS_LloydsBeacon);
return;
}
break;
- case 32:
+ case 33:
frostbite2();
break;
- case 41:
+ case 42:
if (_vm->_mode == MODE_COMBAT) {
NotWhileEngaged::show(_vm, MS_Teleport);
return;
}
break;
- case 47:
+ case 48:
if (_vm->_mode == MODE_COMBAT) {
NotWhileEngaged::show(_vm, MS_SuperShelter);
return;
}
break;
- case 54:
+ case 55:
if (_vm->_mode == MODE_COMBAT) {
NotWhileEngaged::show(_vm, MS_TownPortal);
return;
}
break;
- case 57:
+ case 58:
if (_vm->_mode == MODE_COMBAT) {
NotWhileEngaged::show(_vm, MS_Etheralize);
return;
@@ -143,8 +145,8 @@ void Spells::castItemSpell(int itemSpellId) {
break;
}
- static const MagicSpell spells[73] = {
- MS_Light, MS_Awaken, MS_MagicArrow, MS_FirstAid, MS_FlyingFist,
+ static const MagicSpell spells[74] = {
+ NO_SPELL, MS_Light, MS_Awaken, MS_MagicArrow, MS_FirstAid, MS_FlyingFist,
MS_EnergyBlast, MS_Sleep, MS_Revitalize, MS_CureWounds, MS_Sparks,
MS_Shrapmetal, MS_InsectSpray, MS_ToxicCloud, MS_ProtFromElements, MS_Pain,
MS_Jump, MS_BeastMaster, MS_Clairvoyance, MS_TurnUndead, MS_Levitate,
@@ -426,52 +428,7 @@ void Spells::deadlySwarm() {
}
void Spells::detectMonster() {
- EventsManager &events = *_vm->_events;
- Interface &intf = *_vm->_interface;
- Map &map = *_vm->_map;
- Party &party = *_vm->_party;
- Sound &sound = *_vm->_sound;
- Windows &windows = *_vm->_windows;
- Window &w = windows[19];
- bool isDarkCc = _vm->_files->_isDarkCc;
- int grid[7][7];
-
- SpriteResource sprites(isDarkCc ? "detectmn.icn" : "detctmon.icn");
- Common::fill(&grid[0][0], &grid[6][6], 0);
-
- w.open();
- w.writeString(Res.DETECT_MONSTERS);
- sprites.draw(w, 0, Common::Point(243, 80));
-
- for (int yDiff = 3; yDiff >= -3; --yDiff) {
- for (int xDiff = -3; xDiff <= 3; ++xDiff) {
- for (uint monIndex = 0; monIndex < map._mobData._monsters.size(); ++monIndex) {
- MazeMonster &monster = map._mobData._monsters[monIndex];
- Common::Point pt = party._mazePosition + Common::Point(xDiff, yDiff);
- if (monster._position == pt) {
- int &gridEntry = grid[yDiff + 3][xDiff + 3];
- if (++gridEntry > 3)
- gridEntry = 3;
-
- sprites.draw(w, gridEntry, Common::Point(xDiff * 9 + 244,
- yDiff * 7 + 81));
- }
- }
- }
- }
-
- sprites.draw(w, party._mazeDirection + 1, Common::Point(270, 101));
- sound.playFX(20);
- w.update();
-
- do {
- events.updateGameCounter();
- intf.draw3d(true);
-
- events.wait(1, false);
- } while (!events.isKeyMousePressed());
-
- w.close();
+ DetectMonsters::show(_vm);
}
void Spells::divineIntervention() {
@@ -520,8 +477,8 @@ void Spells::elementalStorm() {
combat._monsterDamage = 150;
combat._damageType = (DamageType)_vm->getRandomNumber(DT_FIRE, DT_POISON);
combat._rangeType = RT_ALL;
- sound.playFX(STORM_FX_LIST[combat._damageType]);
- combat.rangedAttack(STORM_MA_LIST[combat._damageType]);
+ sound.playFX(STORM_FX_LIST[combat._damageType - DT_FIRE]);
+ combat.rangedAttack(STORM_MA_LIST[combat._damageType - DT_FIRE]);
}
void Spells::enchantItem() {
@@ -1148,7 +1105,7 @@ void Spells::superShelter() {
spellFailed();
} else {
Mode oldMode = _vm->_mode;
- _vm->_mode = MODE_12;
+ _vm->_mode = MODE_INTERACTIVE2;
sound.playFX(30);
intf.rest();
_vm->_mode = oldMode;
@@ -1246,11 +1203,16 @@ void Spells::townPortal() {
return;
sound.playFX(51);
- map._loadDarkSide = map._sideTownPortal;
- _vm->_files->_isDarkCc = map._sideTownPortal > 0;
- map.load(Res.TOWN_MAP_NUMBERS[map._sideTownPortal][townNumber - 1]);
+ map._loadCcNum = map._sideTownPortal;
+ _vm->_files->_ccNum = map._sideTownPortal > 0;
+
+ int arrIndex = _vm->getGameID() == GType_Swords ? 2 : map._sideTownPortal;
+ map.load(Res.TOWN_MAP_NUMBERS[arrIndex][townNumber - 1]);
- if (!_vm->_files->_isDarkCc) {
+ if (_vm->getGameID() == GType_Swords) {
+ party._mazePosition = Common::Point(8, 3);
+ party._mazeDirection = DIR_NORTH;
+ } else if (!_vm->_files->_ccNum) {
party.moveToRunLocation();
} else {
switch (townNumber) {
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index a333ea2f5f..24e9dd1f57 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -56,7 +56,7 @@ enum MagicSpell {
MS_SuppressDisease = 67, MS_SuppressPoison = 68, MS_Teleport = 69,
MS_TimeDistortion = 70, MS_TownPortal = 71, MS_ToxicCloud = 72,
MS_TurnUndead = 73, MS_WalkOnWater = 74, MS_WizardEye = 75,
- NO_SPELL = 76
+ NO_SPELL = 76, TOTAL_SPELLS = 76
};
class Spells {
diff --git a/engines/xeen/sprites.cpp b/engines/xeen/sprites.cpp
index 4811f10628..7b484b53e3 100644
--- a/engines/xeen/sprites.cpp
+++ b/engines/xeen/sprites.cpp
@@ -146,6 +146,9 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
dest.create(xOffset + width, yOffset + height);
bounds = Common::Rect(0, 0, dest.w, dest.h);
}
+ if (flags & SPRFLAG_SCENE_CLIPPED) {
+ bounds.clip(Common::Rect(8, 8, 223, 141));
+ }
uint16 scaleMaskXCopy = scaleMaskX;
Common::Rect drawBounds;
@@ -281,17 +284,23 @@ void SpriteResource::drawOffset(XSurface &dest, uint16 offset, const Common::Poi
if (bit) {
// Check whether there's a pixel to write, and we're within the allowable bounds. Note that for
// the SPRFLAG_SCENE_CLIPPED or when enlarging, we also have an extra horizontal bounds check
- if (*lineP != -1 && xp >= bounds.left && xp < bounds.right &&
- ((!(flags & SPRFLAG_SCENE_CLIPPED) && !enlarge) || (xp >= SCENE_CLIP_LEFT && xp < SCENE_CLIP_RIGHT))) {
+ if (*lineP != -1 && xp >= bounds.left && xp < bounds.right) {
drawBounds.left = MIN(drawBounds.left, xp);
drawBounds.right = MAX((int)drawBounds.right, xp + 1);
*destP = (byte)*lineP;
- if (enlarge)
+ if (enlarge) {
*(destP + SCREEN_WIDTH) = (byte)*lineP;
+ *(destP + 1) = (byte)*lineP;
+ *(destP + 1 + SCREEN_WIDTH) = (byte)*lineP;
+ }
}
- ++destP;
++xp;
+ ++destP;
+ if (enlarge) {
+ ++destP;
+ ++xp;
+ }
}
}
diff --git a/engines/xeen/subtitles.cpp b/engines/xeen/subtitles.cpp
index 86dff2dac8..168ed1d4ea 100644
--- a/engines/xeen/subtitles.cpp
+++ b/engines/xeen/subtitles.cpp
@@ -40,7 +40,7 @@ Subtitles::~Subtitles() {
void Subtitles::loadSubtitles() {
File f("special.bin");
- if (!g_vm->_files->_isDarkCc) {
+ if (!g_vm->_files->_ccNum) {
// The first subtitle line contains all the text for the Clouds intro. Since ScummVM allows
// both voice and subtitles at the same time, unlike the original, we need to split up the
// first subtitle into separate lines to allow them to better interleave with the voice
diff --git a/engines/xeen/subtitles.h b/engines/xeen/subtitles.h
index 37148dbc92..55c5faaa26 100644
--- a/engines/xeen/subtitles.h
+++ b/engines/xeen/subtitles.h
@@ -65,7 +65,7 @@ public:
* Set which subtitle line to display
*/
void setLine(int line);
-
+
/**
* Resets subtitles, stopping any display
*/
diff --git a/engines/xeen/swordsofxeen/swordsofxeen.cpp b/engines/xeen/swordsofxeen/swordsofxeen.cpp
index bbe0a74c1c..6f3963e1d0 100644
--- a/engines/xeen/swordsofxeen/swordsofxeen.cpp
+++ b/engines/xeen/swordsofxeen/swordsofxeen.cpp
@@ -49,10 +49,10 @@ void SwordsOfXeenEngine::death() {
_sound->playSound("laff1.voc");
bool breakFlag = false;
- for (int idx = 0, idx2 = 0; idx < (_files->_isDarkCc ? 10 : 23); ++idx) {
+ for (int idx = 0, idx2 = 0; idx < (_files->_ccNum ? 10 : 23); ++idx) {
_events->updateGameCounter();
- if (_files->_isDarkCc) {
+ if (_files->_ccNum) {
breakFlag = _events->wait(2);
} else {
if (idx == 1 || idx == 11)
@@ -63,8 +63,8 @@ void SwordsOfXeenEngine::death() {
_sound->playFX(34);
}
- if ((_files->_isDarkCc ? 9 : 10) == idx) {
- if ((_files->_isDarkCc ? 2 : 1) > idx2) {
+ if ((_files->_ccNum ? 9 : 10) == idx) {
+ if ((_files->_ccNum ? 2 : 1) > idx2) {
// Restart loop
idx = -1;
++idx2;
@@ -82,12 +82,44 @@ void SwordsOfXeenEngine::death() {
_sound->stopAllAudio();
}
+bool SwordsOfXeenEngine::showEnding() {
+ Windows &windows = *_windows;
+ SpriteResource win("win.int");
+
+ _screen->loadBackground("blank.raw");
+ windows[28].setBounds(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ _screen->fadeIn(0x81);
+ _screen->loadPalette("scr.pal");
+ _screen->fadeIn(0x81);
+
+ win.draw(0, 0, Common::Point(0, 0));
+ win.draw(0, 1, Common::Point(160, 0));
+ _sound->playSound("ch1.voc");
+ _events->waitForPress();
+
+ _screen->fadeOut();
+ _screen->loadBackground("blank.raw");
+ return true;
+}
+
void SwordsOfXeenEngine::dream() {
// Swords of Xeen doesn't have any dreams
}
void SwordsOfXeenEngine::showCutscene(const Common::String &name, int status, uint score) {
+ _sound->stopAllAudio();
+ _events->clearEvents();
+
+ if (name != "ENDGAME")
+ error("Unknown cutscene specified");
+
+ showEnding();
+
+ _screen->freePages();
+ _sound->stopAllAudio();
+ _events->clearEvents();
_gameMode = GMODE_MENU;
+
}
} // End of namespace SwordsOfXeen
diff --git a/engines/xeen/swordsofxeen/swordsofxeen.h b/engines/xeen/swordsofxeen/swordsofxeen.h
index d301423287..b19f4e1d53 100644
--- a/engines/xeen/swordsofxeen/swordsofxeen.h
+++ b/engines/xeen/swordsofxeen/swordsofxeen.h
@@ -34,6 +34,11 @@ namespace SwordsOfXeen {
* Swords of Xeen specific game code
*/
class SwordsOfXeenEngine: public XeenEngine {
+private:
+ /**
+ * Show the ending "You won" screen
+ */
+ bool showEnding();
protected:
/**
* Show the starting sequence/intro
diff --git a/engines/xeen/window.cpp b/engines/xeen/window.cpp
index 47732dc841..caa17b7563 100644
--- a/engines/xeen/window.cpp
+++ b/engines/xeen/window.cpp
@@ -41,21 +41,21 @@ Windows::Windows() {
Window windows[48] = {
Window(Common::Rect(0, 0, 320, 200), 0, 0, 0, 0, 320, 200),
Window(Common::Rect(237, 9, 317, 74), 0, 0, 237, 12, 307, 68),
- Window(Common::Rect(225, 1, 319, 73), 1, 8, 225, 1, 319, 73),
+ Window(Common::Rect(225, 1, 320, 73), 1, 8, 225, 1, 319, 73),
Window(Common::Rect(0, 0, 230, 149), 0, 0, 9, 8, 216, 140),
Window(Common::Rect(235, 148, 309, 189), 2, 8, 0, 0, 0, 0),
Window(Common::Rect(70, 20, 250, 183), 3, 8, 80, 38, 240, 166),
- Window(Common::Rect(52, 149, 268, 197), 4, 8, 0, 0, 0, 0),
+ Window(Common::Rect(52, 149, 268, 198), 4, 8, 0, 0, 0, 0),
Window(Common::Rect(108, 0, 200, 200), 5, 0, 0, 0, 0, 0),
Window(Common::Rect(232, 9, 312, 74), 0, 0, 0, 0, 0, 0),
Window(Common::Rect(103, 156, 217, 186), 6, 8, 0, 0, 0, 0),
- Window(Common::Rect(226, 0, 319, 146), 7, 8, 0, 0, 0, 0),
+ Window(Common::Rect(226, 0, 320, 146), 7, 8, 0, 0, 0, 0),
Window(Common::Rect(8, 8, 224, 140), 8, 8, 8, 8, 224, 200),
Window(Common::Rect(0, 143, 320, 199), 9, 8, 0, 0, 0, 0),
Window(Common::Rect(50, 103, 266, 139), 10, 8, 0, 0, 0, 0),
Window(Common::Rect(0, 7, 320, 138), 11, 8, 0, 0, 0, 0),
Window(Common::Rect(50, 71, 182, 129), 12, 8, 0, 0, 0, 0),
- Window(Common::Rect(228, 106, 319, 146), 13, 8, 0, 0, 0, 0),
+ Window(Common::Rect(228, 106, 320, 146), 13, 8, 0, 0, 0, 0),
Window(Common::Rect(20, 142, 290, 199), 14, 8, 0, 0, 0, 0),
Window(Common::Rect(0, 20, 320, 180), 15, 8, 0, 0, 0, 0),
Window(Common::Rect(231, 48, 317, 141), 16, 8, 0, 0, 0, 0),
@@ -74,10 +74,10 @@ Windows::Windows() {
Window(Common::Rect(12, 11, 164, 94), 0, 0, 0, 0, 52, 0),
Window(Common::Rect(8, 147, 224, 192), 0, 8, 0, 0, 0, 94),
Window(Common::Rect(232, 74, 312, 138), 29, 8, 0, 0, 0, 0),
- Window(Common::Rect(226, 26, 319, 146), 30, 8, 0, 0, 0, 0),
- Window(Common::Rect(225, 74, 319, 154), 31, 8, 0, 0, 0, 0),
+ Window(Common::Rect(226, 26, 320, 146), 30, 8, 0, 0, 0, 0),
+ Window(Common::Rect(225, 74, 320, 154), 31, 8, 0, 0, 0, 0),
Window(Common::Rect(27, 6, 195, 142), 0, 8, 0, 0, 0, 0),
- Window(Common::Rect(225, 140, 319, 199), 0, 8, 0, 0, 0, 0),
+ Window(Common::Rect(225, 140, 320, 199), 0, 8, 0, 0, 0, 0),
Window(Common::Rect(12, 8, 162, 198), 0, 0, 128, 0, 119, 0),
Window(Common::Rect(0, 0, 320, 200), 32, 8, 0, 0, 320, 190),
Window(Common::Rect(0, 0, 320, 200), 33, 8, 0, 0, 320, 200)
diff --git a/engines/xeen/worldofxeen/clouds_cutscenes.cpp b/engines/xeen/worldofxeen/clouds_cutscenes.cpp
index 0e8149e37e..2ae921cf19 100644
--- a/engines/xeen/worldofxeen/clouds_cutscenes.cpp
+++ b/engines/xeen/worldofxeen/clouds_cutscenes.cpp
@@ -21,7 +21,6 @@
*/
#include "xeen/worldofxeen/clouds_cutscenes.h"
-#include "xeen/worldofxeen/worldofxeen_resources.h"
#include "xeen/sound.h"
namespace Xeen {
@@ -40,8 +39,10 @@ bool CloudsCutscenes::showCloudsIntro() {
Screen &screen = *g_vm->_screen;
Sound &sound = *g_vm->_sound;
- bool darkCc = files._isDarkCc;
+ bool darkCc = files._ccNum;
files.setGameCc(0);
+ sound._musicSide = 0;
+ _subtitles.reset();
bool seenIntro = showCloudsTitle() && showCloudsIntroInner();
@@ -278,7 +279,7 @@ bool CloudsCutscenes::showCloudsIntroInner() {
sound.playVoice(_INTRO_VOCS[lineCtr]);
}
- for (int frameCtr = 0, lookup = 0; sound.isSoundPlaying() ||
+ for (int frameCtr = 0, lookup = 0; sound.isSoundPlaying() ||
(_subtitles.active() && (lineCtr == 0 || lineCtr == 4 || lineCtr == 10 || lineCtr == 13)); ) {
groupo.draw(0, 0);
groupo.draw(0, 1, Common::Point(160, 0));
@@ -332,7 +333,7 @@ bool CloudsCutscenes::showCloudsIntroInner() {
windows[0].writeString(Res.CLOUDS_INTRO1);
ctr5 = (ctr5 + 1) % 19;
-
+
WAIT(1);
continue;
}
@@ -379,8 +380,9 @@ void CloudsCutscenes::showCloudsEnding(uint finalScore) {
FileManager &files = *g_vm->_files;
Sound &sound = *g_vm->_sound;
- bool darkCc = files._isDarkCc;
+ bool darkCc = files._ccNum;
files.setGameCc(0);
+ _subtitles.reset();
_mirror.load("mirror.end");
_mirrBack.load("mirrback.end");
@@ -406,7 +408,7 @@ bool CloudsCutscenes::showCloudsEnding1() {
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
- files._isDarkCc = false;
+ files._ccNum = false;
files.setGameCc(0);
// Show the castle with swirling clouds and lightning
@@ -985,7 +987,7 @@ bool CloudsCutscenes::showCloudsEnding5() {
king.draw(0, 1, Common::Point(160, 0));
screen.fadeIn();
_subtitles.setLine(13);
-
+
sound.playVoice("king4.voc");
do {
king.draw(0, 0, Common::Point(0, 0));
diff --git a/engines/xeen/worldofxeen/darkside_cutscenes.cpp b/engines/xeen/worldofxeen/darkside_cutscenes.cpp
index 0e931ce9d7..c0ef2e98d7 100644
--- a/engines/xeen/worldofxeen/darkside_cutscenes.cpp
+++ b/engines/xeen/worldofxeen/darkside_cutscenes.cpp
@@ -24,7 +24,6 @@
#include "xeen/xeen.h"
#include "xeen/worldofxeen/darkside_cutscenes.h"
#include "xeen/worldofxeen/worldofxeen.h"
-#include "xeen/worldofxeen/worldofxeen_resources.h"
#define WAIT(TIME) if (_subtitles.wait(TIME)) return false
@@ -74,7 +73,8 @@ const int LEFT_CLAW_IDLE_Y[32] = {
bool DarkSideCutscenes::showDarkSideTitle(bool seenIntro) {
Screen &screen = *g_vm->_screen;
Sound &sound = *g_vm->_sound;
- g_vm->_files->_isDarkCc = true;
+ g_vm->_files->_ccNum = true;
+ _subtitles.reset();
screen.loadPalette("dark.pal");
SpriteResource nwc[4] = {
@@ -105,7 +105,7 @@ bool DarkSideCutscenes::showDarkSideTitle(bool seenIntro) {
// Render the next frame
screen.vertMerge(0);
nwc[nwcIndex].draw(0, nwcFrame);
-
+
switch (idx) {
case 17:
sound.playSound(voc[0]);
@@ -129,7 +129,7 @@ bool DarkSideCutscenes::showDarkSideTitle(bool seenIntro) {
for (int idx = 0; idx < 42 && !g_vm->shouldExit(); ++idx) {
screen.vertMerge(SCREEN_HEIGHT);
nwc[3].draw(0, idx);
-
+
switch (idx) {
case 3:
sound.playFX(40);
@@ -168,8 +168,9 @@ bool DarkSideCutscenes::showDarkSideIntro(bool seenIntro) {
Screen &screen = *g_vm->_screen;
Sound &sound = *g_vm->_sound;
- files._isDarkCc = true;
+ files._ccNum = true;
files.setGameCc(1);
+ _subtitles.reset();
if (showDarkSideTitle(seenIntro)) {
if (seenIntro) {
@@ -809,7 +810,7 @@ bool DarkSideCutscenes::showWorldOfXeenLogo() {
for (int idx = 0; idx < 21; ++idx) {
screen.restoreBackground();
wfire[6].draw(0, idx, Common::Point(0, 45));
-
+
switch (idx) {
case 0:
case 11:
@@ -837,6 +838,7 @@ void DarkSideCutscenes::showDarkSideEnding(uint endingScore) {
Sound &sound = *g_vm->_sound;
files.setGameCc(1);
+ _subtitles.reset();
sound._musicSide = 1;
screen.fadeOut();
@@ -1285,7 +1287,7 @@ bool DarkSideCutscenes::showDarkSideEnding3() {
screen.horizMerge(0);
sc16.draw(0, 0, Common::Point(7, 29));
_subtitles.show();
- sound.playSound("fail1.voc");
+ sound.playVoice("fail1.voc", 2);
for (int idx = 0; idx < 5; ++idx) {
screen.horizMerge(0);
@@ -1689,21 +1691,25 @@ void DarkSideCutscenes::showDarkSideScore(uint endingScore) {
sound.stopAllAudio();
- if (g_vm->shouldExit()) {
+ if (!g_vm->shouldExit()) {
sound.playSong("outday3.m");
Common::String str = Common::String::format(Res.DARKSIDE_ENDING1, endingScore);
showPharaohEndText(str.c_str(), Res.DARKSIDE_ENDING2);
+ g_vm->_mode = MODE_INTERACTIVE;
if (!g_vm->shouldExit())
saves.saveGame();
}
}
bool DarkSideCutscenes::showPharaohEndText(const char *msg1, const char *msg2, const char *msg3) {
+ Windows &windows = *g_vm->_windows;
_ball.load("ball.int");
_claw.load("claw.int");
_dragon1.load("dragon1.int");
+
+ windows[39].setBounds(Common::Rect(12, 8, 162, 198));
bool result = showPharaohEndTextInner(msg1, msg2, msg3);
_ball.clear();
diff --git a/engines/xeen/worldofxeen/worldofxeen.cpp b/engines/xeen/worldofxeen/worldofxeen.cpp
index 962bdfec6a..ecaae8303b 100644
--- a/engines/xeen/worldofxeen/worldofxeen.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen.cpp
@@ -71,7 +71,7 @@ void WorldOfXeenEngine::death() {
}
w.update();
- _events->wait(1);
+ _events->wait(1, false);
}
deathSprites.draw(0, 34, Common::Point(0, 0));
@@ -79,10 +79,10 @@ void WorldOfXeenEngine::death() {
w.update();
savedBg.blitFrom(*_screen);
- _sound->playSong(_files->_isDarkCc ? "laff1.voc" : "xeenlaff.voc");
+ _sound->playSound(_files->_ccNum ? "laff1.voc" : "xeenlaff.voc", _files->_ccNum, 0);
// Animation of Xeen or Alamar laughing
- for (int idx = 0, idx2 = 0; idx < (_files->_isDarkCc ? 10 : 23); ++idx) {
+ for (int idx = 0, idx2 = 0; idx < (_files->_ccNum ? 10 : 23); ++idx) {
_events->updateGameCounter();
_screen->blitFrom(savedBg);
@@ -90,18 +90,18 @@ void WorldOfXeenEngine::death() {
death1Sprites.draw(0, idx - 1);
w.update();
- if (_files->_isDarkCc) {
- _events->wait(2);
+ if (_files->_ccNum) {
+ _events->wait(2, false);
} else {
if (idx == 1 || idx == 11)
_sound->playFX(33);
- _events->wait(2);
+ _events->wait(2, false);
if (idx == 15)
_sound->playFX(34);
}
- if (idx == (_files->_isDarkCc ? 9 : 10)) {
- if (idx2 < (_files->_isDarkCc ? 2 : 1)) {
+ if (idx == (_files->_ccNum ? 9 : 10)) {
+ if (idx2 < (_files->_ccNum ? 2 : 1)) {
idx = -1;
++idx2;
}
@@ -111,6 +111,9 @@ void WorldOfXeenEngine::death() {
idx = 23;
}
+ while (_sound->isSoundPlaying())
+ _events->wait(1, false);
+
_screen->blitFrom(savedBg);
w.update();
}
@@ -131,11 +134,11 @@ void WorldOfXeenEngine::dream() {
while (!shouldExit() && _events->timeElapsed() < 7)
_events->pollEventsAndWait();
- _sound->playSound("dreams2.voc", 1);
+ _sound->playSound("dreams2.voc", 1, 0);
while (!shouldExit() && _sound->isSoundPlaying())
_events->pollEventsAndWait();
- _sound->playSound("laff1.voc", 1);
+ _sound->playSound("laff1.voc", 1, 0);
while (!shouldExit() && _sound->isSoundPlaying())
_events->pollEventsAndWait();
diff --git a/engines/xeen/worldofxeen/worldofxeen_cutscenes.cpp b/engines/xeen/worldofxeen/worldofxeen_cutscenes.cpp
index 9d35733de9..fafbb8ef8d 100644
--- a/engines/xeen/worldofxeen/worldofxeen_cutscenes.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_cutscenes.cpp
@@ -479,14 +479,14 @@ bool WorldOfXeenCutscenes::worldEnding2() {
if (idx == 2 || idx == 15 || idx == 21)
sound.playSound("photon.voc", 1, 0);
- screen.restoreBackground();
+ screen.blitFrom(savedBg);
sc24.draw(0, idx, Common::Point(103, 6));
WAIT(3);
}
for (int idx = 20; idx < 35; ++idx) {
- screen.restoreBackground();
+ screen.blitFrom(savedBg);
sc24.draw(0, idx, Common::Point(103, 6));
WAIT(3);
@@ -599,13 +599,13 @@ bool WorldOfXeenCutscenes::worldEnding3() {
SpriteResource sc30("sc30.eg2");
SpriteResource sc28[14] = {
- SpriteResource("sc28a.eg2"), SpriteResource("sc28b1.eg2"),
- SpriteResource("sc28c.eg2"), SpriteResource("sc28d.eg2"),
- SpriteResource("sc28e.eg2"), SpriteResource("sc28f.eg2"),
- SpriteResource("sc28g.eg2"), SpriteResource("sc28h.eg2"),
- SpriteResource("sc28i.eg2"), SpriteResource("sc28j.eg2"),
- SpriteResource("sc28k.eg2"), SpriteResource("sc28l.eg2"),
- SpriteResource("sc28m.eg2"), SpriteResource("sc28n.eg2"),
+ SpriteResource("sc28a.eg2", 2), SpriteResource("sc28b1.eg2", 2),
+ SpriteResource("sc28c.eg2", 2), SpriteResource("sc28d.eg2", 2),
+ SpriteResource("sc28e.eg2", 2), SpriteResource("sc28f.eg2", 2),
+ SpriteResource("sc28g.eg2", 2), SpriteResource("sc28h.eg2", 2),
+ SpriteResource("sc28i.eg2", 2), SpriteResource("sc28j.eg2", 2),
+ SpriteResource("sc28k.eg2", 2), SpriteResource("sc28l.eg2", 2),
+ SpriteResource("sc28m.eg2", 2), SpriteResource("sc28n.eg2", 2),
};
// Transformation of Xeen into a globe
@@ -652,7 +652,7 @@ bool WorldOfXeenCutscenes::worldEnding3() {
}
screen.fadeOut();
- while (sound.isMusicPlaying()) {
+ while (sound.isSoundPlaying()) {
WAIT(2);
}
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.cpp b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
index 3e4e14455e..6d80e62806 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.cpp
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.cpp
@@ -41,7 +41,10 @@ void MainMenuContainer::show() {
menu = new DarkSideMainMenuContainer();
break;
case GType_WorldOfXeen:
- menu = new WorldOfXeenMainMenuContainer();
+ if (g_vm->getIsCD())
+ menu = new WorldOfXeenCDMainMenuContainer();
+ else
+ menu = new WorldOfXeenMainMenuContainer();
break;
default:
error("Invalid game");
@@ -51,9 +54,20 @@ void MainMenuContainer::show() {
delete menu;
}
-MainMenuContainer::MainMenuContainer(const Common::String &spritesName, uint frameCount) :
- _frameCount(frameCount), _animateCtr(0), _dialog(nullptr) {
- _backgroundSprites.load(spritesName);
+MainMenuContainer::MainMenuContainer(const char *spritesName1, const char *spritesName2, const char *spritesName3) :
+ _animateCtr(0), _dialog(nullptr) {
+ g_vm->_files->setGameCc(g_vm->getGameID() == GType_Clouds ? 0 : 1);
+
+ _backgroundSprites.resize(1 + (spritesName2 ? 1 : 0) + (spritesName3 ? 1 : 0));
+ _backgroundSprites[0].load(spritesName1);
+ if (spritesName2)
+ _backgroundSprites[1].load(spritesName2);
+ if (spritesName3)
+ _backgroundSprites[2].load(spritesName3);
+
+ _frameCount = 0;
+ for (uint idx = 0; idx < _backgroundSprites.size(); ++idx)
+ _frameCount += _backgroundSprites[idx].size();
}
MainMenuContainer::~MainMenuContainer() {
@@ -66,7 +80,17 @@ MainMenuContainer::~MainMenuContainer() {
void MainMenuContainer::draw() {
g_vm->_screen->restoreBackground();
_animateCtr = (_animateCtr + 1) % _frameCount;
- _backgroundSprites.draw(0, _animateCtr);
+
+ // Draw the next background frame
+ uint frameNum = _animateCtr;
+ for (uint idx = 0; idx < _backgroundSprites.size(); ++idx) {
+ if (frameNum < _backgroundSprites[idx].size()) {
+ _backgroundSprites[idx].draw(0, frameNum);
+ return;
+ } else {
+ frameNum -= _backgroundSprites[idx].size();
+ }
+ }
}
void MainMenuContainer::execute() {
@@ -96,7 +120,7 @@ void MainMenuContainer::execute() {
// Check for events
events.updateGameCounter();
-
+
if (events.wait(4, true)) {
if (_dialog) {
// There's a dialog active, so let it handle the event
@@ -109,11 +133,9 @@ void MainMenuContainer::execute() {
} else {
// No active dialog. If Escape pressed, exit game entirely. Otherwise,
// open up the main menu dialog
- if (events.isKeyPending()) {
- Common::KeyState key;
- if (events.getKey(key) && key.keycode == Common::KEYCODE_ESCAPE)
- g_vm->_gameMode = GMODE_QUIT;
- }
+ PendingEvent pe;
+ if (events.getEvent(pe) && pe._keyState.keycode == Common::KEYCODE_ESCAPE)
+ g_vm->_gameMode = GMODE_QUIT;
events.clearEvents();
showMenuDialog();
@@ -124,7 +146,7 @@ void MainMenuContainer::execute() {
/*------------------------------------------------------------------------*/
-CloudsMainMenuContainer::CloudsMainMenuContainer() : MainMenuContainer("intro.vga", 9) {
+CloudsMainMenuContainer::CloudsMainMenuContainer() : MainMenuContainer("intro.vga") {
}
void CloudsMainMenuContainer::display() {
@@ -149,7 +171,7 @@ void CloudsMainMenuContainer::showMenuDialog() {
/*------------------------------------------------------------------------*/
-DarkSideMainMenuContainer::DarkSideMainMenuContainer() : MainMenuContainer("title2a.int", 10) {
+DarkSideMainMenuContainer::DarkSideMainMenuContainer() : MainMenuContainer("title2a.int") {
Screen &screen = *g_vm->_screen;
Sound &sound = *g_vm->_sound;
screen.loadPalette("dark.pal");
@@ -185,7 +207,7 @@ void DarkSideMainMenuContainer::showMenuDialog() {
/*------------------------------------------------------------------------*/
-WorldOfXeenMainMenuContainer::WorldOfXeenMainMenuContainer() : MainMenuContainer("world.int", 5) {
+WorldOfXeenMainMenuContainer::WorldOfXeenMainMenuContainer() : MainMenuContainer("world.int") {
}
void WorldOfXeenMainMenuContainer::display() {
@@ -210,7 +232,33 @@ void WorldOfXeenMainMenuContainer::showMenuDialog() {
/*------------------------------------------------------------------------*/
+WorldOfXeenCDMainMenuContainer::WorldOfXeenCDMainMenuContainer() : MainMenuContainer("world0.int", "world1.int", "world2.int") {
+}
+
+void WorldOfXeenCDMainMenuContainer::display() {
+ FileManager &files = *g_vm->_files;
+ Screen &screen = *g_vm->_screen;
+ Sound &sound = *g_vm->_sound;
+
+ sound._musicSide = 1;
+ files.setGameCc(1);
+
+ screen.loadPalette("dark.pal");
+ screen.loadBackground("world.raw");
+ screen.saveBackground();
+
+ if (!sound.isMusicPlaying())
+ sound.playSong("newbrigh.m");
+}
+
+void WorldOfXeenCDMainMenuContainer::showMenuDialog() {
+ setOwner(new WorldMenuDialog(this));
+}
+
+/*------------------------------------------------------------------------*/
+
bool MainMenuDialog::handleEvents() {
+ FileManager &files = *g_vm->_files;
checkEvents(g_vm);
int difficulty;
@@ -227,14 +275,18 @@ bool MainMenuDialog::handleEvents() {
g_vm->_gameMode = GMODE_PLAY_GAME;
break;
- case Common::KEYCODE_l:
+ case Common::KEYCODE_l: {
// Load existing game
+ int ccNum = files._ccNum;
g_vm->_saves->newGame();
- if (!g_vm->_saves->loadGame())
+ if (!g_vm->_saves->loadGame()) {
+ files.setGameCc(ccNum);
return true;
+ }
g_vm->_gameMode = GMODE_PLAY_GAME;
break;
+ }
case Common::KEYCODE_c:
case Common::KEYCODE_v:
@@ -285,7 +337,7 @@ void CloudsMenuDialog::loadButtons() {
void CloudsMenuDialog::draw() {
Windows &windows = *g_vm->_windows;
Window &w = windows[GAME_WINDOW];
-
+
w.frame();
w.writeString(Common::String::format(Res.OPTIONS_MENU, Res.GAME_NAMES[0], g_vm->_gameWon[0] ? 117 : 92, 1992));
drawButtons(&w);
@@ -532,7 +584,7 @@ void OtherOptionsDialog::draw() {
w.frame();
w.writeString(Common::String::format(Res.OPTIONS_MENU,
- Res.GAME_NAMES[g_vm->getGameID() == GType_WorldOfXeen ? 2 : 1],
+ Res.GAME_NAMES[g_vm->getGameID() == GType_WorldOfXeen ? 2 : 1],
w.getBounds().height() - 33, 1993));
drawButtons(&w);
}
diff --git a/engines/xeen/worldofxeen/worldofxeen_menu.h b/engines/xeen/worldofxeen/worldofxeen_menu.h
index e753665f08..ba4a465047 100644
--- a/engines/xeen/worldofxeen/worldofxeen_menu.h
+++ b/engines/xeen/worldofxeen/worldofxeen_menu.h
@@ -25,6 +25,7 @@
#include "xeen/xeen.h"
#include "xeen/dialogs/dialogs.h"
+#include "common/array.h"
namespace Xeen {
namespace WorldOfXeen {
@@ -35,7 +36,7 @@ class MainMenuContainer {
private:
uint _animateCtr;
uint _frameCount;
- SpriteResource _backgroundSprites;
+ Common::Array<SpriteResource> _backgroundSprites;
MenuContainerDialog *_dialog;
protected:
/**
@@ -61,7 +62,7 @@ public:
/**
* Constructor
*/
- MainMenuContainer(const Common::String &spritesName, uint frameCount);
+ MainMenuContainer(const char *spritesName1, const char *spritesName2 = nullptr, const char *spritesName3 = nullptr);
/**
* Destructor
@@ -128,6 +129,21 @@ public:
WorldOfXeenMainMenuContainer();
};
+class WorldOfXeenCDMainMenuContainer : public MainMenuContainer {
+protected:
+ /**
+ * Called when the menu screen is first shown
+ */
+ virtual void display();
+
+ /**
+ * Shows the main menu dialog
+ */
+ virtual void showMenuDialog();
+public:
+ WorldOfXeenCDMainMenuContainer();
+};
+
class MenuContainerDialog : public ButtonContainer {
protected:
MainMenuContainer *_owner;
diff --git a/engines/xeen/worldofxeen/worldofxeen_resources.cpp b/engines/xeen/worldofxeen/worldofxeen_resources.cpp
deleted file mode 100644
index 5bd6247d08..0000000000
--- a/engines/xeen/worldofxeen/worldofxeen_resources.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "xeen/worldofxeen/worldofxeen_resources.h"
-
-namespace Xeen {
-namespace WorldOfXeen {
-
-const char *const WorldOfXeenResources::CLOUDS_INTRO1 = "\xC" "00\xB" "082\x9" "040\x3"
- "cKing Burlock\xB" "190\x9" "040Peasants\xB" "082\x9" "247"
- "Lord Xeen\xB" "190\x9" "258Xeen's Pet\xB" "179\x9" "150Crodo";
-
-const char *const WorldOfXeenResources::DARKSIDE_ENDING1 = "\n\x3" "cCongratulations\n"
- "\n"
- "Your Final Score is:\n"
- "\n"
- "%010lu\n"
- "\x3" "l\n"
- "Please send this score to the Ancient's Headquarters "
- "where you'll be added to the Hall of Legends!\n"
- "\n"
- "Ancient's Headquarters\n"
- "New World Computing, Inc.\n"
- "P.O. Box 4302\n"
- "Hollywood, CA 90078";
-
-const char *const WorldOfXeenResources::DARKSIDE_ENDING2 = "\n"
- "Adventurers,\n"
- "\n"
- "I will save your game in Castleview.\n"
- "\n"
- "The World of Xeen still needs you!\n"
- "\n"
- "Load your game afterwards and come visit me in the "
- "Great Pyramid for further instructions";
-
-const char *const WorldOfXeenResources::PHAROAH_ENDING_TEXT1 = "\xC" "d\xB"
- "001\x9" "001%s\x3" "c\x9" "000\xB" "180Press a Key!\x3" "l";
-const char *const WorldOfXeenResources::PHAROAH_ENDING_TEXT2 = "\xC" "04\xB"
- "000\x9" "000%s\x3" "c\x9" "000\xB" "180Press a Key!\x3" "l\xC" "d";
-
-} // End of namespace WorldOfXeen
-} // End of namespace Xeen
diff --git a/engines/xeen/xeen.cpp b/engines/xeen/xeen.cpp
index c8fb40d2a0..371f437172 100644
--- a/engines/xeen/xeen.cpp
+++ b/engines/xeen/xeen.cpp
@@ -49,6 +49,7 @@ XeenEngine::XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc)
_locations = nullptr;
_map = nullptr;
_party = nullptr;
+ _patcher = nullptr;
_resources = nullptr;
_saves = nullptr;
_screen = nullptr;
@@ -75,6 +76,7 @@ XeenEngine::~XeenEngine() {
delete _locations;
delete _map;
delete _party;
+ delete _patcher;
delete _saves;
delete _screen;
delete _scripts;
@@ -100,6 +102,7 @@ bool XeenEngine::initialize() {
_locations = new LocationManager();
_map = new Map(this);
_party = new Party(this);
+ _patcher = new Patcher();
_saves = new SavesManager(_targetName);
_screen = new Screen(this);
_scripts = new Scripts(this);
@@ -114,19 +117,26 @@ bool XeenEngine::initialize() {
syncSoundSettings();
// Load settings
+ loadSettings();
+
+ return true;
+}
+
+void XeenEngine::loadSettings() {
_gameWon[0] = ConfMan.hasKey("game_won") && ConfMan.getBool("game_won");
_gameWon[1] = ConfMan.hasKey("game_won2") && ConfMan.getBool("game_won2");
_gameWon[2] = ConfMan.hasKey("game_won3") && ConfMan.getBool("game_won3");
_finalScore = ConfMan.hasKey("final_score") ? ConfMan.getInt("final_score") : 0;
+ _extOptions._showItemCosts = ConfMan.hasKey("ShowItemCosts") && ConfMan.getBool("ShowItemCosts");
+ _extOptions._durableArmor = ConfMan.hasKey("DurableArmor") && ConfMan.getBool("DurableArmor");
+
// If requested, load a savegame instead of showing the intro
if (ConfMan.hasKey("save_slot")) {
int saveSlot = ConfMan.getInt("save_slot");
if (saveSlot >= 0 && saveSlot <= 999)
_loadSaveSlot = saveSlot;
}
-
- return true;
}
Common::Error XeenEngine::run() {
@@ -183,11 +193,12 @@ Common::Error XeenEngine::loadGameState(int slot) {
}
bool XeenEngine::canLoadGameStateCurrently() {
- return _mode != MODE_COMBAT;
+ return _mode != MODE_STARTUP;
}
bool XeenEngine::canSaveGameStateCurrently() {
- return _mode != MODE_COMBAT;
+ return _mode != MODE_COMBAT && _mode != MODE_STARTUP && _mode != MODE_SCRIPT_IN_PROGRESS
+ && (_map->mazeData()._mazeFlags & RESTRICTION_SAVE) == 0;
}
void XeenEngine::playGame() {
@@ -196,6 +207,7 @@ void XeenEngine::playGame() {
SpriteResource::setClippedBottom(140);
play();
+ _sound->stopAllAudio();
}
void XeenEngine::play() {
@@ -203,14 +215,15 @@ void XeenEngine::play() {
_screen->loadBackground("back.raw");
_screen->loadPalette("mm4.pal");
- if (getGameID() == GType_DarkSide && !_map->_loadDarkSide) {
- _map->_loadDarkSide = true;
+ if (getGameID() == GType_DarkSide && !_map->_loadCcNum) {
+ _map->_loadCcNum = 1;
_party->_mazeId = 29;
_party->_mazeDirection = DIR_NORTH;
_party->_mazePosition.x = 25;
_party->_mazePosition.y = 21;
}
+ _map->clearMaze();
if (_loadSaveSlot >= 0) {
_saves->newGame();
_saves->loadGameState(_loadSaveSlot);
@@ -231,7 +244,7 @@ void XeenEngine::play() {
_combat->_moveMonsters = true;
if (_mode == MODE_STARTUP) {
- _mode = MODE_1;
+ _mode = MODE_INTERACTIVE;
_screen->fadeIn();
}
@@ -243,22 +256,26 @@ void XeenEngine::play() {
death();
_mode = MODE_STARTUP;
+ _gameMode = GMODE_MENU;
}
void XeenEngine::gameLoop() {
// Main game loop
- while (!shouldExit()) {
- if (_loadSaveSlot >= 0) {
+ while (isLoadPending() || !shouldExit()) {
+ if (isLoadPending()) {
// Load any pending savegame
int saveSlot = _loadSaveSlot;
_loadSaveSlot = -1;
_saves->loadGameState(saveSlot);
+ _interface->drawParty(true);
}
_map->cellFlagLookup(_party->_mazePosition);
if (_map->_currentIsEvent) {
_gameMode = (GameMode)_scripts->checkEvents();
- if (shouldExit() || _gameMode)
+ if (isLoadPending())
+ continue;
+ if (shouldExit())
return;
}
_party->giveTreasure();
diff --git a/engines/xeen/xeen.h b/engines/xeen/xeen.h
index c79b240388..98b09e7f23 100644
--- a/engines/xeen/xeen.h
+++ b/engines/xeen/xeen.h
@@ -39,6 +39,7 @@
#include "xeen/locations.h"
#include "xeen/map.h"
#include "xeen/party.h"
+#include "xeen/patcher.h"
#include "xeen/resources.h"
#include "xeen/saves.h"
#include "xeen/screen.h"
@@ -77,7 +78,7 @@ enum XeenDebugChannels {
enum Mode {
MODE_FF = -1,
MODE_STARTUP = 0,
- MODE_1 = 1,
+ MODE_INTERACTIVE = 1,
MODE_COMBAT = 2,
MODE_3 = 3,
MODE_4 = 4,
@@ -85,11 +86,11 @@ enum Mode {
MODE_6 = 6,
MODE_7 = 7,
MODE_8 = 8,
- MODE_RECORD_EVENTS = 9,
+ MODE_SCRIPT_IN_PROGRESS = 9,
MODE_CHARACTER_INFO = 10,
- MODE_12 = 12,
+ MODE_INTERACTIVE2 = 12,
MODE_DIALOG_123 = 13,
- MODE_17 = 17,
+ MODE_INTERACTIVE7 = 17,
MODE_86 = 86
};
@@ -106,6 +107,15 @@ struct XeenGameDescription;
#define XEEN_SAVEGAME_VERSION 1
class XeenEngine : public Engine {
+ /**
+ * Container to a set of options newly introduced under ScummVM
+ */
+ struct ExtendedOptions {
+ bool _showItemCosts;
+ bool _durableArmor;
+
+ ExtendedOptions() : _showItemCosts(false), _durableArmor(false) {}
+ };
private:
const XeenGameDescription *_gameDescription;
Common::RandomSource _randomSource;
@@ -115,6 +125,11 @@ private:
*/
bool initialize();
+ /**
+ * Load settings
+ */
+ void loadSettings();
+
// Engine APIs
virtual Common::Error run();
virtual bool hasFeature(EngineFeature f) const;
@@ -170,6 +185,7 @@ public:
LocationManager *_locations;
Map *_map;
Party *_party;
+ Patcher *_patcher;
Resources *_resources;
SavesManager *_saves;
Screen *_screen;
@@ -178,13 +194,13 @@ public:
Spells *_spells;
Windows *_windows;
Mode _mode;
- GameEvent _gameEvent;
GameMode _gameMode;
bool _noDirectionSense;
bool _startupWindowActive;
uint _endingScore;
bool _gameWon[3];
uint _finalScore;
+ ExtendedOptions _extOptions;
public:
XeenEngine(OSystem *syst, const XeenGameDescription *gameDesc);
virtual ~XeenEngine();
@@ -195,6 +211,7 @@ public:
uint16 getVersion() const;
uint32 getGameID() const;
uint32 getGameFeatures() const;
+ bool getIsCD() const;
int getRandomNumber(int maxNumber);
@@ -206,9 +223,14 @@ public:
void GUIError(const char *msg, ...) GCC_PRINTF(2, 3);
/**
- * Returns true if the game should be exited (and likely return to game menu)
+ * Returns true if the game should be exited (either quitting, exiting to the main menu, or loading a savegame)
+ */
+ bool shouldExit() const { return _gameMode != GMODE_NONE || isLoadPending() || shouldQuit(); }
+
+ /**
+ * Returns true if a savegame load is pending
*/
- bool shouldExit() const { return _gameMode != GMODE_NONE || shouldQuit(); }
+ bool isLoadPending() const { return _loadSaveSlot != -1; }
/**
* Load a savegame
diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp
index 5e535a9954..f14263f012 100644
--- a/engines/zvision/detection.cpp
+++ b/engines/zvision/detection.cpp
@@ -88,8 +88,8 @@ bool ZVisionMetaEngine::hasFeature(MetaEngineFeature f) const {
(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
(f == kSavesSupportCreationDate) ||
+ (f == kSavesSupportPlayTime) ||
(f == kSimpleSavesNames);
- //(f == kSavesSupportPlayTime);
}
bool ZVision::ZVision::hasFeature(EngineFeature f) const {
@@ -178,7 +178,7 @@ SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, in
// We only use readSaveGameHeader() here, which doesn't need an engine callback
ZVision::SaveManager *zvisionSaveMan = new ZVision::SaveManager(NULL);
- bool successfulRead = zvisionSaveMan->readSaveGameHeader(in, header);
+ bool successfulRead = zvisionSaveMan->readSaveGameHeader(in, header, false);
delete zvisionSaveMan;
delete in;
@@ -192,7 +192,7 @@ SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, in
desc.setThumbnail(header.thumbnail);
- if (header.version > 0) {
+ if (header.version >= 1) {
int day = header.saveDay;
int month = header.saveMonth;
int year = header.saveYear;
@@ -203,8 +203,10 @@ SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, in
int minutes = header.saveMinutes;
desc.setSaveTime(hour, minutes);
+ }
- //desc.setPlayTime(header.playTime * 1000);
+ if (header.version >= 2) {
+ desc.setPlayTime(header.playTime * 1000);
}
return desc;
diff --git a/engines/zvision/detection_tables.h b/engines/zvision/detection_tables.h
index 3df8f280ee..cb813e6d5b 100644
--- a/engines/zvision/detection_tables.h
+++ b/engines/zvision/detection_tables.h
@@ -49,7 +49,7 @@ static const ADExtraGuiOptionsMap optionsList[] = {
GAMEOPTION_ORIGINAL_SAVELOAD,
{
_s("Use original save/load screens"),
- _s("Use the original save/load screens instead of the ScummVM interface"),
+ _s("Use the original save/load screens instead of the ScummVM ones"),
"originalsaveload",
false
}
diff --git a/engines/zvision/file/save_manager.cpp b/engines/zvision/file/save_manager.cpp
index 4259937a3b..dd4425ae90 100644
--- a/engines/zvision/file/save_manager.cpp
+++ b/engines/zvision/file/save_manager.cpp
@@ -128,6 +128,8 @@ void SaveManager::writeSaveGameHeader(Common::OutSaveFile *file, const Common::S
file->writeSint16LE(td.tm_mday);
file->writeSint16LE(td.tm_hour);
file->writeSint16LE(td.tm_min);
+
+ file->writeUint32LE(g_engine->getTotalPlayTime() / 1000);
}
Common::Error SaveManager::loadGame(int slot) {
@@ -162,8 +164,6 @@ Common::Error SaveManager::loadGame(int slot) {
scriptManager->deserialize(saveFile);
delete saveFile;
- if (header.thumbnail)
- delete header.thumbnail;
if (_engine->getGameId() == GID_NEMESIS && scriptManager->getCurrentLocation() == "tv2f") {
// WORKAROUND for script bug #6793: location tv2f (stairs) has two states:
@@ -186,20 +186,26 @@ Common::Error SaveManager::loadGame(int slot) {
}
}
+ g_engine->setTotalPlayTime(header.playTime * 1000);
+
return Common::kNoError;
}
-bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header) {
+bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &header, bool skipThumbnail) {
+ header.saveYear = 0;
+ header.saveMonth = 0;
+ header.saveDay = 0;
+ header.saveHour = 0;
+ header.saveMinutes = 0;
+ header.playTime = 0;
+ header.saveName.clear();
+ header.thumbnail = nullptr;
+ header.version = 0;
+
uint32 tag = in->readUint32BE();
// Check if it's original savegame than fill header structure
if (tag == MKTAG('Z', 'N', 'S', 'G')) {
- header.saveYear = 0;
- header.saveMonth = 0;
- header.saveDay = 0;
- header.saveHour = 0;
- header.saveMinutes = 0;
header.saveName = "Original Save";
- header.thumbnail = NULL;
header.version = SAVE_ORIGINAL;
in->seek(-4, SEEK_CUR);
return true;
@@ -226,23 +232,26 @@ bool SaveManager::readSaveGameHeader(Common::InSaveFile *in, SaveGameHeader &hea
}
// Read in the save name
- header.saveName.clear();
char ch;
while ((ch = (char)in->readByte()) != '\0')
header.saveName += ch;
// Get the thumbnail
- header.thumbnail = Graphics::loadThumbnail(*in);
- if (!header.thumbnail)
+ if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) {
return false;
+ }
// Read in save date/time
- header.saveYear = in->readSint16LE();
- header.saveMonth = in->readSint16LE();
- header.saveDay = in->readSint16LE();
- header.saveHour = in->readSint16LE();
+ header.saveYear = in->readSint16LE();
+ header.saveMonth = in->readSint16LE();
+ header.saveDay = in->readSint16LE();
+ header.saveHour = in->readSint16LE();
header.saveMinutes = in->readSint16LE();
+ if (header.version >= 2) {
+ header.playTime = in->readUint32LE();
+ }
+
return true;
}
diff --git a/engines/zvision/file/save_manager.h b/engines/zvision/file/save_manager.h
index 9e816373ea..e5bf47b47b 100644
--- a/engines/zvision/file/save_manager.h
+++ b/engines/zvision/file/save_manager.h
@@ -42,8 +42,9 @@ struct SaveGameHeader {
byte version;
Common::String saveName;
Graphics::Surface *thumbnail;
- int saveYear, saveMonth, saveDay;
- int saveHour, saveMinutes;
+ int16 saveYear, saveMonth, saveDay;
+ int16 saveHour, saveMinutes;
+ uint32 playTime;
};
class SaveManager {
@@ -64,7 +65,7 @@ private:
enum {
SAVE_ORIGINAL = 0,
- SAVE_VERSION = 1
+ SAVE_VERSION = 2
};
Common::MemoryWriteStreamDynamic *_tempThumbnail;
@@ -94,7 +95,7 @@ public:
Common::Error loadGame(int slot);
Common::SeekableReadStream *getSlotFile(uint slot);
- bool readSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &header);
+ bool readSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &header, bool skipThumbnail = true);
void prepareSaveBuffer();
void flushSaveBuffer();
diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp
index 73dc6309b2..e92a09f8c9 100644
--- a/graphics/VectorRenderer.cpp
+++ b/graphics/VectorRenderer.cpp
@@ -143,7 +143,7 @@ void VectorRenderer::stepGetPositions(const DrawStep &step, const Common::Rect &
break;
case Graphics::DrawStep::kVectorAlignCenter:
- in_y = area.top + (area.height() / 2) - (in_h / 2) + ((step.padding.top + step.padding.bottom ) / 2) ;
+ in_y = area.top + (area.height() / 2) - (in_h / 2) + ((step.padding.top + step.padding.bottom ) / 2);
break;
case Graphics::DrawStep::kVectorAlignTop:
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 2b84c21894..2abe0e0759 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -437,7 +437,7 @@ public:
void drawCallback_ALPHABITMAP(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
uint16 x, y, w, h;
stepGetPositions(step, area, x, y, w, h);
- blitAlphaBitmap(step.blitAlphaSrc, Common::Rect(x, y, x + w, y + h), step.autoscale, step.xAlign, step.yAlign); //TODO
+ blitAlphaBitmap(step.blitAlphaSrc, Common::Rect(x, y, x + w, y + h), step.autoscale, step.xAlign, step.yAlign); // TODO
}
void drawCallback_CROSS(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 1d6b2589cb..e308dde821 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -419,7 +419,7 @@ inline frac_t fp_sqroot(uint32 x) {
x--; px -= pitch; \
} \
a2 = (T >> 8); \
- a1 = ~a2; \
+ a1 = ~a2; \
} while (0)
@@ -448,16 +448,16 @@ void colorFill(PixelType *first, PixelType *last, PixelType color) {
return;
int n = (count + 7) >> 3;
switch (count % 8) {
- case 0: do {
- *first++ = color; // fall through
- case 7: *first++ = color; // fall through
- case 6: *first++ = color; // fall through
- case 5: *first++ = color; // fall through
- case 4: *first++ = color; // fall through
- case 3: *first++ = color; // fall through
- case 2: *first++ = color; // fall through
+ case 0: do {
+ *first++ = color; // fall through
+ case 7: *first++ = color; // fall through
+ case 6: *first++ = color; // fall through
+ case 5: *first++ = color; // fall through
+ case 4: *first++ = color; // fall through
+ case 3: *first++ = color; // fall through
+ case 2: *first++ = color; // fall through
case 1: *first++ = color;
- } while (--n > 0);
+ } while (--n > 0);
}
}
@@ -487,16 +487,16 @@ void colorFillClip(PixelType *first, PixelType *last, PixelType color, int realX
int n = (count + 7) >> 3;
switch (count % 8) {
- case 0: do {
- *first++ = color; // fall through
- case 7: *first++ = color; // fall through
- case 6: *first++ = color; // fall through
- case 5: *first++ = color; // fall through
- case 4: *first++ = color; // fall through
- case 3: *first++ = color; // fall through
- case 2: *first++ = color; // fall through
+ case 0: do {
+ *first++ = color; // fall through
+ case 7: *first++ = color; // fall through
+ case 6: *first++ = color; // fall through
+ case 5: *first++ = color; // fall through
+ case 4: *first++ = color; // fall through
+ case 3: *first++ = color; // fall through
+ case 2: *first++ = color; // fall through
case 1: *first++ = color;
- } while (--n > 0);
+ } while (--n > 0);
}
}
@@ -2680,7 +2680,7 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
int gradient = (dx << 8) / (dy + 0x100);
int interx = (x1 << 8) + gradient;
#else
- double gradient = dx / (dy+1);
+ double gradient = dx / (dy + 1);
double interx = x1 + gradient;
#endif
@@ -2846,7 +2846,7 @@ drawTriangleVertAlgClip(int x1, int y1, int w, int h, bool inverted, PixelType c
break;
case kFillForeground:
case kFillBackground:
- colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
+ colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right + 1, y_right, _clippingArea);
blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
break;
@@ -2905,7 +2905,7 @@ drawTriangleVertAlgClip(int x1, int y1, int w, int h, bool inverted, PixelType c
break;
case kFillForeground:
case kFillBackground:
- colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
+ colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right + 1, y_right, _clippingArea);
blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
break;
@@ -2953,7 +2953,7 @@ drawTriangleVertAlgClip(int x1, int y1, int w, int h, bool inverted, PixelType c
break;
case kFillForeground:
case kFillBackground:
- colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
+ colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right + 1, y_right, _clippingArea);
blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
break;
@@ -3061,10 +3061,10 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
BE_RESET();
r--;
- int alphaStep_tr = ((alpha_t - alpha_r)/(y+1));
- int alphaStep_br = ((alpha_r - alpha_b)/(y+1));
- int alphaStep_bl = ((alpha_b - alpha_l)/(y+1));
- int alphaStep_tl = ((alpha_l - alpha_t)/(y+1));
+ int alphaStep_tr = ((alpha_t - alpha_r) / (y + 1));
+ int alphaStep_br = ((alpha_r - alpha_b) / (y + 1));
+ int alphaStep_bl = ((alpha_b - alpha_l) / (y + 1));
+ int alphaStep_tl = ((alpha_l - alpha_t) / (y + 1));
// Avoid blending the last pixels twice, since we have an alpha
while (x++ < (y - 2)) {
@@ -3199,8 +3199,6 @@ drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType colo
while (x++ < y) {
BE_ALGORITHM();
- if (y1 + r + y < _clippingArea.top || y1 + r + y > _clippingArea.bottom) continue;
-
color1 = calcGradient(real_radius - x, long_h);
color2 = calcGradient(real_radius - y, long_h);
color3 = calcGradient(long_h - r + x, long_h);
@@ -3972,10 +3970,10 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
px = pitch * x;
py = 0;
- int alphaStep_tr = ((alpha_t - alpha_r)/(x+1));
- int alphaStep_br = ((alpha_r - alpha_b)/(x+1));
- int alphaStep_bl = ((alpha_b - alpha_l)/(x+1));
- int alphaStep_tl = ((alpha_l - alpha_t)/(x+1));
+ int alphaStep_tr = ((alpha_t - alpha_r) / (x + 1));
+ int alphaStep_br = ((alpha_r - alpha_b) / (x + 1));
+ int alphaStep_bl = ((alpha_b - alpha_l) / (x + 1));
+ int alphaStep_tl = ((alpha_l - alpha_t) / (x + 1));
while (x > y++) {
WU_ALGORITHM();
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 84c802f6df..958ad0717b 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -289,7 +289,8 @@ protected:
* @param alpha Alpha intensity of the pixel (0-255)
*/
inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) {
- while (first != last) blendPixelPtr(first++, color, alpha);
+ while (first != last)
+ blendPixelPtr(first++, color, alpha);
}
inline void blendFillClip(PixelType *first, PixelType *last, PixelType color, uint8 alpha, int realX, int realY) {
diff --git a/graphics/fonts/bdf.h b/graphics/fonts/bdf.h
index d99b5fd401..c903d52c55 100644
--- a/graphics/fonts/bdf.h
+++ b/graphics/fonts/bdf.h
@@ -85,9 +85,9 @@ private:
};
#define DEFINE_FONT(n) \
- const BdfFont *n = 0; \
+ const BdfFont *n = 0; \
void create_##n() { \
- n = new BdfFont(desc, DisposeAfterUse::NO); \
+ n = new BdfFont(desc, DisposeAfterUse::NO); \
}
#define FORWARD_DECLARE_FONT(n) \
diff --git a/graphics/nine_patch.cpp b/graphics/nine_patch.cpp
index 56e1202be3..ce82fff61e 100644
--- a/graphics/nine_patch.cpp
+++ b/graphics/nine_patch.cpp
@@ -156,7 +156,7 @@ NinePatchBitmap::NinePatchBitmap(Graphics::TransparentSurface *bmp, bool owns_bi
bmp->format.colorToARGB(*(uint32 *)bmp->getBasePtr(x, y), a, r, g, b); \
if (a != 0 && r + g + b + a != 4) goto bad_bitmap;
- _check_pixel(0,0);
+ _check_pixel(0, 0);
_check_pixel(bmp->w - 1, 0);
_check_pixel(0, bmp->h - 1);
_check_pixel(bmp->w - 1, bmp->h - 1);
diff --git a/graphics/primitives.cpp b/graphics/primitives.cpp
index 8663a61606..76c44b650d 100644
--- a/graphics/primitives.cpp
+++ b/graphics/primitives.cpp
@@ -262,13 +262,13 @@ void drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*p
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);
+ 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);
+ (*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;
@@ -284,15 +284,15 @@ void drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*p
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);
+ 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.left, rect.top + r + i, color, data);
(*plotProc)(rect.right, rect.top + r + i, color, data);
}
}
@@ -307,13 +307,13 @@ void drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*p
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);
+ 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);
+ (*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;
@@ -329,15 +329,15 @@ void drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*p
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);
+ 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.top, color, data);
(*plotProc)(rect.left + r + i, rect.bottom, color, data);
}
}
@@ -385,14 +385,14 @@ void drawPolygonScan(int *polyX, int *polyY, int npoints, Common::Rect &bbox, in
// 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 */
+ 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;
+ y0 += (b + 1) / 2; y1 = y0 - b1; /* starting pixel */
+ a *= 8 * a; b1 = 8 * b * b;
do {
if (filled) {
@@ -411,15 +411,15 @@ void drawEllipse(int x0, int y0, int x1, int y1, int color, bool filled, void (*
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);
+ 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);
+ (*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--;
diff --git a/graphics/scaler.cpp b/graphics/scaler.cpp
index 745988cbd9..a3ac7fc107 100644
--- a/graphics/scaler.cpp
+++ b/graphics/scaler.cpp
@@ -107,12 +107,12 @@ void InitLUT(Graphics::PixelFormat format) {
hqx_low2bits = (3 << format.rShift) | (3 << format.gShift) | (3 << format.bShift),
hqx_low3bits = (7 << format.rShift) | (7 << format.gShift) | (7 << format.bShift),
- hqx_highbits = format.RGBToColor(255,255,255) ^ hqx_lowbits;
+ hqx_highbits = format.RGBToColor(255, 255, 255) ^ hqx_lowbits;
// FIXME: The following code only does the right thing
// if the color order is RGB or BGR, i.e., green is in the middle.
- hqx_greenMask = format.RGBToColor(0,255,0);
- hqx_redBlueMask = format.RGBToColor(255,0,255);
+ hqx_greenMask = format.RGBToColor( 0, 255, 0);
+ hqx_redBlueMask = format.RGBToColor(255, 0, 255);
hqx_green_redBlue_Mask = (hqx_greenMask << 16) | hqx_redBlueMask;
#endif
@@ -145,10 +145,10 @@ void InitScalers(uint32 BitFormat) {
#endif
// Build dotmatrix lookup table for the DotMatrix scaler.
- g_dotmatrix[0] = g_dotmatrix[10] = format.RGBToColor(0, 63, 0);
- g_dotmatrix[1] = g_dotmatrix[11] = format.RGBToColor(0, 0, 63);
- g_dotmatrix[2] = g_dotmatrix[8] = format.RGBToColor(63, 0, 0);
- g_dotmatrix[4] = g_dotmatrix[6] =
+ g_dotmatrix[0] = g_dotmatrix[10] = format.RGBToColor( 0, 63, 0);
+ g_dotmatrix[1] = g_dotmatrix[11] = format.RGBToColor( 0, 0, 63);
+ g_dotmatrix[2] = g_dotmatrix[ 8] = format.RGBToColor(63, 0, 0);
+ g_dotmatrix[4] = g_dotmatrix[ 6] =
g_dotmatrix[12] = g_dotmatrix[14] = format.RGBToColor(63, 63, 63);
}
diff --git a/graphics/scaler/intern.h b/graphics/scaler/intern.h
index eddc3c7f3d..213b69b049 100644
--- a/graphics/scaler/intern.h
+++ b/graphics/scaler/intern.h
@@ -195,18 +195,18 @@ static inline bool diffYUV(int yuv1, int yuv2) {
int mask;
diff = ((yuv1 & Umask) - (yuv2 & Umask));
- mask = diff >> 31; // -1 if value < 0, 0 otherwise
- diff = (diff ^ mask) - mask; //-1: ~value + 1; 0: value
+ mask = diff >> 31; // -1 if value < 0, 0 otherwise
+ diff = (diff ^ mask) - mask; // -1: ~value + 1; 0: value
if (diff > trU) return true;
diff = ((yuv1 & Vmask) - (yuv2 & Vmask));
- mask = diff >> 31; // -1 if value < 0, 0 otherwise
- diff = (diff ^ mask) - mask; //-1: ~value + 1; 0: value
+ mask = diff >> 31; // -1 if value < 0, 0 otherwise
+ diff = (diff ^ mask) - mask; // -1: ~value + 1; 0: value
if (diff > trV) return true;
diff = ((yuv1 & Ymask) - (yuv2 & Ymask));
- mask = diff >> 31; // -1 if value < 0, 0 otherwise
- diff = (diff ^ mask) - mask; //-1: ~value + 1; 0: value
+ mask = diff >> 31; // -1 if value < 0, 0 otherwise
+ diff = (diff ^ mask) - mask; // -1: ~value + 1; 0: value
if (diff > trY) return true;
return false;
diff --git a/graphics/scaler/scalebit.cpp b/graphics/scaler/scalebit.cpp
index c8b54f4b25..bcba5793e2 100644
--- a/graphics/scaler/scalebit.cpp
+++ b/graphics/scaler/scalebit.cpp
@@ -47,17 +47,17 @@
static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) {
switch (pixel) {
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
- case 1 : scale2x_8_mmx(DST(8,0), DST(8,1), SRC(8,0), SRC(8,1), SRC(8,2), pixel_per_row); break;
- case 2 : scale2x_16_mmx(DST(16,0), DST(16,1), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
- case 4 : scale2x_32_mmx(DST(32,0), DST(32,1), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
+ case 1: scale2x_8_mmx( DST( 8,0), DST( 8,1), SRC( 8,0), SRC( 8,1), SRC( 8,2), pixel_per_row); break;
+ case 2: scale2x_16_mmx(DST(16,0), DST(16,1), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
+ case 4: scale2x_32_mmx(DST(32,0), DST(32,1), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
#elif defined(USE_ARM_SCALER_ASM)
- case 1 : scale2x_8_arm(DST(8,0), DST(8,1), SRC(8,0), SRC(8,1), SRC(8,2), pixel_per_row); break;
- case 2 : scale2x_16_arm(DST(16,0), DST(16,1), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
- case 4 : scale2x_32_arm(DST(32,0), DST(32,1), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
+ case 1: scale2x_8_arm( DST( 8,0), DST( 8,1), SRC( 8,0), SRC( 8,1), SRC( 8,2), pixel_per_row); break;
+ case 2: scale2x_16_arm(DST(16,0), DST(16,1), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
+ case 4: scale2x_32_arm(DST(32,0), DST(32,1), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
#else
- case 1 : scale2x_8_def(DST(8,0), DST(8,1), SRC(8,0), SRC(8,1), SRC(8,2), pixel_per_row); break;
- case 2 : scale2x_16_def(DST(16,0), DST(16,1), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
- case 4 : scale2x_32_def(DST(32,0), DST(32,1), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
+ case 1: scale2x_8_def( DST( 8,0), DST( 8,1), SRC( 8,0), SRC( 8,1), SRC( 8,2), pixel_per_row); break;
+ case 2: scale2x_16_def(DST(16,0), DST(16,1), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
+ case 4: scale2x_32_def(DST(32,0), DST(32,1), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
#endif
}
}
@@ -67,9 +67,9 @@ static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const
*/
static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) {
switch (pixel) {
- case 1 : scale3x_8_def(DST(8,0), DST(8,1), DST(8,2), SRC(8,0), SRC(8,1), SRC(8,2), pixel_per_row); break;
- case 2 : scale3x_16_def(DST(16,0), DST(16,1), DST(16,2), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
- case 4 : scale3x_32_def(DST(32,0), DST(32,1), DST(32,2), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
+ case 1: scale3x_8_def( DST( 8,0), DST( 8,1), DST( 8,2), SRC( 8,0), SRC( 8,1), SRC( 8,2), pixel_per_row); break;
+ case 2: scale3x_16_def(DST(16,0), DST(16,1), DST(16,2), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
+ case 4: scale3x_32_def(DST(32,0), DST(32,1), DST(32,2), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
}
}
@@ -281,12 +281,12 @@ int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned
return -1;
switch (scale) {
- case 2 :
- case 3 :
+ case 2:
+ case 3:
if (height < 2)
return -1;
break;
- case 4 :
+ case 4:
if (height < 4)
return -1;
break;
@@ -294,14 +294,14 @@ int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
switch (scale) {
- case 2 :
- case 4 :
+ case 2:
+ case 4:
if (width < (16 / pixel))
return -1;
if (width % (8 / pixel) != 0)
return -1;
break;
- case 3 :
+ case 3:
if (width < 2)
return -1;
break;
@@ -329,13 +329,13 @@ int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned
void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
{
switch (scale) {
- case 2 :
+ case 2:
scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
break;
- case 3 :
+ case 3:
scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
break;
- case 4 :
+ case 4:
scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
break;
}
diff --git a/graphics/sjis.cpp b/graphics/sjis.cpp
index 45cf1cee90..877f314c69 100644
--- a/graphics/sjis.cpp
+++ b/graphics/sjis.cpp
@@ -334,16 +334,16 @@ const uint8 *FontTowns::getCharData(uint16 ch) const {
if (f >= 0xe0 && f <= 0xea) kanjiType = EKANJI;
if ((f > 0xe8 || (f == 0xe8 && base >= 0x9f)) || (f > 0x90 || (f == 0x90 && base >= 0x9f))) {
- c = 48; //correction
- p = -8; //correction
+ c = 48; // correction
+ p = -8; // correction
}
- if (kanjiType == KANA) {//Kana
+ if (kanjiType == KANA) {
chunk_f = (f - 0x81) * 2;
- } else if (kanjiType == KANJI) {//Standard Kanji
+ } else if (kanjiType == KANJI) { // Standard Kanji
p += f - 0x88;
chunk_f = c + 2 * p;
- } else if (kanjiType == EKANJI) {//Enhanced Kanji
+ } else if (kanjiType == EKANJI) { // Enhanced Kanji
p += f - 0xe0;
chunk_f = c + 2 * p;
}
@@ -360,37 +360,37 @@ const uint8 *FontTowns::getCharData(uint16 ch) const {
switch (base) {
case 0x3f:
- cr = 0; //3f
+ cr = 0; // 3f
if (kanjiType == KANA) chunk = 1;
else if (kanjiType == KANJI) chunk = 31;
else if (kanjiType == EKANJI) chunk = 111;
break;
case 0x5f:
- cr = 0; //5f
+ cr = 0; // 5f
if (kanjiType == KANA) chunk = 17;
else if (kanjiType == KANJI) chunk = 47;
else if (kanjiType == EKANJI) chunk = 127;
break;
case 0x7f:
- cr = -1; //80
+ cr = -1; // 80
if (kanjiType == KANA) chunk = 9;
else if (kanjiType == KANJI) chunk = 63;
else if (kanjiType == EKANJI) chunk = 143;
break;
case 0x9f:
- cr = 1; //9e
+ cr = 1; // 9e
if (kanjiType == KANA) chunk = 2;
else if (kanjiType == KANJI) chunk = 32;
else if (kanjiType == EKANJI) chunk = 112;
break;
case 0xbf:
- cr = 1; //be
+ cr = 1; // be
if (kanjiType == KANA) chunk = 18;
else if (kanjiType == KANJI) chunk = 48;
else if (kanjiType == EKANJI) chunk = 128;
break;
case 0xdf:
- cr = 1; //de
+ cr = 1; // de
if (kanjiType == KANA) chunk = 10;
else if (kanjiType == KANJI) chunk = 64;
else if (kanjiType == EKANJI) chunk = 144;
diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp
index a3037e5ad5..72a06f91ec 100644
--- a/graphics/thumbnail.cpp
+++ b/graphics/thumbnail.cpp
@@ -147,7 +147,11 @@ bool skipThumbnail(Common::SeekableReadStream &in) {
return true;
}
-Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) {
+bool loadThumbnail(Common::SeekableReadStream &in, Graphics::Surface *&thumbnail, bool skipThumbnail) {
+ if (skipThumbnail) {
+ return Graphics::skipThumbnail(in);
+ }
+
const uint32 position = in.pos();
ThumbnailHeader header;
HeaderState headerState = loadHeader(in, header, true);
@@ -160,32 +164,32 @@ Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) {
// stream at this point then.
if (headerState == kHeaderNone) {
in.seek(position, SEEK_SET);
- return 0;
+ return false;
} else if (headerState == kHeaderUnsupported) {
in.seek(header.size - (in.pos() - position), SEEK_CUR);
- return 0;
+ return false;
}
if (header.format.bytesPerPixel != 2 && header.format.bytesPerPixel != 4) {
warning("trying to load thumbnail with unsupported bit depth %d", header.format.bytesPerPixel);
- return 0;
+ return false;
}
- Graphics::Surface *const to = new Graphics::Surface();
- to->create(header.width, header.height, header.format);
+ thumbnail = new Graphics::Surface();
+ thumbnail->create(header.width, header.height, header.format);
- for (int y = 0; y < to->h; ++y) {
+ for (int y = 0; y < thumbnail->h; ++y) {
switch (header.format.bytesPerPixel) {
case 2: {
- uint16 *pixels = (uint16 *)to->getBasePtr(0, y);
- for (uint x = 0; x < to->w; ++x) {
+ uint16 *pixels = (uint16 *)thumbnail->getBasePtr(0, y);
+ for (uint x = 0; x < thumbnail->w; ++x) {
*pixels++ = in.readUint16BE();
}
} break;
case 4: {
- uint32 *pixels = (uint32 *)to->getBasePtr(0, y);
- for (uint x = 0; x < to->w; ++x) {
+ uint32 *pixels = (uint32 *)thumbnail->getBasePtr(0, y);
+ for (uint x = 0; x < thumbnail->w; ++x) {
*pixels++ = in.readUint32BE();
}
} break;
@@ -194,7 +198,7 @@ Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) {
assert(0);
}
}
- return to;
+ return true;
}
bool saveThumbnail(Common::WriteStream &out) {
diff --git a/graphics/thumbnail.h b/graphics/thumbnail.h
index cec3d02800..17ce856e23 100644
--- a/graphics/thumbnail.h
+++ b/graphics/thumbnail.h
@@ -52,7 +52,7 @@ bool skipThumbnail(Common::SeekableReadStream &in);
/**
* Loads a thumbnail from the given input stream.
*/
-Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in);
+bool loadThumbnail(Common::SeekableReadStream &in, Graphics::Surface *&thumbnail, bool skipThumbnail = false);
/**
* Saves a thumbnail to the given write stream.
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
index 849405410a..560df0ec35 100644
--- a/gui/EventRecorder.cpp
+++ b/gui/EventRecorder.cpp
@@ -600,13 +600,13 @@ void EventRecorder::setFileHeader() {
return;
}
TimeDate t;
- GameDescriptor desc = EngineMan.findGame(ConfMan.getActiveDomainName());
+ PlainGameDescriptor desc = EngineMan.findGame(ConfMan.getActiveDomainName());
g_system->getTimeAndDate(t);
if (_author.empty()) {
setAuthor("Unknown Author");
}
if (_name.empty()) {
- g_eventRec.setName(Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description());
+ g_eventRec.setName(Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description);
}
_playbackFile->getHeader().author = _author;
_playbackFile->getHeader().notes = _desc;
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index b16a6cfe4f..2dc4c063ab 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -211,8 +211,6 @@ ThemeEngine::ThemeEngine(Common::String id, GraphicsMode mode) :
_cursorWidth = _cursorHeight = 0;
_cursorPalSize = 0;
- _needPaletteUpdates = false;
-
// We prefer files in archive bundles over the common search paths.
_themeFiles.add("default", &SearchMan, 0, false);
}
@@ -853,38 +851,9 @@ void ThemeEngine::drawDD(DrawData type, const Common::Rect &r, uint32 dynamic, b
extendedRect.bottom += drawData->_shadowOffset - drawData->_backgroundOffset;
}
- if (forceRestore || drawData->_layer == kDrawLayerBackground)
- restoreBackground(extendedRect);
-
- if (drawData->_layer == _layerToDraw) {
- Common::List<Graphics::DrawStep>::const_iterator step;
- for (step = drawData->_steps.begin(); step != drawData->_steps.end(); ++step)
- _vectorRenderer->drawStep(area, *step, dynamic);
-
- addDirtyRect(extendedRect);
- }
-}
-
-void ThemeEngine::drawDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic,
- bool forceRestore) {
- WidgetDrawData *drawData = _widgets[type];
-
- if (!drawData)
- return;
-
- if (kDrawDataDefaults[type].parent != kDDNone && kDrawDataDefaults[type].parent != type)
- drawDDClip(kDrawDataDefaults[type].parent, r, clippingRect);
-
- Common::Rect area = r;
- area.clip(_screen.w, _screen.h);
-
- Common::Rect extendedRect = area;
- extendedRect.grow(kDirtyRectangleThreshold + drawData->_backgroundOffset);
- if (drawData->_shadowOffset > drawData->_backgroundOffset) {
- extendedRect.right += drawData->_shadowOffset - drawData->_backgroundOffset;
- extendedRect.bottom += drawData->_shadowOffset - drawData->_backgroundOffset;
+ if (!_clip.isEmpty()) {
+ extendedRect.clip(_clip);
}
- extendedRect.clip(clippingRect);
if (forceRestore || drawData->_layer == kDrawLayerBackground)
restoreBackground(extendedRect);
@@ -892,7 +861,7 @@ void ThemeEngine::drawDDClip(DrawData type, const Common::Rect &r, const Common:
if (drawData->_layer == _layerToDraw) {
Common::List<Graphics::DrawStep>::const_iterator step;
for (step = drawData->_steps.begin(); step != drawData->_steps.end(); ++step) {
- _vectorRenderer->drawStepClip(area, clippingRect, *step, dynamic);
+ _vectorRenderer->drawStepClip(area, _clip, *step, dynamic);
}
addDirtyRect(extendedRect);
@@ -913,31 +882,9 @@ void ThemeEngine::drawDDText(TextData type, TextColor color, const Common::Rect
if (dirty.isEmpty()) dirty = area;
else dirty.clip(area);
- if (restoreBg)
- restoreBackground(dirty);
-
- _vectorRenderer->setFgColor(_textColors[color]->r, _textColors[color]->g, _textColors[color]->b);
- _vectorRenderer->drawString(_texts[type]->_fontPtr, text, area, alignH, alignV, deltax, ellipsis, drawableTextArea);
-
- addDirtyRect(dirty);
-}
-
-void ThemeEngine::drawDDTextClip(TextData type, TextColor color, const Common::Rect &r,
- const Common::Rect &clippingArea, const Common::String &text, bool restoreBg,
- bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax,
- const Common::Rect &drawableTextArea) {
-
- if (type == kTextDataNone || !_texts[type] || _layerToDraw == kDrawLayerBackground)
- return;
-
- Common::Rect area = r;
- area.clip(_screen.w, _screen.h);
-
- Common::Rect dirty = drawableTextArea;
- if (dirty.isEmpty()) dirty = area;
- else dirty.clip(area);
-
- dirty.clip(clippingArea);
+ if (!_clip.isEmpty()) {
+ dirty.clip(_clip);
+ }
// HACK: One small pixel should be invisible enough
if (dirty.isEmpty()) dirty = Common::Rect(0, 0, 1, 1);
@@ -959,39 +906,12 @@ void ThemeEngine::drawBitmap(const Graphics::Surface *bitmap, const Common::Rect
area.clip(_screen.w, _screen.h);
if (alpha)
- _vectorRenderer->blitKeyBitmap(bitmap, r);
- else
- _vectorRenderer->blitSubSurface(bitmap, r);
-
- addDirtyRect(r);
-}
-
-void ThemeEngine::drawABitmap(Graphics::TransparentSurface *bitmap, const Common::Rect &r, AutoScaleMode autoscale, int alpha) {
- if (_layerToDraw == kDrawLayerBackground)
- return;
-
- Common::Rect area = r;
- area.clip(_screen.w, _screen.h);
-
- _vectorRenderer->blitAlphaBitmap(bitmap, area, autoscale, Graphics::DrawStep::kVectorAlignManual, Graphics::DrawStep::kVectorAlignManual, alpha);
-
- addDirtyRect(area);
-}
-
-void ThemeEngine::drawBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &r, const Common::Rect &clip, bool alpha) {
- if (_layerToDraw == kDrawLayerBackground)
- return;
-
- Common::Rect area = r;
- area.clip(_screen.w, _screen.h);
-
- if (alpha)
- _vectorRenderer->blitKeyBitmapClip(bitmap, area, clip);
+ _vectorRenderer->blitKeyBitmapClip(bitmap, area, _clip);
else
- _vectorRenderer->blitSubSurfaceClip(bitmap, area, clip);
+ _vectorRenderer->blitSubSurfaceClip(bitmap, area, _clip);
Common::Rect dirtyRect = area;
- dirtyRect.clip(clip);
+ dirtyRect.clip(_clip);
addDirtyRect(dirtyRect);
}
@@ -1014,42 +934,17 @@ void ThemeEngine::drawButton(const Common::Rect &r, const Common::String &str, W
dd = kDDButtonPressed;
drawDD(dd, r, 0, hints & WIDGET_CLEARBG);
- drawDDText(getTextData(dd), getTextColor(dd), r, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
-}
-
-void ThemeEngine::drawButtonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str, WidgetStateInfo state, uint16 hints) {
- if (!ready())
- return;
-
- DrawData dd = kDDButtonIdle;
-
- if (state == kStateEnabled)
- dd = kDDButtonIdle;
- else if (state == kStateHighlight)
- dd = kDDButtonHover;
- else if (state == kStateDisabled)
- dd = kDDButtonDisabled;
- else if (state == kStatePressed)
- dd = kDDButtonPressed;
-
- drawDDClip(dd, r, clippingRect, 0, hints & WIDGET_CLEARBG);
- drawDDTextClip(getTextData(dd), getTextColor(dd), r, clippingRect, str, false, true, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV);
+ drawDDText(getTextData(dd), getTextColor(dd), r, str, false, true, _widgets[dd]->_textAlignH,
+ _widgets[dd]->_textAlignV);
}
-void ThemeEngine::drawLineSeparator(const Common::Rect &r, WidgetStateInfo state) {
+void ThemeEngine::drawLineSeparator(const Common::Rect &r) {
if (!ready())
return;
drawDD(kDDSeparator, r);
}
-void ThemeEngine::drawLineSeparatorClip(const Common::Rect &r, const Common::Rect &clippingRect, WidgetStateInfo state) {
- if (!ready())
- return;
-
- drawDDClip(kDDSeparator, r, clippingRect);
-}
-
void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
if (!ready())
return;
@@ -1073,33 +968,8 @@ void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str,
r2.left = r2.right + checkBoxSize;
r2.right = r.right;
- drawDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
-}
-
-void ThemeEngine::drawCheckboxClip(const Common::Rect &r, const Common::Rect &clip, const Common::String &str, bool checked, WidgetStateInfo state) {
- if (!ready())
- return;
-
- Common::Rect r2 = r;
- DrawData dd = kDDCheckboxDefault;
-
- if (checked)
- dd = kDDCheckboxSelected;
-
- if (state == kStateDisabled)
- dd = kDDCheckboxDisabled;
-
- const int checkBoxSize = MIN((int)r.height(), getFontHeight());
-
- r2.bottom = r2.top + checkBoxSize;
- r2.right = r2.left + checkBoxSize;
-
- drawDDClip(dd, r2, clip);
-
- r2.left = r2.right + checkBoxSize;
- r2.right = r.right;
-
- drawDDTextClip(getTextData(dd), getTextColor(dd), r2, clip, str, true, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV);
+ drawDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDCheckboxDefault]->_textAlignH,
+ _widgets[dd]->_textAlignV);
}
void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) {
@@ -1123,35 +993,10 @@ void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &s
drawDD(dd, r2);
r2.left = r2.right + checkBoxSize;
- r2.right = r.right;
-
- drawDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV);
-}
-
-void ThemeEngine::drawRadiobuttonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str, bool checked, WidgetStateInfo state) {
- if (!ready())
- return;
-
- Common::Rect r2 = r;
- DrawData dd = kDDRadiobuttonDefault;
-
- if (checked)
- dd = kDDRadiobuttonSelected;
-
- if (state == kStateDisabled)
- dd = kDDRadiobuttonDisabled;
-
- const int checkBoxSize = MIN((int)r.height(), getFontHeight());
-
- r2.bottom = r2.top + checkBoxSize;
- r2.right = r2.left + checkBoxSize;
-
- drawDDClip(dd, r2, clippingRect);
-
- r2.left = r2.right + checkBoxSize;
r2.right = MAX(r2.left, r.right);
- drawDDTextClip(getTextData(dd), getTextColor(dd), r2, clippingRect, str, true, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV);
+ drawDDText(getTextData(dd), getTextColor(dd), r2, str, true, false, _widgets[kDDRadiobuttonDefault]->_textAlignH,
+ _widgets[dd]->_textAlignV);
}
void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) {
@@ -1167,34 +1012,14 @@ void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo s
Common::Rect r2 = r;
r2.setWidth(MIN((int16)width, r.width()));
-// r2.top++; r2.bottom--; r2.left++; r2.right--;
-
- drawWidgetBackground(r, 0, kWidgetBackgroundSlider, kStateEnabled);
-
- drawDD(dd, r2);
-}
-
-void ThemeEngine::drawSliderClip(const Common::Rect &r, const Common::Rect &clip, int width, WidgetStateInfo state) {
- if (!ready())
- return;
-
- DrawData dd = kDDSliderFull;
-
- if (state == kStateHighlight)
- dd = kDDSliderHover;
- else if (state == kStateDisabled)
- dd = kDDSliderDisabled;
-
- Common::Rect r2 = r;
- r2.setWidth(MIN((int16)width, r.width()));
// r2.top++; r2.bottom--; r2.left++; r2.right--;
- drawWidgetBackgroundClip(r, clip, 0, kWidgetBackgroundSlider, kStateEnabled);
+ drawWidgetBackground(r, 0, kWidgetBackgroundSlider);
- drawDDClip(dd, r2, clip);
+ drawDD(dd, r2);
}
-void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) {
+void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState) {
if (!ready())
return;
@@ -1204,46 +1029,22 @@ void ThemeEngine::drawScrollbar(const Common::Rect &r, int sliderY, int sliderHe
const int buttonExtra = (r.width() * 120) / 100;
r2.bottom = r2.top + buttonExtra;
- drawDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleUp);
+ drawDD(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2,
+ Graphics::VectorRenderer::kTriangleUp);
r2.translate(0, r.height() - r2.height());
- drawDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, Graphics::VectorRenderer::kTriangleDown);
+ drawDD(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2,
+ Graphics::VectorRenderer::kTriangleDown);
r2 = r;
r2.left += 1;
r2.right -= 1;
r2.top += sliderY;
r2.bottom = r2.top + sliderHeight;
-
- //r2.top += r.width() / 5;
- //r2.bottom -= r.width() / 5;
drawDD(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2);
}
-void ThemeEngine::drawScrollbarClip(const Common::Rect &r, const Common::Rect &clippingRect, int sliderY, int sliderHeight, ScrollbarState scrollState, WidgetStateInfo state) {
- if (!ready())
- return;
-
- drawDDClip(kDDScrollbarBase, r, clippingRect);
-
- Common::Rect r2 = r;
- const int buttonExtra = (r.width() * 120) / 100;
-
- r2.bottom = r2.top + buttonExtra;
- drawDDClip(scrollState == kScrollbarStateUp ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, clippingRect, Graphics::VectorRenderer::kTriangleUp);
-
- r2.translate(0, r.height() - r2.height());
- drawDDClip(scrollState == kScrollbarStateDown ? kDDScrollbarButtonHover : kDDScrollbarButtonIdle, r2, clippingRect, Graphics::VectorRenderer::kTriangleDown);
-
- r2 = r;
- r2.left += 1;
- r2.right -= 1;
- r2.top += sliderY;
- r2.bottom = r2.top + sliderHeight;
- drawDDClip(scrollState == kScrollbarStateSlider ? kDDScrollbarHandleHover : kDDScrollbarHandleIdle, r2, clippingRect);
-}
-
-void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype, WidgetStateInfo state) {
+void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground bgtype) {
if (!ready())
return;
@@ -1268,41 +1069,12 @@ void ThemeEngine::drawDialogBackground(const Common::Rect &r, DialogBackground b
drawDD(kDDDefaultBackground, r);
break;
case kDialogBackgroundNone:
- break;
- }
-}
-
-void ThemeEngine::drawDialogBackgroundClip(const Common::Rect &r, const Common::Rect &clip, DialogBackground bgtype, WidgetStateInfo state) {
- if (!ready())
- return;
-
- switch (bgtype) {
- case kDialogBackgroundMain:
- drawDDClip(kDDMainDialogBackground, r, clip);
- break;
-
- case kDialogBackgroundSpecial:
- drawDDClip(kDDSpecialColorBackground, r, clip);
- break;
-
- case kDialogBackgroundPlain:
- drawDDClip(kDDPlainColorBackground, r, clip);
- break;
-
- case kDialogBackgroundTooltip:
- drawDDClip(kDDTooltipBackground, r, clip);
- break;
-
- case kDialogBackgroundDefault:
- drawDDClip(kDDDefaultBackground, r, clip);
- break;
- case kDialogBackgroundNone:
// no op
break;
}
}
-void ThemeEngine::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo state) {
+void ThemeEngine::drawCaret(const Common::Rect &r, bool erase) {
if (!ready())
return;
@@ -1312,17 +1084,7 @@ void ThemeEngine::drawCaret(const Common::Rect &r, bool erase, WidgetStateInfo s
drawDD(kDDCaret, r);
}
-void ThemeEngine::drawCaretClip(const Common::Rect &r, const Common::Rect &clip, bool erase, WidgetStateInfo state) {
- if (!ready())
- return;
-
- if (erase) {
- restoreBackground(r);
- } else
- drawDDClip(kDDCaret, r, clip);
-}
-
-void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state, Graphics::TextAlign align) {
+void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax, WidgetStateInfo state) {
if (!ready())
return;
@@ -1337,55 +1099,21 @@ void ThemeEngine::drawPopUpWidget(const Common::Rect &r, const Common::String &s
drawDD(dd, r);
- if (!sel.empty()) {
- Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
- drawDDText(getTextData(dd), getTextColor(dd), text, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax);
- }
-}
-
-void ThemeEngine::drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect &clip, const Common::String &sel, int deltax, WidgetStateInfo state, Graphics::TextAlign align) {
- if (!ready())
- return;
-
- DrawData dd = kDDPopUpIdle;
-
- if (state == kStateEnabled)
- dd = kDDPopUpIdle;
- else if (state == kStateHighlight)
- dd = kDDPopUpHover;
- else if (state == kStateDisabled)
- dd = kDDPopUpDisabled;
-
- drawDDClip(dd, r, clip);
-
if (!sel.empty() && r.width() >= 13 && r.height() >= 1) {
Common::Rect text(r.left + 3, r.top + 1, r.right - 10, r.bottom);
- drawDDTextClip(getTextData(dd), getTextColor(dd), text, clip, sel, true, false, _widgets[dd]->_textAlignH, _widgets[dd]->_textAlignV, deltax);
+ drawDDText(getTextData(dd), getTextColor(dd), text, sel, true, false, _widgets[dd]->_textAlignH,
+ _widgets[dd]->_textAlignV, deltax);
}
}
-void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) {
+void ThemeEngine::drawSurface(const Common::Rect &r, const Graphics::Surface &surface, bool themeTrans) {
if (!ready())
return;
drawBitmap(&surface, r, themeTrans);
}
-void ThemeEngine::drawASurface(const Common::Rect &r, Graphics::TransparentSurface &surface, AutoScaleMode autoscale, int alpha) {
- if (!ready())
- return;
-
- drawABitmap(&surface, r, autoscale, alpha);
-}
-
-void ThemeEngine::drawSurfaceClip(const Common::Rect &r, const Common::Rect &clip, const Graphics::Surface &surface, WidgetStateInfo state, int alpha, bool themeTrans) {
- if (!ready())
- return;
-
- drawBitmapClip(&surface, r, clip, themeTrans);
-}
-
-void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background, WidgetStateInfo state) {
+void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background) {
if (!ready())
return;
@@ -1408,64 +1136,14 @@ void ThemeEngine::drawWidgetBackground(const Common::Rect &r, uint16 hints, Widg
}
}
-void ThemeEngine::drawWidgetBackgroundClip(const Common::Rect &r, const Common::Rect &clip, uint16 hints, WidgetBackground background, WidgetStateInfo state) {
- if (!ready())
- return;
-
- switch (background) {
- case kWidgetBackgroundBorderSmall:
- drawDDClip(kDDWidgetBackgroundSmall, r, clip);
- break;
-
- case kWidgetBackgroundEditText:
- drawDDClip(kDDWidgetBackgroundEditText, r, clip);
- break;
-
- case kWidgetBackgroundSlider:
- drawDDClip(kDDWidgetBackgroundSlider, r, clip);
- break;
-
- default:
- drawDDClip(kDDWidgetBackgroundDefault, r, clip);
- break;
- }
-}
-
-void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
- if (!ready())
- return;
-
- drawDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight));
-
- for (int i = 0; i < (int)tabs.size(); ++i) {
- if (i == active)
- continue;
-
- if (r.left + i * tabWidth > r.right || r.left + (i + 1) * tabWidth > r.right)
- continue;
-
- Common::Rect tabRect(r.left + i * tabWidth, r.top, r.left + (i + 1) * tabWidth, r.top + tabHeight);
- drawDD(kDDTabInactive, tabRect);
- drawDDText(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
- }
-
- if (active >= 0 &&
- (r.left + active * tabWidth < r.right) && (r.left + (active + 1) * tabWidth < r.right)) {
- Common::Rect tabRect(r.left + active * tabWidth, r.top, r.left + (active + 1) * tabWidth, r.top + tabHeight);
- const uint16 tabLeft = active * tabWidth;
- const uint16 tabRight = MAX(r.right - tabRect.right, 0);
- drawDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF));
- drawDDText(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
- }
-}
-
-void ThemeEngine::drawTabClip(const Common::Rect &r, const Common::Rect &clip, int tabHeight, const Common::Array<int> &tabWidths, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state) {
+void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, const Common::Array<int> &tabWidths,
+ const Common::Array<Common::String> &tabs, int active) {
if (!ready())
return;
assert(tabs.size() == tabWidths.size());
- drawDDClip(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight), clip);
+ drawDD(kDDTabBackground, Common::Rect(r.left, r.top, r.right, r.top + tabHeight));
int width = 0;
int activePos = -1;
@@ -1480,20 +1158,24 @@ void ThemeEngine::drawTabClip(const Common::Rect &r, const Common::Rect &clip, i
Common::Rect tabRect(r.left + width, r.top, r.left + width + tabWidths[i], r.top + tabHeight);
- drawDDClip(kDDTabInactive, tabRect, clip);
- drawDDTextClip(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, clip, tabs[i], false, false, _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
+ drawDD(kDDTabInactive, tabRect);
+ drawDDText(getTextData(kDDTabInactive), getTextColor(kDDTabInactive), tabRect, tabs[i], false, false,
+ _widgets[kDDTabInactive]->_textAlignH, _widgets[kDDTabInactive]->_textAlignV);
}
if (activePos >= 0) {
Common::Rect tabRect(r.left + activePos, r.top, r.left + activePos + tabWidths[active], r.top + tabHeight);
const uint16 tabLeft = activePos;
const uint16 tabRight = MAX(r.right - tabRect.right, 0);
- drawDDClip(kDDTabActive, tabRect, clip, (tabLeft << 16) | (tabRight & 0xFFFF));
- drawDDTextClip(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, clip, tabs[active], false, false, _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
+ drawDD(kDDTabActive, tabRect, (tabLeft << 16) | (tabRight & 0xFFFF));
+ drawDDText(getTextData(kDDTabActive), getTextColor(kDDTabActive), tabRect, tabs[active], false, false,
+ _widgets[kDDTabActive]->_textAlignH, _widgets[kDDTabActive]->_textAlignV);
}
}
-void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) {
+void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state,
+ Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis,
+ FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) {
if (!ready())
return;
@@ -1566,80 +1248,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid
drawDDText(textId, colorId, r, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea);
}
-void ThemeEngine::drawTextClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) {
- if (!ready())
- return;
-
- TextColor colorId = kTextColorMAX;
-
- switch (color) {
- case kFontColorNormal:
- if (inverted) {
- colorId = kTextColorNormalInverted;
- } else {
- switch (state) {
- case kStateDisabled:
- colorId = kTextColorNormalDisabled;
- break;
-
- case kStateHighlight:
- colorId = kTextColorNormalHover;
- break;
-
- case kStateEnabled:
- case kStatePressed:
- colorId = kTextColorNormal;
- break;
- }
- }
- break;
-
- case kFontColorAlternate:
- if (inverted) {
- colorId = kTextColorAlternativeInverted;
- } else {
- switch (state) {
- case kStateDisabled:
- colorId = kTextColorAlternativeDisabled;
- break;
-
- case kStateHighlight:
- colorId = kTextColorAlternativeHover;
- break;
-
- case kStateEnabled:
- case kStatePressed:
- colorId = kTextColorAlternative;
- break;
- }
- }
- break;
-
- default:
- return;
- }
-
- TextData textId = fontStyleToData(font);
-
- switch (inverted) {
- case kTextInversion:
- drawDDClip(kDDTextSelectionBackground, r, clippingArea);
- restore = false;
- break;
-
- case kTextInversionFocus:
- drawDDClip(kDDTextSelectionFocusBackground, r, clippingArea);
- restore = false;
- break;
-
- default:
- break;
- }
-
- drawDDTextClip(textId, colorId, r, clippingArea, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea);
-}
-
-void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state, FontColor color) {
+void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, FontColor color) {
if (!ready())
return;
@@ -1648,20 +1257,7 @@ void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font
uint32 rgbColor = _overlayFormat.RGBToColor(_textColors[color]->r, _textColors[color]->g, _textColors[color]->b);
- restoreBackground(charArea);
- font->drawChar(&_screen, ch, charArea.left, charArea.top, rgbColor);
- addDirtyRect(charArea);
-}
-
-void ThemeEngine::drawCharClip(const Common::Rect &r, const Common::Rect &clip, byte ch, const Graphics::Font *font, WidgetStateInfo state, FontColor color) {
- if (!ready())
- return;
-
- Common::Rect charArea = r;
- charArea.clip(_screen.w, _screen.h);
- if (!clip.isEmpty()) charArea.clip(clip);
-
- uint32 rgbColor = _overlayFormat.RGBToColor(_textColors[color]->r, _textColors[color]->g, _textColors[color]->b);
+ // TODO: Handle clipping when drawing chars
restoreBackground(charArea);
font->drawChar(&_screen, ch, charArea.left, charArea.top, rgbColor);
@@ -2282,4 +1878,10 @@ void ThemeEngine::drawToScreen() {
_vectorRenderer->setSurface(&_screen);
}
+Common::Rect ThemeEngine::swapClipRect(const Common::Rect &newRect) {
+ Common::Rect oldRect = _clip;
+ _clip = newRect;
+ return oldRect;
+}
+
} // End of namespace GUI.
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 5675f0c5d7..984ac0f083 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -376,75 +376,56 @@ public:
//@}
+ /**
+ * Set the clipping rect to be used by the widget drawing methods defined below.
+ *
+ * Widgets are not drawn outside of the clipping rect. Widgets that overlap the
+ * clipping rect are drawn partially.
+ *
+ * @param newRect The new clipping rect
+ * @return The previous clipping rect
+ */
+ Common::Rect swapClipRect(const Common::Rect &newRect);
/** @name WIDGET DRAWING METHODS */
//@{
- void drawWidgetBackground(const Common::Rect &r, uint16 hints,
- WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
- void drawWidgetBackgroundClip(const Common::Rect &r, const Common::Rect &clippingArea, uint16 hints,
- WidgetBackground background = kWidgetBackgroundPlain, WidgetStateInfo state = kStateEnabled);
-
- void drawButton(const Common::Rect &r, const Common::String &str,
- WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
- void drawButtonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
- WidgetStateInfo state = kStateEnabled, uint16 hints = 0);
+ void drawWidgetBackground(const Common::Rect &r, uint16 hints, WidgetBackground background = kWidgetBackgroundPlain);
- void drawSurface(const Common::Rect &r, const Graphics::Surface &surface,
- WidgetStateInfo state = kStateEnabled, int alpha = 255, bool themeTrans = false);
- void drawSurfaceClip(const Common::Rect &r, const Common::Rect &clippingRect, const Graphics::Surface &surface,
- WidgetStateInfo state = kStateEnabled, int alpha = 255, bool themeTrans = false);
+ void drawButton(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled,
+ uint16 hints = 0);
- void drawASurface(const Common::Rect &r, Graphics::TransparentSurface &surface, AutoScaleMode autoscale, int alpha);
+ void drawSurface(const Common::Rect &r, const Graphics::Surface &surface, bool themeTrans = false);
- void drawSlider(const Common::Rect &r, int width,
- WidgetStateInfo state = kStateEnabled);
- void drawSliderClip(const Common::Rect &r, const Common::Rect &clippingRect, int width,
- WidgetStateInfo state = kStateEnabled);
+ void drawSlider(const Common::Rect &r, int width, WidgetStateInfo state = kStateEnabled);
- void drawCheckbox(const Common::Rect &r, const Common::String &str,
- bool checked, WidgetStateInfo state = kStateEnabled);
- void drawCheckboxClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
- bool checked, WidgetStateInfo state = kStateEnabled);
+ void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked,
+ WidgetStateInfo state = kStateEnabled);
- void drawRadiobutton(const Common::Rect &r, const Common::String &str,
- bool checked, WidgetStateInfo state = kStateEnabled);
- void drawRadiobuttonClip(const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &str,
- bool checked, WidgetStateInfo state = kStateEnabled);
+ void drawRadiobutton(const Common::Rect &r, const Common::String &str, bool checked,
+ WidgetStateInfo state = kStateEnabled);
- void drawTab(const Common::Rect &r, int tabHeight, int tabWidth,
- const Common::Array<Common::String> &tabs, int active, uint16 hints,
- int titleVPad, WidgetStateInfo state = kStateEnabled);
- void drawTabClip(const Common::Rect &r, const Common::Rect &clippingRect, int tabHeight, const Common::Array<int> &tabWidths,
- const Common::Array<Common::String> &tabs, int active, uint16 hints,
- int titleVPad, WidgetStateInfo state = kStateEnabled);
+ void drawTab(const Common::Rect &r, int tabHeight, const Common::Array<int> &tabWidths,
+ const Common::Array<Common::String> &tabs, int active);
- void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight,
- ScrollbarState, WidgetStateInfo state = kStateEnabled);
- void drawScrollbarClip(const Common::Rect &r, const Common::Rect &clippingRect, int sliderY, int sliderHeight,
- ScrollbarState scrollState, WidgetStateInfo state = kStateEnabled);
+ void drawScrollbar(const Common::Rect &r, int sliderY, int sliderHeight, ScrollbarState scrollState);
- void drawPopUpWidget(const Common::Rect &r, const Common::String &sel,
- int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
- void drawPopUpWidgetClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &sel,
- int deltax, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignLeft);
+ void drawPopUpWidget(const Common::Rect &r, const Common::String &sel, int deltax,
+ WidgetStateInfo state = kStateEnabled);
- void drawCaret(const Common::Rect &r, bool erase,
- WidgetStateInfo state = kStateEnabled);
- void drawCaretClip(const Common::Rect &r, const Common::Rect &clip, bool erase,
- WidgetStateInfo state = kStateEnabled);
+ void drawCaret(const Common::Rect &r, bool erase);
- void drawLineSeparator(const Common::Rect &r, WidgetStateInfo state = kStateEnabled);
- void drawLineSeparatorClip(const Common::Rect &r, const Common::Rect &clippingArea, WidgetStateInfo state = kStateEnabled);
+ void drawLineSeparator(const Common::Rect &r);
- void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled);
- void drawDialogBackgroundClip(const Common::Rect &r, const Common::Rect &clip, DialogBackground type, WidgetStateInfo state = kStateEnabled);
+ void drawDialogBackground(const Common::Rect &r, DialogBackground type);
- void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
- void drawTextClip(const Common::Rect &r, const Common::Rect &clippingArea, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
+ void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled,
+ Graphics::TextAlign align = Graphics::kTextAlignCenter,
+ TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true,
+ FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true,
+ const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
- void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
- void drawCharClip(const Common::Rect &r, const Common::Rect &clippingArea, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal);
+ void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, FontColor color = kFontColorNormal);
//@}
@@ -606,15 +587,6 @@ public:
int getGraphicsMode() const { return _graphicsMode; }
protected:
- /**
- * Initializes the drawing screen surfaces, _screen and _backBuffer.
- * If the surfaces already exist, they are cleared and re-initialized.
- *
- * @param backBuffer Sets whether the _backBuffer surface should be initialized.
- * @template PixelType C type which specifies the size of each pixel.
- * Defaults to uint16 (2 BPP for the surfaces)
- */
- template<typename PixelType> void screenInit(bool backBuffer = true);
/**
* Loads the given theme into the ThemeEngine.
@@ -657,21 +629,11 @@ protected:
* These functions are called from all the Widget drawing methods.
*/
void drawDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool forceRestore = false);
- void drawDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic = 0,
- bool forceRestore = false);
void drawDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft,
TextAlignVertical alignV = kTextAlignVTop, int deltax = 0,
const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
- void drawDDTextClip(TextData type, TextColor color, const Common::Rect &r, const Common::Rect &clippingRect,
- const Common::String &text, bool restoreBg,
- bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft,
- TextAlignVertical alignV = kTextAlignVTop, int deltax = 0,
- const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
- void drawBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha);
- void drawBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &clippingRect, const Common::Rect &r,
- bool alpha);
- void drawABitmap(Graphics::TransparentSurface *bitmap, const Common::Rect &r, AutoScaleMode autoscale, int alpha);
+ void drawBitmap(const Graphics::Surface *bitmap, const Common::Rect &clippingRect, bool alpha);
/**
* DEBUG: Draws a white square and writes some text next to it.
@@ -732,7 +694,6 @@ protected:
GraphicsMode _graphicsMode;
/** Font info. */
- Common::String _fontName;
const Graphics::Font *_font;
/**
@@ -773,10 +734,11 @@ protected:
MAX_CURS_COLORS = 255
};
byte *_cursor;
- bool _needPaletteUpdates;
uint _cursorWidth, _cursorHeight;
byte _cursorPal[3 * MAX_CURS_COLORS];
byte _cursorPalSize;
+
+ Common::Rect _clip;
};
} // End of namespace GUI.
diff --git a/gui/Tooltip.cpp b/gui/Tooltip.cpp
index bcaa8cee2a..50f10272fb 100644
--- a/gui/Tooltip.cpp
+++ b/gui/Tooltip.cpp
@@ -64,7 +64,8 @@ void Tooltip::drawDialog(DrawLayer layerToDraw) {
for (Common::StringArray::const_iterator i = _wrappedLines.begin(); i != _wrappedLines.end(); ++i, ++num) {
g_gui.theme()->drawText(
- Common::Rect(_x + 1, _y + 1 + num * h, _x + 1 +_w, _y + 1+ (num + 1) * h), *i,
+ Common::Rect(_x + 1, _y + 1 + num * h, _x + 1 + _w, _y + 1 + (num + 1) * h),
+ *i,
ThemeEngine::kStateEnabled,
Graphics::kTextAlignLeft,
ThemeEngine::kTextInversionNone,
diff --git a/gui/Tooltip.h b/gui/Tooltip.h
index 64496fff9d..e812ebed8c 100644
--- a/gui/Tooltip.h
+++ b/gui/Tooltip.h
@@ -42,29 +42,29 @@ public:
void drawDialog(DrawLayer layerToDraw) override;
- virtual void receivedFocus(int x = -1, int y = -1) {}
+ virtual void receivedFocus(int x = -1, int y = -1) override {}
protected:
- virtual void handleMouseDown(int x, int y, int button, int clickCount) {
+ virtual void handleMouseDown(int x, int y, int button, int clickCount) override {
close();
_parent->handleMouseDown(x + (getAbsX() - _parent->getAbsX()), y + (getAbsY() - _parent->getAbsY()), button, clickCount);
}
- virtual void handleMouseUp(int x, int y, int button, int clickCount) {
+ virtual void handleMouseUp(int x, int y, int button, int clickCount) override {
close();
_parent->handleMouseUp(x + (getAbsX() - _parent->getAbsX()), y + (getAbsY() - _parent->getAbsY()), button, clickCount);
}
- virtual void handleMouseWheel(int x, int y, int direction) {
+ virtual void handleMouseWheel(int x, int y, int direction) override {
close();
_parent->handleMouseWheel(x + (getAbsX() - _parent->getAbsX()), y + (getAbsX() - _parent->getAbsX()), direction);
}
- virtual void handleKeyDown(Common::KeyState state) {
+ virtual void handleKeyDown(Common::KeyState state) override {
close();
_parent->handleKeyDown(state);
}
- virtual void handleKeyUp(Common::KeyState state) {
+ virtual void handleKeyUp(Common::KeyState state) override {
close();
_parent->handleKeyUp(state);
}
- virtual void handleMouseMoved(int x, int y, int button) {
+ virtual void handleMouseMoved(int x, int y, int button) override {
close();
}
diff --git a/gui/about.cpp b/gui/about.cpp
index 0d70f3dd42..869e0f82ba 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -242,7 +242,9 @@ void AboutDialog::drawDialog(DrawLayer layerToDraw) {
str++;
if (*str)
- g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, ThemeEngine::kTextInversionNone, 0, false, ThemeEngine::kFontStyleBold, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
+ g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()),
+ str, state, align, ThemeEngine::kTextInversionNone, 0, false,
+ ThemeEngine::kFontStyleBold, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
y += _lineHeight;
}
}
diff --git a/gui/about.h b/gui/about.h
index b6510772bf..a6b13cd1da 100644
--- a/gui/about.h
+++ b/gui/about.h
@@ -46,15 +46,15 @@ protected:
public:
AboutDialog();
- void open();
- void close();
+ void open() override;
+ void close() override;
void drawDialog(DrawLayer layerToDraw) override;
- void handleTickle();
- void handleMouseUp(int x, int y, int button, int clickCount);
- void handleKeyDown(Common::KeyState state);
- void handleKeyUp(Common::KeyState state);
+ void handleTickle() override;
+ void handleMouseUp(int x, int y, int button, int clickCount) override;
+ void handleKeyDown(Common::KeyState state) override;
+ void handleKeyUp(Common::KeyState state) override;
- void reflowLayout();
+ void reflowLayout() override;
};
} // End of namespace GUI
diff --git a/gui/console.cpp b/gui/console.cpp
index 1c7be32286..5e9def8740 100644
--- a/gui/console.cpp
+++ b/gui/console.cpp
@@ -243,9 +243,19 @@ void ConsoleDialog::handleMouseWheel(int x, int y, int direction) {
_scrollBar->handleMouseWheel(x, y, direction);
}
-void ConsoleDialog::handleKeyDown(Common::KeyState state) {
- int i;
+Common::String ConsoleDialog::getUserInput() {
+ assert(_promptEndPos >= _promptStartPos);
+ int len = _promptEndPos - _promptStartPos;
+
+ // Copy the user input to str
+ Common::String str;
+ for (int i = 0; i < len; i++)
+ str.insertChar(buffer(_promptStartPos + i), i);
+ return str;
+}
+
+void ConsoleDialog::handleKeyDown(Common::KeyState state) {
if (_slideMode != kNoSlideMode)
return;
@@ -257,26 +267,16 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) {
nextLine();
- assert(_promptEndPos >= _promptStartPos);
- int len = _promptEndPos - _promptStartPos;
bool keepRunning = true;
-
- if (len > 0) {
-
- Common::String str;
-
- // Copy the user input to str
- for (i = 0; i < len; i++)
- str.insertChar(buffer(_promptStartPos + i), i);
-
+ Common::String userInput = getUserInput();
+ if (!userInput.empty()) {
// Add the input to the history
- addToHistory(str);
+ addToHistory(userInput);
// Pass it to the input callback, if any
if (_callbackProc)
- keepRunning = (*_callbackProc)(this, str.c_str(), _callbackRefCon);
-
+ keepRunning = (*_callbackProc)(this, userInput.c_str(), _callbackRefCon);
}
print(PROMPT);
@@ -311,7 +311,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) {
char *str = new char[len + 1];
// Copy the user input to str
- for (i = 0; i < len; i++)
+ for (int i = 0; i < len; i++)
str[i] = buffer(_promptStartPos + i);
str[len] = '\0';
@@ -504,7 +504,7 @@ void ConsoleDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
}
}
-void ConsoleDialog::specialKeys(int keycode) {
+void ConsoleDialog::specialKeys(Common::KeyCode keycode) {
switch (keycode) {
case Common::KEYCODE_a:
_currentPos = _promptStartPos;
@@ -528,6 +528,23 @@ void ConsoleDialog::specialKeys(int keycode) {
killLastWord();
g_gui.scheduleTopDialogRedraw();
break;
+ case Common::KEYCODE_v:
+ if (g_system->hasFeature(OSystem::kFeatureClipboardSupport) && g_system->hasTextInClipboard()) {
+ Common::String text = g_system->getTextFromClipboard();
+ insertIntoPrompt(text.c_str());
+ scrollToCurrent();
+ drawLine(pos2line(_currentPos));
+ }
+ break;
+ case Common::KEYCODE_c:
+ if (g_system->hasFeature(OSystem::kFeatureClipboardSupport)) {
+ Common::String userInput = getUserInput();
+ if (!userInput.empty())
+ g_system->setTextInClipboard(userInput);
+ }
+ break;
+ default:
+ break;
}
}
@@ -712,7 +729,7 @@ void ConsoleDialog::drawCaret(bool erase) {
int y = _y + _topPadding + displayLine * kConsoleLineHeight;
_caretVisible = !erase;
- g_gui.theme()->drawCaret(Common::Rect(x, y, x+1, y+kConsoleLineHeight), erase);
+ g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + kConsoleLineHeight), erase);
}
void ConsoleDialog::scrollToCurrent() {
diff --git a/gui/console.h b/gui/console.h
index 04ad5526a6..2445005afc 100644
--- a/gui/console.h
+++ b/gui/console.h
@@ -69,29 +69,29 @@ public:
protected:
enum {
- kBufferSize = 32768,
+ kBufferSize = 32768,
kCharsPerLine = 128,
- kHistorySize = 20
+ kHistorySize = 20
};
const Graphics::Font *_font;
- char _buffer[kBufferSize];
- int _linesInBuffer;
+ char _buffer[kBufferSize];
+ int _linesInBuffer;
- int _pageWidth;
- int _linesPerPage;
+ int _pageWidth;
+ int _linesPerPage;
- int _currentPos;
- int _scrollLine;
- int _firstLineInBuffer;
+ int _currentPos;
+ int _scrollLine;
+ int _firstLineInBuffer;
- int _promptStartPos;
- int _promptEndPos;
+ int _promptStartPos;
+ int _promptEndPos;
- bool _caretVisible;
- uint32 _caretTime;
+ bool _caretVisible;
+ uint32 _caretTime;
enum SlideMode {
kNoSlideMode,
@@ -99,8 +99,8 @@ protected:
kDownSlideMode
};
- SlideMode _slideMode;
- uint32 _slideTime;
+ SlideMode _slideMode;
+ uint32 _slideTime;
ScrollBarWidget *_scrollBar;
@@ -120,25 +120,25 @@ protected:
float _widthPercent, _heightPercent;
- int _leftPadding;
- int _rightPadding;
- int _topPadding;
- int _bottomPadding;
+ int _leftPadding;
+ int _rightPadding;
+ int _topPadding;
+ int _bottomPadding;
void slideUpAndClose();
public:
ConsoleDialog(float widthPercent, float heightPercent);
- void open();
- void close();
+ void open() override;
+ void close() override;
void drawDialog(DrawLayer layerToDraw) override;
- void handleTickle();
- void reflowLayout();
- void handleMouseWheel(int x, int y, int direction);
- void handleKeyDown(Common::KeyState state);
- void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+ void handleTickle() override;
+ void reflowLayout() override;
+ void handleMouseWheel(int x, int y, int direction) override;
+ void handleKeyDown(Common::KeyState state) override;
+ void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
int printFormat(int dummy, const char *format, ...) GCC_PRINTF(3, 4);
int vprintFormat(int dummy, const char *format, va_list argptr);
@@ -174,11 +174,12 @@ protected:
void print(const char *str);
void updateScrollBuffer();
void scrollToCurrent();
+ Common::String getUserInput();
void defaultKeyDownHandler(Common::KeyState &state);
// Line editing
- void specialKeys(int keycode);
+ void specialKeys(Common::KeyCode keycode);
void nextLine();
void killChar();
void killLine();
diff --git a/gui/credits.h b/gui/credits.h
index 8f3f934024..82cc27bf8b 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -362,6 +362,13 @@ static const char *credits[] = {
"C0""Einar Johan T. S\370m\345en",
"C0""Tobia Tesan",
"",
+"C1""Xeen",
+"C0""Paul Gilbert",
+"C0""David Goldsmith",
+"C2""(analysis)",
+"C0""Matt Taylor",
+"C2""(analysis)",
+"",
"C1""Z-Vision",
"C0""Adrian Astley",
"C0""Filippos Karapetis",
diff --git a/gui/debugger.cpp b/gui/debugger.cpp
index ce4661e9cb..9b559d8bb9 100644
--- a/gui/debugger.cpp
+++ b/gui/debugger.cpp
@@ -404,17 +404,17 @@ void Debugger::splitCommand(char *input, int &argc, const char **argv) {
byte c;
enum states { DULL, IN_WORD, IN_STRING } state = DULL;
const char *paramStart = nullptr;
-
+
argc = 0;
for (char *p = input; *p; ++p) {
c = (byte)*p;
switch (state) {
- case DULL:
+ case DULL:
// not in a word, not in a double quoted string
if (isspace(c))
break;
-
+
// not a space -- if it's a double quote we go to IN_STRING, else to IN_WORD
if (c == '"') {
state = IN_STRING;
@@ -470,7 +470,7 @@ bool Debugger::tabComplete(const char *input, Common::String &completion) const
CommandsMap::const_iterator i, e = _cmds.end();
for (i = _cmds.begin(); i != e; ++i) {
- if (i->_key.hasPrefix(input)) {
+ if (i->_key.hasPrefixIgnoreCase(input)) {
uint commandlen = i->_key.size();
if (commandlen == inputlen) { // perfect match, so no tab completion possible
return false;
diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index 6f4e8e6b44..560c29174a 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -167,7 +167,7 @@ void Dialog::drawDialog(DrawLayer layerToDraw) {
return;
g_gui.theme()->_layerToDraw = layerToDraw;
- g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _backgroundType);
+ g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x + _w, _y + _h), _backgroundType);
markWidgetsAsDirty();
drawWidgets();
diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp
index 4192c4058a..80fb41fad1 100644
--- a/gui/editgamedialog.cpp
+++ b/gui/editgamedialog.cpp
@@ -95,7 +95,7 @@ protected:
}
};
-EditGameDialog::EditGameDialog(const String &domain, const String &desc)
+EditGameDialog::EditGameDialog(const String &domain)
: OptionsDialog(domain, "GameOptions") {
// Retrieve all game specific options.
const Plugin *plugin = nullptr;
@@ -106,7 +106,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
gameId = domain;
// Retrieve the plugin, since we need to access the engine's MetaEngine
// implementation.
- EngineMan.findGame(gameId, &plugin);
+ PlainGameDescriptor pgd = EngineMan.findGame(gameId, &plugin);
if (plugin) {
_engineOptions = plugin->get<MetaEngine>().getExtraGuiOptions(domain);
} else {
@@ -120,8 +120,8 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
// GAME: Determine the description string
String description(ConfMan.get("description", domain));
- if (description.empty() && !desc.empty()) {
- description = desc;
+ if (description.empty() && pgd.description) {
+ description = pgd.description;
}
// GUI: Add tab widget
@@ -384,35 +384,35 @@ void EditGameDialog::open() {
void EditGameDialog::apply() {
ConfMan.set("description", _descriptionWidget->getEditString(), _domain);
-
+
Common::Language lang = (Common::Language)_langPopUp->getSelectedTag();
if (lang < 0)
ConfMan.removeKey("language", _domain);
else
ConfMan.set("language", Common::getLanguageCode(lang), _domain);
-
+
String gamePath(_gamePathWidget->getLabel());
if (!gamePath.empty())
ConfMan.set("path", gamePath, _domain);
-
+
String extraPath(_extraPathWidget->getLabel());
if (!extraPath.empty() && (extraPath != _c("None", "path")))
ConfMan.set("extrapath", extraPath, _domain);
else
ConfMan.removeKey("extrapath", _domain);
-
+
String savePath(_savePathWidget->getLabel());
if (!savePath.empty() && (savePath != _("Default")))
ConfMan.set("savepath", savePath, _domain);
else
ConfMan.removeKey("savepath", _domain);
-
+
Common::Platform platform = (Common::Platform)_platformPopUp->getSelectedTag();
if (platform < 0)
ConfMan.removeKey("platform", _domain);
else
ConfMan.set("platform", Common::getPlatformCode(platform), _domain);
-
+
// Set the state of engine-specific checkboxes
for (uint i = 0; i < _engineOptions.size(); i++) {
ConfMan.setBool(_engineOptions[i].configOption, _engineCheckboxes[i]->getState(), _domain);
diff --git a/gui/editgamedialog.h b/gui/editgamedialog.h
index a317e364c6..7c6a08eb3c 100644
--- a/gui/editgamedialog.h
+++ b/gui/editgamedialog.h
@@ -40,8 +40,6 @@ class StaticTextWidget;
class EditTextWidget;
class SaveLoadChooser;
-Common::String addGameToConf(const GameDescriptor &result);
-
/*
* A dialog that allows the user to edit a config game entry.
* TODO: add widgets for some/all of the following
@@ -62,7 +60,7 @@ class EditGameDialog : public OptionsDialog {
typedef Common::String String;
typedef Common::Array<Common::String> StringArray;
public:
- EditGameDialog(const String &domain, const String &desc);
+ EditGameDialog(const String &domain);
void open();
virtual void apply();
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 4fe1ae79c8..214dc30834 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -45,6 +45,7 @@
#include "gui/EventRecorder.h"
#endif
#include "gui/saveload.h"
+#include "gui/unknown-game-dialog.h"
#include "gui/widgets/edittext.h"
#include "gui/widgets/list.h"
#include "gui/widgets/tab.h"
@@ -266,9 +267,9 @@ void LauncherDialog::updateListing() {
if (gameid.empty())
gameid = iter->_key;
if (description.empty()) {
- GameDescriptor g = EngineMan.findGame(gameid);
- if (g.contains("description"))
- description = g.description();
+ PlainGameDescriptor g = EngineMan.findGame(gameid);
+ if (g.description)
+ description = g.description;
}
if (description.empty()) {
@@ -375,45 +376,6 @@ void LauncherDialog::addGame() {
} while (looping);
}
-Common::String addGameToConf(const GameDescriptor &result) {
- // The auto detector or the user made a choice.
- // Pick a domain name which does not yet exist (after all, we
- // are *adding* a game to the config, not replacing).
- Common::String domain = result.preferredtarget();
-
- assert(!domain.empty());
- if (ConfMan.hasGameDomain(domain)) {
- int suffixN = 1;
- Common::String gameid(domain);
-
- while (ConfMan.hasGameDomain(domain)) {
- domain = gameid + Common::String::format("-%d", suffixN);
- suffixN++;
- }
- }
-
- // Add the name domain
- ConfMan.addGameDomain(domain);
-
- // Copy all non-empty key/value pairs into the new domain
- for (GameDescriptor::const_iterator iter = result.begin(); iter != result.end(); ++iter) {
- if (!iter->_value.empty() && iter->_key != "preferredtarget")
- ConfMan.set(iter->_key, iter->_value, domain);
- }
-
- // TODO: Setting the description field here has the drawback
- // that the user does never notice when we upgrade our descriptions.
- // It might be nice ot leave this field empty, and only set it to
- // a value when the user edits the description string.
- // However, at this point, that's impractical. Once we have a method
- // to query all backends for the proper & full description of a given
- // game target, we can change this (currently, you can only query
- // for the generic gameid description; it's not possible to obtain
- // a description which contains extended information like language, etc.).
-
- return domain;
-}
-
void LauncherDialog::removeGame(int item) {
MessageDialog alert(_("Do you really want to remove this game configuration?"), _("Yes"), _("No"));
@@ -442,7 +404,8 @@ void LauncherDialog::editGame(int item) {
String gameId(ConfMan.get("gameid", _domains[item]));
if (gameId.empty())
gameId = _domains[item];
- EditGameDialog editDialog(_domains[item], EngineMan.findGame(gameId).description());
+
+ EditGameDialog editDialog(_domains[item]);
if (editDialog.runModal() > 0) {
// User pressed OK, so make changes permanent
@@ -573,7 +536,17 @@ bool LauncherDialog::doGameDetection(const Common::String &path) {
// ...so let's determine a list of candidates, games that
// could be contained in the specified directory.
- GameList candidates(EngineMan.detectGames(files));
+ DetectionResults detectionResults = EngineMan.detectGames(files);
+
+ if (detectionResults.foundUnknownGames()) {
+ Common::String report = detectionResults.generateUnknownGameReport(false, 80);
+ g_system->logMessage(LogMessageType::kInfo, report.c_str());
+
+ UnknownGameDialog dialog(detectionResults);
+ dialog.runModal();
+ }
+
+ Common::Array<DetectedGame> candidates = detectionResults.listRecognizedGames();
int idx;
if (candidates.empty()) {
@@ -589,22 +562,19 @@ bool LauncherDialog::doGameDetection(const Common::String &path) {
// Display the candidates to the user and let her/him pick one
StringArray list;
for (idx = 0; idx < (int)candidates.size(); idx++)
- list.push_back(candidates[idx].description());
+ list.push_back(candidates[idx].description);
ChooserDialog dialog(_("Pick the game:"));
dialog.setList(list);
idx = dialog.runModal();
}
if (0 <= idx && idx < (int)candidates.size()) {
- GameDescriptor result = candidates[idx];
-
- // TODO: Change the detectors to set "path" !
- result["path"] = dir.getPath();
+ const DetectedGame &result = candidates[idx];
- Common::String domain = addGameToConf(result);
+ Common::String domain = EngineMan.createTargetForGame(result);
// Display edit dialog for the new entry
- EditGameDialog editDialog(domain, result.description());
+ EditGameDialog editDialog(domain);
if (editDialog.runModal() > 0) {
// User pressed OK, so make changes permanent
diff --git a/gui/launcher.h b/gui/launcher.h
index 08413fe3d2..9f0a1c8e95 100644
--- a/gui/launcher.h
+++ b/gui/launcher.h
@@ -38,8 +38,6 @@ class StaticTextWidget;
class EditTextWidget;
class SaveLoadChooser;
-Common::String addGameToConf(const GameDescriptor &result);
-
class LauncherDialog : public Dialog {
typedef Common::String String;
typedef Common::Array<Common::String> StringArray;
diff --git a/gui/massadd.cpp b/gui/massadd.cpp
index db569fac82..8bc5a10720 100644
--- a/gui/massadd.cpp
+++ b/gui/massadd.cpp
@@ -28,10 +28,7 @@
#include "common/taskbar.h"
#include "common/translation.h"
-#include "gui/launcher.h" // For addGameToConf()
#include "gui/massadd.h"
-#include "gui/widget.h"
-#include "gui/widgets/list.h"
#ifndef DISABLE_MASS_ADD
namespace GUI {
@@ -120,14 +117,14 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir)
}
struct GameTargetLess {
- bool operator()(const GameDescriptor &x, const GameDescriptor &y) const {
- return x.preferredtarget().compareToIgnoreCase(y.preferredtarget()) < 0;
+ bool operator()(const DetectedGame &x, const DetectedGame &y) const {
+ return x.preferredTarget.compareToIgnoreCase(y.preferredTarget) < 0;
}
};
struct GameDescLess {
- bool operator()(const GameDescriptor &x, const GameDescriptor &y) const {
- return x.description().compareToIgnoreCase(y.description()) < 0;
+ bool operator()(const DetectedGame &x, const DetectedGame &y) const {
+ return x.description.compareToIgnoreCase(y.description) < 0;
}
};
@@ -143,13 +140,13 @@ void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
if (cmd == kOkCmd) {
// Sort the detected games. This is not strictly necessary, but nice for
// people who want to edit their config file by hand after a mass add.
- sort(_games.begin(), _games.end(), GameTargetLess());
+ Common::sort(_games.begin(), _games.end(), GameTargetLess());
// Add all the detected games to the config
- for (GameList::iterator iter = _games.begin(); iter != _games.end(); ++iter) {
+ for (DetectedGames::iterator iter = _games.begin(); iter != _games.end(); ++iter) {
debug(1, " Added gameid '%s', desc '%s'\n",
- (*iter)["gameid"].c_str(),
- (*iter)["description"].c_str());
- (*iter)["gameid"] = addGameToConf(*iter);
+ iter->gameId.c_str(),
+ iter->description.c_str());
+ iter->gameId = EngineMan.createTargetForGame(*iter);
}
// Write everything to disk
@@ -157,8 +154,8 @@ void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
// And scroll to first detected game
if (!_games.empty()) {
- sort(_games.begin(), _games.end(), GameDescLess());
- ConfMan.set("temp_selection", _games.front().gameid());
+ Common::sort(_games.begin(), _games.end(), GameDescLess());
+ ConfMan.set("temp_selection", _games.front().gameId);
}
close();
@@ -187,7 +184,12 @@ void MassAddDialog::handleTickle() {
}
// Run the detector on the dir
- GameList candidates(EngineMan.detectGames(files));
+ DetectionResults detectionResults = EngineMan.detectGames(files);
+
+ if (detectionResults.foundUnknownGames()) {
+ Common::String report = detectionResults.generateUnknownGameReport(false, 80);
+ g_system->logMessage(LogMessageType::kInfo, report.c_str());
+ }
// Just add all detected games / game variants. If we get more than one,
// that either means the directory contains multiple games, or the detector
@@ -195,8 +197,10 @@ void MassAddDialog::handleTickle() {
// case, let the user choose which entries he wants to keep.
//
// However, we only add games which are not already in the config file.
- for (GameList::const_iterator cand = candidates.begin(); cand != candidates.end(); ++cand) {
- GameDescriptor result = *cand;
+ DetectedGames candidates = detectionResults.listRecognizedGames();
+ for (DetectedGames::const_iterator cand = candidates.begin(); cand != candidates.end(); ++cand) {
+ const DetectedGame &result = *cand;
+
Common::String path = dir.getPath();
// Remove trailing slashes
@@ -205,6 +209,9 @@ void MassAddDialog::handleTickle() {
// Check for existing config entries for this path/gameid/lang/platform combination
if (_pathToTargets.contains(path)) {
+ const char *resultPlatformCode = Common::getPlatformCode(result.platform);
+ const char *resultLanguageCode = Common::getLanguageCode(result.language);
+
bool duplicate = false;
const StringArray &targets = _pathToTargets[path];
for (StringArray::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) {
@@ -212,9 +219,9 @@ void MassAddDialog::handleTickle() {
Common::ConfigManager::Domain *dom = ConfMan.getDomain(*iter);
assert(dom);
- if ((*dom)["gameid"] == result["gameid"] &&
- (*dom)["platform"] == result["platform"] &&
- (*dom)["language"] == result["language"]) {
+ if ((*dom)["gameid"] == result.gameId &&
+ (*dom)["platform"] == resultPlatformCode &&
+ (*dom)["language"] == resultLanguageCode) {
duplicate = true;
break;
}
@@ -224,10 +231,9 @@ void MassAddDialog::handleTickle() {
break; // Skip duplicates
}
}
- result["path"] = path;
_games.push_back(result);
- _list->append(result.description());
+ _list->append(result.description);
}
diff --git a/gui/massadd.h b/gui/massadd.h
index 116a420d79..b81a6046e2 100644
--- a/gui/massadd.h
+++ b/gui/massadd.h
@@ -24,6 +24,7 @@
#define MASSADD_DIALOG_H
#include "gui/dialog.h"
+#include "gui/widgets/list.h"
#include "common/fs.h"
#include "common/hashmap.h"
#include "common/stack.h"
@@ -44,13 +45,13 @@ public:
Common::String getFirstAddedTarget() const {
if (!_games.empty())
- return _games.front().gameid();
+ return _games.front().gameId;
return Common::String();
}
private:
Common::Stack<Common::FSNode> _scanStack;
- GameList _games;
+ DetectedGames _games;
/**
* Map each path occuring in the config file to the target(s) using that path.
diff --git a/gui/module.mk b/gui/module.mk
index eb3ee88a9a..0218e082b4 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -25,6 +25,7 @@ MODULE_OBJS := \
ThemeLayout.o \
ThemeParser.o \
Tooltip.o \
+ unknown-game-dialog.o \
animation/Animation.o \
animation/RepeatAnimationWrapper.o \
animation/SequenceAnimationComposite.o \
diff --git a/gui/object.cpp b/gui/object.cpp
index 327bc27894..d2a6701443 100644
--- a/gui/object.cpp
+++ b/gui/object.cpp
@@ -67,4 +67,8 @@ void GuiObject::removeWidget(Widget *del) {
}
}
+Common::Rect GuiObject::getClipRect() const {
+ return Common::Rect(getAbsX(), getAbsY(), getAbsX() + getWidth(), getAbsY() + getHeight());
+}
+
} // End of namespace GUI
diff --git a/gui/object.h b/gui/object.h
index 40ea2da636..33d6ec3c8f 100644
--- a/gui/object.h
+++ b/gui/object.h
@@ -95,6 +95,11 @@ public:
return (x >= _x && x < (_x + _w) && (y >= _y) && (y < _y + _h));
}
+ /**
+ * Returns the clipping rect to be used when drawing the children widgets of this object
+ */
+ virtual Common::Rect getClipRect() const;
+
protected:
virtual void releaseFocus() = 0;
};
diff --git a/gui/options.h b/gui/options.h
index b1666c2fff..bc58d7a63e 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -81,7 +81,7 @@ protected:
ButtonWidget *_soundFontButton;
StaticTextWidget *_soundFont;
ButtonWidget *_soundFontClearButton;
-
+
virtual void build();
virtual void clean();
void rebuild();
@@ -115,7 +115,7 @@ protected:
int _pathsTabId;
private:
-
+
//
// Control controls
//
@@ -143,7 +143,7 @@ private:
CheckboxWidget *_aspectCheckbox;
StaticTextWidget *_renderModePopUpDesc;
PopUpWidget *_renderModePopUp;
-
+
//
// Shader controls
//
diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp
index 5650fd8e94..b01e4950d5 100644
--- a/gui/predictivedialog.cpp
+++ b/gui/predictivedialog.cpp
@@ -35,7 +35,7 @@
#include "common/file.h"
#include "common/savefile.h"
-#ifdef __DS__
+#if defined(__DS__) && defined(ENABLE_AGI)
#include "backends/platform/ds/arm9/source/wordcompletion.h"
#endif
@@ -945,7 +945,7 @@ void PredictiveDialog::loadDictionary(Common::SeekableReadStream *in, Dict &dict
while ((ptr = strchr(ptr, '\n'))) {
*ptr = 0;
ptr++;
-#ifdef __DS__
+#if defined(__DS__) && defined(ENABLE_AGI)
// Pass the line on to the DS word list
DS::addAutoCompleteLine(dict.dictLine[i - 1]);
#endif
@@ -960,7 +960,7 @@ void PredictiveDialog::loadDictionary(Common::SeekableReadStream *in, Dict &dict
// FIXME: We use binary search on _predictiveDict.dictLine, yet we make no at_tempt
// to ever sort this array (except for the DS port). That seems risky, doesn't it?
-#ifdef __DS__
+#if defined(__DS__) && defined(ENABLE_AGI)
// Sort the DS word completion list, to allow for a binary chop later (in the ds backend)
DS::sortAutoCompleteWordList();
#endif
diff --git a/gui/recorderdialog.cpp b/gui/recorderdialog.cpp
index cd89b58f00..7a2cd048f4 100644
--- a/gui/recorderdialog.cpp
+++ b/gui/recorderdialog.cpp
@@ -167,9 +167,9 @@ void RecorderDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
case kRecordCmd: {
TimeDate t;
Common::String gameId = ConfMan.get("gameid", _target);
- GameDescriptor desc = EngineMan.findGame(gameId);
+ PlainGameDescriptor desc = EngineMan.findGame(gameId);
g_system->getTimeAndDate(t);
- EditRecordDialog editDlg(_("Unknown Author"), Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description(), "");
+ EditRecordDialog editDlg(_("Unknown Author"), Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description, "");
if (editDlg.runModal() != kOKCmd) {
return;
}
diff --git a/gui/themes/translations.dat b/gui/themes/translations.dat
index d9d35d8201..d6ad2ccbb7 100644
--- a/gui/themes/translations.dat
+++ b/gui/themes/translations.dat
Binary files differ
diff --git a/gui/unknown-game-dialog.cpp b/gui/unknown-game-dialog.cpp
new file mode 100644
index 0000000000..561d39457b
--- /dev/null
+++ b/gui/unknown-game-dialog.cpp
@@ -0,0 +1,220 @@
+/* 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 "gui/unknown-game-dialog.h"
+
+#include "common/translation.h"
+#include "common/str-array.h"
+#include "common/system.h"
+
+#include "gui/gui-manager.h"
+#include "gui/message.h"
+#include "gui/ThemeEval.h"
+#include "gui/widgets/popup.h"
+#include "gui/widgets/scrollcontainer.h"
+
+namespace GUI {
+
+enum {
+ kCopyToClipboard = 'cpcl',
+ kOpenBugtrackerURL = 'ourl',
+ kClose = 'clse',
+ kScrollContainerReflow = 'SCRf'
+};
+
+UnknownGameDialog::UnknownGameDialog(const DetectionResults &detectionResults) :
+ Dialog(30, 20, 260, 124),
+ _detectionResults(detectionResults) {
+ // For now place the buttons with a default place and size. They will be resized and moved when rebuild() is called.
+ _closeButton = new ButtonWidget(this, 0, 0, 0, 0, _("Close"), 0, kClose);
+
+ //Check if we have clipboard functionality
+ if (g_system->hasFeature(OSystem::kFeatureClipboardSupport)) {
+ _copyToClipboardButton = new ButtonWidget(this, 0, 0, 0, 0, _("Copy to clipboard"), 0, kCopyToClipboard);
+ } else
+ _copyToClipboardButton = nullptr;
+
+#if 0
+ // Do not create the button for reporting the game directly to the bugtracker
+ // for now until we find a proper solution for the problem that a change
+ // to our bugtracker system might break the URL generation. A possible approach
+ // for solving this would be to have a ULR under the .scummvm.org (of the type
+ // https://www.scummvm.org/unknowngame?engine=Foo&description=Bar) that would
+ // redirect to whatever our bugtracker system is.
+
+ //Check if we have support for opening URLs
+ if (g_system->hasFeature(OSystem::kFeatureOpenUrl)) {
+ buttonPos -= openBugtrackerURLButtonWidth + 5;
+ _openBugTrackerUrlButton = new ButtonWidget(this, 0, 0, 0, 0, _("Report game"), 0, kOpenBugtrackerURL);
+ //Formatting the reportData for bugtracker submission [replace line breaks]...
+ _bugtrackerGameData = _reportData;
+ while (_bugtrackerGameData.contains("\n")) {
+ Common::replace(_bugtrackerGameData, "\n", "%0A");
+ }
+ } else
+#endif
+ _openBugTrackerUrlButton = nullptr;
+
+ // Use a ScrollContainer for the report in case we have a lot of lines.
+ _textContainer = new ScrollContainerWidget(this, 0, 0, 0, 0, kScrollContainerReflow);
+ _textContainer->setTarget(this);
+
+ rebuild();
+}
+
+void UnknownGameDialog::reflowLayout() {
+ rebuild();
+ Dialog::reflowLayout();
+}
+
+void UnknownGameDialog::rebuild() {
+ // First remove the old text widgets
+ for (uint i = 0; i < _textWidgets.size() ; i++) {
+ _textContainer->removeWidget(_textWidgets[i]);
+ delete _textWidgets[i];
+ }
+ _textWidgets.clear();
+
+ // Work out dialog size and position of the various elements in the dialog.
+ // Limit the width of the dialog to 600 - 2 * 10 pixels.
+ const int screenW = MIN((int)g_system->getOverlayWidth(), 600);
+ const int screenH = g_system->getOverlayHeight();
+
+ int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0);
+ int buttonWidth = g_gui.xmlEval()->getVar("Globals.Button.Width", 0);
+
+ Common::String reportTranslated = _detectionResults.generateUnknownGameReport(true);
+
+ // Check if we have clipboard functionality and expand the reportTranslated message if needed...
+ if (g_system->hasFeature(OSystem::kFeatureClipboardSupport)) {
+ reportTranslated += "\n";
+ reportTranslated += _("Use the button below to copy the required game information into your clipboard.");
+ }
+
+#if 0
+ // Check if we have support for opening URLs and expand the reportTranslated message if needed...
+ if (g_system->hasFeature(OSystem::kFeatureOpenUrl)) {
+ reportTranslated += "\n";
+ reportTranslated += _("You can also directly report your game to the Bug Tracker.");
+ }
+#endif
+
+ // We use a ScrollContainer to display the text, with a 2 * 8 pixels margin to the dialog border,
+ // the scrollbar, and 2 * 10 margin for the text in the container.
+ // We also keep 2 * 10 pixels between the screen border and the dialog.
+ int scrollbarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);
+ Common::Array<Common::String> lines;
+ int maxlineWidth = g_gui.getFont().wordWrapText(reportTranslated, screenW - 2 * 20 - 16 - scrollbarWidth, lines);
+
+ int lineCount = lines.size() + 1;
+
+ _h = MIN(screenH - 20, lineCount * kLineHeight + kLineHeight + buttonHeight + 24);
+
+ int closeButtonWidth = MAX(buttonWidth, g_gui.getFont().getStringWidth(_closeButton->getLabel()) + 10);
+ int copyToClipboardButtonWidth = 0, openBugtrackerURLButtonWidth = 0, totalButtonWidth = closeButtonWidth;
+ if (_copyToClipboardButton) {
+ copyToClipboardButtonWidth = MAX(buttonWidth, g_gui.getFont().getStringWidth(_copyToClipboardButton->getLabel()) + 10);
+ totalButtonWidth += copyToClipboardButtonWidth + 10;
+ }
+ if (_openBugTrackerUrlButton) {
+ openBugtrackerURLButtonWidth = MAX(buttonWidth, g_gui.getFont().getStringWidth(_openBugTrackerUrlButton->getLabel()) + 10);
+ totalButtonWidth += openBugtrackerURLButtonWidth + 10;
+ }
+
+ _w = MAX(MAX(maxlineWidth, 0) + 16 + scrollbarWidth, totalButtonWidth) + 20;
+
+ // Center the dialog on the screen
+ _x = (g_system->getOverlayWidth() - _w) / 2;
+ _y = (g_system->getOverlayHeight() - _h) / 2;
+
+ // Now move the buttons and text container to their proper place
+ int buttonPos = _w - closeButtonWidth - 10;
+ _closeButton->resize(buttonPos, _h - buttonHeight - 8, closeButtonWidth, buttonHeight);
+ if (_copyToClipboardButton) {
+ buttonPos -= copyToClipboardButtonWidth + 5;
+ _copyToClipboardButton->resize(buttonPos, _h - buttonHeight - 8, copyToClipboardButtonWidth, buttonHeight);
+ }
+ if (_openBugTrackerUrlButton) {
+ buttonPos -= openBugtrackerURLButtonWidth + 5;
+ _openBugTrackerUrlButton->resize(buttonPos, _h - buttonHeight - 8, openBugtrackerURLButtonWidth, buttonHeight);
+ }
+
+ int containerHeight = _h - kLineHeight - buttonHeight - 16;
+ _textContainer->resize(8, 8, _w - 16, containerHeight);
+
+ // And create text widgets
+ uint y = 8;
+ for (uint i = 0; i < lines.size() ; i++) {
+ StaticTextWidget *widget = new StaticTextWidget(_textContainer, 10, y, _w - 36 - scrollbarWidth, kLineHeight, lines[i], Graphics::kTextAlignLeft);
+ _textWidgets.push_back(widget);
+ y += kLineHeight;
+ }
+}
+
+
+Common::String UnknownGameDialog::generateBugtrackerURL() {
+ // TODO: Remove the filesystem path from the bugtracker report
+ Common::String report = _detectionResults.generateUnknownGameReport(false);
+
+ // Formatting the report for bugtracker submission [replace line breaks]...
+ while (report.contains("\n")) {
+ Common::replace(report, "\n", "%0A");
+ }
+
+ return Common::String::format(
+ "https://bugs.scummvm.org/newticket?"
+ "&description=%s"
+ "&type=enhancement"
+ "&keywords=unknown-game",
+ report.c_str());
+}
+
+void UnknownGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ switch(cmd) {
+ case kCopyToClipboard: {
+ // TODO: Remove the filesystem path from the report
+ Common::String report = _detectionResults.generateUnknownGameReport(false);
+
+ if (g_system->setTextInClipboard(report)) {
+ g_system->displayMessageOnOSD(
+ _("All necessary information about your game has been copied into the clipboard"));
+ } else {
+ g_system->displayMessageOnOSD(_("Copying the game information to the clipboard has failed!"));
+ }
+ break;
+ }
+ case kClose:
+ // When the detection entry comes from the fallback detector, the game can be added / launched anyways.
+ // TODO: Add a button to cancel adding the game. And make it clear that launching the game may not work properly.
+ close();
+ break;
+ case kOpenBugtrackerURL:
+ g_system->openUrl(generateBugtrackerURL());
+ break;
+ case kScrollContainerReflow:
+ for (uint i = 0; i < _textWidgets.size() ; i++)
+ _textWidgets[i]->setVisible(true);
+ break;
+ }
+}
+
+} // End of namespace GUI
diff --git a/gui/unknown-game-dialog.h b/gui/unknown-game-dialog.h
new file mode 100644
index 0000000000..bad61d7064
--- /dev/null
+++ b/gui/unknown-game-dialog.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 GUI_UNKNOWN_GAME_DIALOG_H
+#define GUI_UNKNOWN_GAME_DIALOG_H
+
+#include "gui/dialog.h"
+#include "common/array.h"
+#include "engines/game.h"
+
+namespace GUI {
+
+class StaticTextWidget;
+class ScrollContainerWidget;
+class ButtonWidget;
+
+class UnknownGameDialog : public Dialog {
+public:
+ UnknownGameDialog(const DetectionResults &detectionResults);
+
+private:
+ void rebuild();
+
+ // Dialog API
+ void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
+ void reflowLayout() override;
+
+ Common::String generateBugtrackerURL();
+
+ const DetectionResults &_detectionResults;
+ ScrollContainerWidget *_textContainer;
+ Common::Array<StaticTextWidget *> _textWidgets;
+ ButtonWidget* _openBugTrackerUrlButton;
+ ButtonWidget* _copyToClipboardButton;
+ ButtonWidget* _closeButton;
+};
+
+} // End of namespace GUI
+
+#endif
diff --git a/gui/widget.cpp b/gui/widget.cpp
index 9993d64dbb..1dfd069f29 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -54,31 +54,6 @@ void Widget::init() {
_needsRedraw = true;
}
-Common::Rect Widget::getBossClipRect() const {
- int bx = _boss->getAbsX();
- int by = _boss->getAbsY();
- Common::Rect result = Common::Rect(bx, by, bx + _boss->getWidth(), by + _boss->getHeight());
- bool needsClipping = false;
-
- //check whether clipping area is inside the screen
- if (result.left < 0 && (needsClipping = true))
- warning("Widget <%s> has clipping area x < 0 (%d)", _name.c_str(), result.left);
- if (result.left >= g_gui.getWidth() && (needsClipping = true))
- warning("Widget <%s> has clipping area x > %d (%d)", _name.c_str(), g_gui.getWidth(), result.left);
- if (result.right > g_gui.getWidth() && (needsClipping = true))
- warning("Widget <%s> has clipping area x + w > %d (%d)", _name.c_str(), g_gui.getWidth(), result.right);
- if (result.top < 0 && (needsClipping = true))
- warning("Widget <%s> has clipping area y < 0 (%d)", _name.c_str(), result.top);
- if (result.top >= g_gui.getHeight() && (needsClipping = true))
- warning("Widget <%s> has clipping area y > %d (%d)", _name.c_str(), g_gui.getHeight(), result.top);
- if (result.bottom > g_gui.getHeight() && (needsClipping = true))
- warning("Widget <%s> has clipping area y + h > %d (%d)", _name.c_str(), g_gui.getHeight(), result.bottom);
-
- if (needsClipping)
- result.clip(g_gui.getWidth(), g_gui.getHeight());
- return result;
-}
-
Widget::~Widget() {
delete _next;
_next = 0;
@@ -134,9 +109,12 @@ void Widget::draw() {
_x = getAbsX();
_y = getAbsY();
+ Common::Rect oldClip = g_gui.theme()->swapClipRect(_boss->getClipRect());
+
// Draw border
if (_flags & WIDGET_BORDER) {
- g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
+ g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0,
+ ThemeEngine::kWidgetBackgroundBorder);
_x += 4;
_y += 4;
_w -= 8;
@@ -146,6 +124,8 @@ void Widget::draw() {
// Now perform the actual widget draw
drawWidget();
+ g_gui.theme()->swapClipRect(oldClip);
+
// Restore x/y
if (_flags & WIDGET_BORDER) {
_x -= 4;
@@ -318,9 +298,9 @@ void StaticTextWidget::setAlign(Graphics::TextAlign align) {
void StaticTextWidget::drawWidget() {
- g_gui.theme()->drawTextClip(
- Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(),
- _label, _state, _align, ThemeEngine::kTextInversionNone, 0, true, _font
+ g_gui.theme()->drawText(
+ Common::Rect(_x, _y, _x + _w, _y + _h),
+ _label, _state, _align, ThemeEngine::kTextInversionNone, 0, true, _font
);
}
@@ -360,10 +340,7 @@ void ButtonWidget::handleMouseDown(int x, int y, int button, int clickCount) {
}
void ButtonWidget::drawWidget() {
- g_gui.theme()->drawButtonClip(
- Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(),
- _label, _state, getFlags()
- );
+ g_gui.theme()->drawButton(Common::Rect(_x, _y, _x + _w, _y + _h), _label, _state, getFlags());
}
void ButtonWidget::setLabel(const Common::String &label) {
@@ -411,19 +388,17 @@ void ButtonWidget::setUnpressedState() {
PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd, uint8 hotkey)
: ButtonWidget(boss, x, y, w, h, "", tooltip, cmd, hotkey),
- _alpha(255), _transparency(false), _showButton(true), _isAlpha(false) {
+ _alpha(255), _transparency(false), _showButton(true) {
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
_type = kButtonWidget;
- _mode = ThemeEngine::kAutoScaleNone;
}
PicButtonWidget::PicButtonWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd, uint8 hotkey)
: ButtonWidget(boss, name, "", tooltip, cmd, hotkey),
- _alpha(255), _transparency(false), _showButton(true), _isAlpha(false) {
+ _alpha(255), _transparency(false), _showButton(true) {
setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
_type = kButtonWidget;
- _mode = ThemeEngine::kAutoScaleNone;
}
PicButtonWidget::~PicButtonWidget() {
@@ -451,23 +426,6 @@ void PicButtonWidget::setGfx(const Graphics::Surface *gfx, int statenum) {
_gfx[statenum].copyFrom(*gfx);
}
-void PicButtonWidget::setAGfx(const Graphics::TransparentSurface *gfx, int statenum, ThemeEngine::AutoScaleMode mode) {
- _agfx[statenum].free();
-
- if (!gfx || !gfx->getPixels())
- return;
-
- if (gfx->format.bytesPerPixel == 1) {
- warning("PicButtonWidget::setGfx got paletted surface passed");
- return;
- }
-
- _agfx[statenum].copyFrom(*gfx);
-
- _isAlpha = true;
- _mode = mode;
-}
-
void PicButtonWidget::setGfx(int w, int h, int r, int g, int b, int statenum) {
if (w == -1)
w = _w;
@@ -483,62 +441,34 @@ void PicButtonWidget::setGfx(int w, int h, int r, int g, int b, int statenum) {
void PicButtonWidget::drawWidget() {
if (_showButton)
- g_gui.theme()->drawButtonClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), "", _state, getFlags());
+ g_gui.theme()->drawButton(Common::Rect(_x, _y, _x + _w, _y + _h), "", _state, getFlags());
- if (!_isAlpha) {
- Graphics::Surface *gfx;
+ Graphics::Surface *gfx;
- if (_state == ThemeEngine::kStateHighlight)
- gfx = &_gfx[kPicButtonHighlight];
- else if (_state == ThemeEngine::kStateDisabled)
- gfx = &_gfx[kPicButtonStateDisabled];
- else if (_state == ThemeEngine::kStatePressed)
- gfx = &_gfx[kPicButtonStatePressed];
- else
- gfx = &_gfx[kPicButtonStateEnabled];
+ if (_state == ThemeEngine::kStateHighlight)
+ gfx = &_gfx[kPicButtonHighlight];
+ else if (_state == ThemeEngine::kStateDisabled)
+ gfx = &_gfx[kPicButtonStateDisabled];
+ else if (_state == ThemeEngine::kStatePressed)
+ gfx = &_gfx[kPicButtonStatePressed];
+ else
+ gfx = &_gfx[kPicButtonStateEnabled];
- if (!gfx->getPixels())
- gfx = &_gfx[kPicButtonStateEnabled];
+ if (!gfx->getPixels())
+ gfx = &_gfx[kPicButtonStateEnabled];
- if (gfx->getPixels()) {
+ if (gfx->getPixels()) {
// Check whether the set up surface needs to be converted to the GUI
// color format.
- const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
- if (gfx->format != requiredFormat) {
- gfx->convertToInPlace(requiredFormat);
- }
-
- const int x = _x + (_w - gfx->w) / 2;
- const int y = _y + (_h - gfx->h) / 2;
-
- g_gui.theme()->drawSurfaceClip(Common::Rect(x, y, x + gfx->w, y + gfx->h), getBossClipRect(), *gfx, _state, _alpha, _transparency);
+ const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
+ if (gfx->format != requiredFormat) {
+ gfx->convertToInPlace(requiredFormat);
}
- } else {
- Graphics::TransparentSurface *gfx;
-
- if (_state == ThemeEngine::kStateHighlight)
- gfx = &_agfx[kPicButtonHighlight];
- else if (_state == ThemeEngine::kStateDisabled)
- gfx = &_agfx[kPicButtonStateDisabled];
- else if (_state == ThemeEngine::kStatePressed)
- gfx = &_agfx[kPicButtonStatePressed];
- else
- gfx = &_agfx[kPicButtonStateEnabled];
-
- if (!gfx->getPixels())
- gfx = &_agfx[kPicButtonStateEnabled];
- if (gfx->getPixels()) {
- if (_mode == GUI::ThemeEngine::kAutoScaleNone) {
- const int x = _x + (_w - gfx->w) / 2;
- const int y = _y + (_h - gfx->h) / 2;
+ const int x = _x + (_w - gfx->w) / 2;
+ const int y = _y + (_h - gfx->h) / 2;
- g_gui.theme()->drawASurface(Common::Rect(x, y, x + gfx->w, y + gfx->h), *gfx, _mode, _alpha);
-
- } else {
- g_gui.theme()->drawASurface(Common::Rect(_x, _y, _x + _w, _y + _h), *gfx, _mode, _alpha);
- }
- }
+ g_gui.theme()->drawSurface(Common::Rect(x, y, x + gfx->w, y + gfx->h), *gfx, _transparency);
}
}
@@ -573,7 +503,7 @@ void CheckboxWidget::setState(bool state) {
}
void CheckboxWidget::drawWidget() {
- g_gui.theme()->drawCheckboxClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _label, _state, Widget::_state);
+ g_gui.theme()->drawCheckbox(Common::Rect(_x, _y, _x + _w, _y + _h), _label, _state, Widget::_state);
}
#pragma mark -
@@ -642,7 +572,7 @@ void RadiobuttonWidget::setState(bool state, bool setGroup) {
}
void RadiobuttonWidget::drawWidget() {
- g_gui.theme()->drawRadiobuttonClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _label, _state, Widget::_state);
+ g_gui.theme()->drawRadiobutton(Common::Rect(_x, _y, _x + _w, _y + _h), _label, _state, Widget::_state);
}
#pragma mark -
@@ -710,7 +640,7 @@ void SliderWidget::handleMouseWheel(int x, int y, int direction) {
}
void SliderWidget::drawWidget() {
- g_gui.theme()->drawSliderClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), valueToBarWidth(_value), _state);
+ g_gui.theme()->drawSlider(Common::Rect(_x, _y, _x + _w, _y + _h), valueToBarWidth(_value), _state);
}
int SliderWidget::valueToBarWidth(int value) {
@@ -764,26 +694,6 @@ void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
_gfx.copyFrom(*gfx);
}
-void GraphicsWidget::setAGfx(const Graphics::TransparentSurface *gfx, ThemeEngine::AutoScaleMode mode) {
- _agfx.free();
-
- if (!gfx || !gfx->getPixels())
- return;
-
- if (gfx->format.bytesPerPixel == 1) {
- warning("GraphicsWidget::setGfx got paletted surface passed");
- return;
- }
-
- if ((gfx->w > _w || gfx->h > _h) && mode == ThemeEngine::kAutoScaleNone) {
- warning("GraphicsWidget has size %dx%d, but a surface with %dx%d is to be set", _w, _h, gfx->w, gfx->h);
- return;
- }
-
- _agfx.copyFrom(*gfx);
- _mode = mode;
-}
-
void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
if (w == -1)
w = _w;
@@ -809,24 +719,7 @@ void GraphicsWidget::drawWidget() {
const int x = _x + (_w - _gfx.w) / 2;
const int y = _y + (_h - _gfx.h) / 2;
- g_gui.theme()->drawSurfaceClip(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), getBossClipRect(), _gfx, _state, _alpha, _transparency);
- } else if (_agfx.getPixels()) {
- // Check whether the set up surface needs to be converted to the GUI
- // color format.
- const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
- if (_agfx.format != requiredFormat) {
- _agfx.convertToInPlace(requiredFormat);
- }
-
- if (_mode == GUI::ThemeEngine::kAutoScaleNone) {
- const int x = _x + (_w - _agfx.w) / 2;
- const int y = _y + (_h - _agfx.h) / 2;
-
- g_gui.theme()->drawASurface(Common::Rect(x, y, x + _agfx.w, y + _agfx.h), _agfx, _mode, _alpha);
-
- } else {
- g_gui.theme()->drawASurface(Common::Rect(_x, _y, _x + _w, _y + _h), _agfx, _mode, _alpha);
- }
+ g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), _gfx, _transparency);
}
}
@@ -867,7 +760,8 @@ void ContainerWidget::removeWidget(Widget *widget) {
}
void ContainerWidget::drawWidget() {
- g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
+ g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0,
+ ThemeEngine::kWidgetBackgroundBorder);
}
} // End of namespace GUI
diff --git a/gui/widget.h b/gui/widget.h
index e57f3cde51..f87816b2e3 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -123,7 +123,6 @@ public:
virtual int16 getAbsX() const { return _x + _boss->getChildX(); }
virtual int16 getAbsY() const { return _y + _boss->getChildY(); }
- virtual Common::Rect getBossClipRect() const;
virtual void setPos(int x, int y) { _x = x; _y = y; }
virtual void setSize(int w, int h) { _w = w; _h = h; }
@@ -240,7 +239,6 @@ public:
~PicButtonWidget();
void setGfx(const Graphics::Surface *gfx, int statenum = kPicButtonStateEnabled);
- void setAGfx(const Graphics::TransparentSurface *gfx, int statenum = kPicButtonStateEnabled, ThemeEngine::AutoScaleMode mode = ThemeEngine::kAutoScaleNone);
void setGfx(int w, int h, int r, int g, int b, int statenum = kPicButtonStateEnabled);
void useAlpha(int alpha) { _alpha = alpha; }
@@ -251,12 +249,9 @@ protected:
void drawWidget();
Graphics::Surface _gfx[kPicButtonStateMax + 1];
- Graphics::TransparentSurface _agfx[kPicButtonStateMax + 1];
int _alpha;
bool _transparency;
bool _showButton;
- bool _isAlpha;
- ThemeEngine::AutoScaleMode _mode;
};
/* CheckboxWidget */
@@ -375,7 +370,6 @@ public:
void setGfx(const Graphics::Surface *gfx);
void setGfx(int w, int h, int r, int g, int b);
- void setAGfx(const Graphics::TransparentSurface *gfx, ThemeEngine::AutoScaleMode mode = ThemeEngine::kAutoScaleNone);
void useAlpha(int alpha) { _alpha = alpha; }
void useThemeTransparency(bool enable) { _transparency = enable; }
@@ -384,10 +378,8 @@ protected:
void drawWidget();
Graphics::Surface _gfx;
- Graphics::TransparentSurface _agfx;
int _alpha;
bool _transparency;
- ThemeEngine::AutoScaleMode _mode;
};
/* ContainerWidget */
diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp
index 5e7c94b64a..2af078f9f6 100644
--- a/gui/widgets/editable.cpp
+++ b/gui/widgets/editable.cpp
@@ -200,6 +200,15 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
}
break;
+ case Common::KEYCODE_c:
+ if (g_system->hasFeature(OSystem::kFeatureClipboardSupport) && state.flags & Common::KBD_CTRL) {
+ if (!getEditString().empty())
+ g_system->setTextInClipboard(getEditString());
+ } else {
+ defaultKeyDownHandler(state, dirty, forcecaret, handled);
+ }
+ break;
+
#ifdef MACOSX
// Let ctrl-a / ctrl-e move the caret to the start / end of the line.
//
@@ -289,7 +298,7 @@ void EditableWidget::drawCaret(bool erase) {
x += getAbsX();
y += getAbsY();
- g_gui.theme()->drawCaretClip(Common::Rect(x, y, x + 1, y + editRect.height()), getBossClipRect(), erase);
+ g_gui.theme()->drawCaret(Common::Rect(x, y, x + 1, y + editRect.height()), erase);
if (erase) {
GUI::EditableWidget::String character;
@@ -318,7 +327,9 @@ void EditableWidget::drawCaret(bool erase) {
// possible glitches due to different methods used.
width = MIN(editRect.width() - caretOffset, width);
if (width > 0) {
- g_gui.theme()->drawTextClip(Common::Rect(x, y, x + width, y + editRect.height()), getBossClipRect(), character, _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
+ g_gui.theme()->drawText(Common::Rect(x, y, x + width, y + editRect.height()), character,
+ _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font,
+ ThemeEngine::kFontColorNormal, true, _textDrawableArea);
}
}
diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp
index 97366741d0..b0e68985d1 100644
--- a/gui/widgets/edittext.cpp
+++ b/gui/widgets/edittext.cpp
@@ -97,7 +97,8 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
}
void EditTextWidget::drawWidget() {
- g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundEditText);
+ g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0,
+ ThemeEngine::kWidgetBackgroundEditText);
// Draw the text
adjustOffset();
@@ -105,7 +106,10 @@ void EditTextWidget::drawWidget() {
const Common::Rect &r = Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 8, _y + _h);
setTextDrawableArea(r);
- g_gui.theme()->drawTextClip(Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 2, _y + _h), getBossClipRect(), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
+ g_gui.theme()->drawText(
+ Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 2, _y + _h),
+ _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone,
+ -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
}
Common::Rect EditTextWidget::getEditRect() const {
diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp
index df12d6fd5f..6dd4ab4dd5 100644
--- a/gui/widgets/list.cpp
+++ b/gui/widgets/list.cpp
@@ -495,7 +495,8 @@ void ListWidget::drawWidget() {
Common::String buffer;
// Draw a thin frame around the list.
- g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
+ g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0,
+ ThemeEngine::kWidgetBackgroundBorder);
// Draw the list items
for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) {
@@ -513,8 +514,8 @@ void ListWidget::drawWidget() {
// If in numbering mode, we first print a number prefix
if (_numberingMode != kListNumberingOff) {
buffer = Common::String::format("%2d. ", (pos + _numberingMode));
- g_gui.theme()->drawTextClip(Common::Rect(_x + _hlLeftPadding, y, _x + r.left + _leftPadding, y + fontHeight - 2),
- getBossClipRect(), buffer, _state, Graphics::kTextAlignLeft, inverted, _leftPadding, true);
+ g_gui.theme()->drawText(Common::Rect(_x + _hlLeftPadding, y, _x + r.left + _leftPadding, y + fontHeight - 2),
+ buffer, _state, Graphics::kTextAlignLeft, inverted, _leftPadding, true);
pad = 0;
}
@@ -531,14 +532,12 @@ void ListWidget::drawWidget() {
buffer = _editString;
color = _editColor;
adjustOffset();
- g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.right, y + fontHeight - 2),
- getBossClipRect(), buffer, _state,
- Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
+ g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.right, y + fontHeight - 2), buffer, _state,
+ Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
} else {
buffer = _list[pos];
- g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.right, y + fontHeight - 2),
- getBossClipRect(), buffer, _state,
- Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
+ g_gui.theme()->drawText(Common::Rect(_x + r.left, y, _x + r.right, y + fontHeight - 2), buffer, _state,
+ Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
}
}
}
diff --git a/gui/widgets/popup.cpp b/gui/widgets/popup.cpp
index 40af769a34..a36a652e5b 100644
--- a/gui/widgets/popup.cpp
+++ b/gui/widgets/popup.cpp
@@ -50,10 +50,10 @@ public:
void drawDialog(DrawLayer layerToDraw) override;
- void handleMouseUp(int x, int y, int button, int clickCount);
- void handleMouseWheel(int x, int y, int direction); // Scroll through entries with scroll wheel
- void handleMouseMoved(int x, int y, int button); // Redraw selections depending on mouse position
- void handleKeyDown(Common::KeyState state); // Scroll through entries with arrow keys etc.
+ void handleMouseUp(int x, int y, int button, int clickCount) override;
+ void handleMouseWheel(int x, int y, int direction) override; // Scroll through entries with scroll wheel
+ void handleMouseMoved(int x, int y, int button) override; // Redraw selections depending on mouse position
+ void handleKeyDown(Common::KeyState state) override; // Scroll through entries with arrow keys etc.
protected:
void drawMenuEntry(int entry, bool hilite);
@@ -151,7 +151,7 @@ void PopUpDialog::drawDialog(DrawLayer layerToDraw) {
Dialog::drawDialog(layerToDraw);
// Draw the menu border
- g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0);
+ g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0);
/*if (_twoColumns)
g_gui.vLine(_x + _w / 2, _y, _y + _h - 2, g_gui._color);*/
@@ -367,10 +367,10 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) {
if (name.size() == 0) {
// Draw a separator
- g_gui.theme()->drawLineSeparator(Common::Rect(x, y, x+w, y+kLineHeight));
+ g_gui.theme()->drawLineSeparator(Common::Rect(x, y, x + w, y + kLineHeight));
} else {
g_gui.theme()->drawText(
- Common::Rect(x+1, y+2, x+w, y+2+kLineHeight),
+ Common::Rect(x + 1, y + 2, x + w, y + 2 + kLineHeight),
name, hilite ? ThemeEngine::kStateHighlight : ThemeEngine::kStateEnabled,
Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, _leftPadding
);
@@ -478,10 +478,7 @@ void PopUpWidget::drawWidget() {
Common::String sel;
if (_selectedItem >= 0)
sel = _entries[_selectedItem].name;
- g_gui.theme()->drawPopUpWidgetClip(
- Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(),
- sel, _leftPadding, _state, Graphics::kTextAlignLeft
- );
+ g_gui.theme()->drawPopUpWidget(Common::Rect(_x, _y, _x + _w, _y + _h), sel, _leftPadding, _state);
}
} // End of namespace GUI
diff --git a/gui/widgets/scrollbar.cpp b/gui/widgets/scrollbar.cpp
index b0e2576ec1..38cdc6fda6 100644
--- a/gui/widgets/scrollbar.cpp
+++ b/gui/widgets/scrollbar.cpp
@@ -203,11 +203,7 @@ void ScrollBarWidget::drawWidget() {
state = ThemeEngine::kScrollbarStateSlider;
}
- Common::Rect clipRect = getBossClipRect();
- //scrollbar is not a usual child of ScrollContainerWidget, so it gets this special treatment
- if (dynamic_cast<ScrollContainerWidget *>(_boss))
- clipRect.right += _w;
- g_gui.theme()->drawScrollbarClip(Common::Rect(_x, _y, _x+_w, _y+_h), clipRect, _sliderPos, _sliderHeight, state, _state);
+ g_gui.theme()->drawScrollbar(Common::Rect(_x, _y, _x + _w, _y + _h), _sliderPos, _sliderHeight, state);
}
} // End of namespace GUI
diff --git a/gui/widgets/scrollcontainer.cpp b/gui/widgets/scrollcontainer.cpp
index d6b1b740fd..7994c0078d 100644
--- a/gui/widgets/scrollcontainer.cpp
+++ b/gui/widgets/scrollcontainer.cpp
@@ -140,7 +140,8 @@ void ScrollContainerWidget::reflowLayout() {
}
void ScrollContainerWidget::drawWidget() {
- g_gui.theme()->drawDialogBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + getHeight() - 1), getBossClipRect(), ThemeEngine::kDialogBackgroundDefault);
+ g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x + _w, _y + getHeight() - 1),
+ ThemeEngine::kDialogBackgroundDefault);
}
bool ScrollContainerWidget::containsWidget(Widget *w) const {
@@ -155,4 +156,9 @@ Widget *ScrollContainerWidget::findWidget(int x, int y) {
return Widget::findWidgetInChain(_firstWidget, x + _scrolledX, y + _scrolledY);
}
+Common::Rect ScrollContainerWidget::getClipRect() const {
+ // Make sure the clipping rect contains the scrollbar so it is properly redrawn
+ return Common::Rect(getAbsX(), getAbsY(), getAbsX() + _w, getAbsY() + getHeight());
+}
+
} // End of namespace GUI
diff --git a/gui/widgets/scrollcontainer.h b/gui/widgets/scrollcontainer.h
index 9366a0b658..c4b2f716e6 100644
--- a/gui/widgets/scrollcontainer.h
+++ b/gui/widgets/scrollcontainer.h
@@ -48,6 +48,8 @@ public:
virtual bool containsWidget(Widget *) const;
+ Common::Rect getClipRect() const override;
+
protected:
// We overload getChildY to make sure child widgets are positioned correctly.
// Essentially this compensates for the space taken up by the tab title header.
diff --git a/gui/widgets/tab.cpp b/gui/widgets/tab.cpp
index dfcb919264..977aaaf021 100644
--- a/gui/widgets/tab.cpp
+++ b/gui/widgets/tab.cpp
@@ -167,7 +167,7 @@ void TabWidget::setActiveTab(int tabID) {
}
_activeTab = tabID;
_firstWidget = _tabs[tabID].firstWidget;
-
+
// Also ensure the tab is visible in the tab bar
if (_firstVisibleTab > tabID)
setFirstVisible(tabID, true);
@@ -320,9 +320,12 @@ void TabWidget::drawWidget() {
tabs.push_back(_tabs[i].title);
widths.push_back(_tabs[i]._tabWidth);
}
- g_gui.theme()->drawDialogBackgroundClip(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP+_tabHeight), getBossClipRect(), _bodyBackgroundType);
+ g_gui.theme()->drawDialogBackground(
+ Common::Rect(_x + _bodyLP, _y + _bodyTP, _x + _w - _bodyRP, _y + _h - _bodyBP + _tabHeight),
+ _bodyBackgroundType);
- g_gui.theme()->drawTabClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), _tabHeight, widths, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad);
+ g_gui.theme()->drawTab(Common::Rect(_x, _y, _x + _w, _y + _h), _tabHeight, widths, tabs,
+ _activeTab - _firstVisibleTab);
}
void TabWidget::draw() {
diff --git a/gui/widgets/tab.h b/gui/widgets/tab.h
index bdd3e56b46..f85d30a9c6 100644
--- a/gui/widgets/tab.h
+++ b/gui/widgets/tab.h
@@ -101,15 +101,15 @@ public:
_tabs[tabID].title = title;
}
- virtual void handleMouseDown(int x, int y, int button, int clickCount);
- virtual bool handleKeyDown(Common::KeyState state);
- virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+ virtual void handleMouseDown(int x, int y, int button, int clickCount) override;
+ virtual bool handleKeyDown(Common::KeyState state) override;
+ virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
virtual int getFirstVisible() const;
virtual void setFirstVisible(int tabID, bool adjustIfRoom = false);
- virtual bool containsWidget(Widget *) const;
+ virtual bool containsWidget(Widget *) const override;
- virtual void reflowLayout();
+ virtual void reflowLayout() override;
void draw() override;
void markAsDirty() override;
@@ -117,12 +117,12 @@ public:
protected:
// We overload getChildY to make sure child widgets are positioned correctly.
// Essentially this compensates for the space taken up by the tab title header.
- virtual int16 getChildY() const;
- virtual uint16 getHeight() const;
+ virtual int16 getChildY() const override;
+ virtual uint16 getHeight() const override;
- virtual void drawWidget();
+ virtual void drawWidget() override;
- virtual Widget *findWidget(int x, int y);
+ virtual Widget *findWidget(int x, int y) override;
virtual void adjustTabs(int value);
diff --git a/image/codecs/cinepak.cpp b/image/codecs/cinepak.cpp
index 2b02fc8127..1c477c82d5 100644
--- a/image/codecs/cinepak.cpp
+++ b/image/codecs/cinepak.cpp
@@ -405,8 +405,13 @@ const Graphics::Surface *CinepakDecoder::decodeFrame(Common::SeekableReadStream
_curFrame.height = stream.readUint16BE();
_curFrame.stripCount = stream.readUint16BE();
- if (!_curFrame.strips)
+ if (!_curFrame.strips) {
_curFrame.strips = new CinepakStrip[_curFrame.stripCount];
+ for (uint16 i = 0; i < _curFrame.stripCount; i++) {
+ initializeCodebook(i, 1);
+ initializeCodebook(i, 4);
+ }
+ }
debug(4, "Cinepak Frame: Width = %d, Height = %d, Strip Count = %d", _curFrame.width, _curFrame.height, _curFrame.stripCount);
@@ -424,7 +429,6 @@ const Graphics::Surface *CinepakDecoder::decodeFrame(Common::SeekableReadStream
_curFrame.surface->create(_curFrame.width, _curFrame.height, _pixelFormat);
}
- // Reset the y variable.
_y = 0;
for (uint16 i = 0; i < _curFrame.stripCount; i++) {
@@ -500,6 +504,19 @@ const Graphics::Surface *CinepakDecoder::decodeFrame(Common::SeekableReadStream
return _curFrame.surface;
}
+void CinepakDecoder::initializeCodebook(uint16 strip, byte codebookType) {
+ CinepakCodebook *codebook = (codebookType == 1) ? _curFrame.strips[strip].v1_codebook : _curFrame.strips[strip].v4_codebook;
+
+ for (uint16 i = 0; i < 256; i++) {
+ memset(codebook[i].y, 0, 4);
+ codebook[i].u = 0;
+ codebook[i].v = 0;
+
+ if (_ditherType == kDitherTypeQT)
+ ditherCodebookQT(strip, codebookType, i);
+ }
+}
+
void CinepakDecoder::loadCodebook(Common::SeekableReadStream &stream, uint16 strip, byte codebookType, byte chunkID, uint32 chunkSize) {
CinepakCodebook *codebook = (codebookType == 1) ? _curFrame.strips[strip].v1_codebook : _curFrame.strips[strip].v4_codebook;
diff --git a/image/codecs/cinepak.h b/image/codecs/cinepak.h
index 4efb1191cc..3b0fe477a6 100644
--- a/image/codecs/cinepak.h
+++ b/image/codecs/cinepak.h
@@ -94,6 +94,7 @@ private:
byte *_colorMap;
DitherType _ditherType;
+ void initializeCodebook(uint16 strip, byte codebookType);
void loadCodebook(Common::SeekableReadStream &stream, uint16 strip, byte codebookType, byte chunkID, uint32 chunkSize);
void decodeVectors(Common::SeekableReadStream &stream, uint16 strip, byte chunkID, uint32 chunkSize);
diff --git a/image/codecs/indeo/indeo.cpp b/image/codecs/indeo/indeo.cpp
index 4826137358..80b424fb90 100644
--- a/image/codecs/indeo/indeo.cpp
+++ b/image/codecs/indeo/indeo.cpp
@@ -465,22 +465,26 @@ IVI45DecContext::IVI45DecContext() : _gb(nullptr), _frameNum(0), _frameType(0),
/*------------------------------------------------------------------------*/
IndeoDecoderBase::IndeoDecoderBase(uint16 width, uint16 height, uint bitsPerPixel) : Codec() {
- switch (bitsPerPixel) {
- case 15:
- _pixelFormat = Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0);
- break;
- case 16:
- _pixelFormat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
- break;
- case 24:
- _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
- break;
- case 32:
- _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
- break;
- default:
- error("Invalid color depth");
- break;
+ _pixelFormat = g_system->getScreenFormat();
+
+ if (_pixelFormat.bytesPerPixel == 1) {
+ switch (bitsPerPixel) {
+ case 15:
+ _pixelFormat = Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0);
+ break;
+ case 16:
+ _pixelFormat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ break;
+ case 24:
+ _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
+ break;
+ case 32:
+ _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+ break;
+ default:
+ error("Invalid color depth");
+ break;
+ }
}
_surface.create(width, height, _pixelFormat);
diff --git a/image/codecs/indeo3.cpp b/image/codecs/indeo3.cpp
index 1aa1ef73b6..2b681c98ce 100644
--- a/image/codecs/indeo3.cpp
+++ b/image/codecs/indeo3.cpp
@@ -44,22 +44,26 @@ Indeo3Decoder::Indeo3Decoder(uint16 width, uint16 height, uint bitsPerPixel) : _
_iv_frame[0].the_buf = 0;
_iv_frame[1].the_buf = 0;
- switch (bitsPerPixel) {
- case 15:
- _pixelFormat = Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0);
- break;
- case 16:
- _pixelFormat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
- break;
- case 24:
- _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
- break;
- case 32:
- _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
- break;
- default:
- error("Invalid color depth");
- break;
+ _pixelFormat = g_system->getScreenFormat();
+
+ if (_pixelFormat.bytesPerPixel == 1) {
+ switch (bitsPerPixel) {
+ case 15:
+ _pixelFormat = Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0);
+ break;
+ case 16:
+ _pixelFormat = Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
+ break;
+ case 24:
+ _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
+ break;
+ case 32:
+ _pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
+ break;
+ default:
+ error("Invalid color depth");
+ break;
+ }
}
_surface = new Graphics::Surface;
diff --git a/po/POTFILES b/po/POTFILES
index ac4866032e..df71f61ed6 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -23,6 +23,7 @@ gui/saveload-dialog.cpp
gui/storagewizarddialog.cpp
gui/themebrowser.cpp
gui/ThemeEngine.cpp
+gui/unknown-game-dialog.cpp
gui/updates-dialog.cpp
gui/widget.cpp
@@ -35,6 +36,7 @@ common/updates.cpp
engines/advancedDetector.cpp
engines/dialogs.cpp
engines/engine.cpp
+engines/game.cpp
audio/adlib.cpp
audio/fmopl.cpp
diff --git a/po/be_BY.po b/po/be_BY.po
index ebb4141967..5dd03a6e8d 100644
--- a/po/be_BY.po
+++ b/po/be_BY.po
@@ -6,9 +6,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-11-28 19:36+0300\n"
-"Last-Translator: Ivan Lukyanov <greencis@mail.ru>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:07+0000\n"
+"Last-Translator: Adrian Fruehwirth <bonki@scummvm.org>\n"
"Language-Team: Belarusian <https://translations.scummvm.org/projects/scummvm/"
"scummvm/be/>\n"
"Language: be_BY\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 2.0.4\n"
+"X-Generator: Weblate 2.9\n"
"X-Language-name: Belarusian\n"
#: gui/about.cpp:94
@@ -57,7 +57,7 @@ msgstr "Уверх"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Абраць"
msgid "Select directory where to download game data"
msgstr "Абярыце дырэкторыю для спампавання дадзеных гульні"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Абярыце дырэкторыю з файламі гульні"
@@ -115,7 +115,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -128,7 +128,7 @@ msgstr "Так"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -139,7 +139,7 @@ msgstr "Так"
msgid "No"
msgstr "Не"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM не можа адкрыць азначаную дырэкторыю!"
@@ -152,8 +152,8 @@ msgstr ""
"мае файл з тым жа імем."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -168,7 +168,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -538,10 +538,10 @@ 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
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Закрыць"
@@ -590,111 +590,111 @@ msgstr "Націсніце клавішу для прызначэння"
msgid "Choose an action to map"
msgstr "Абярыце дзеянне для прызначэння"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~В~ыхад"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Завяршыць ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "Пра п~р~аграму..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Пра праграму ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~Н~алады..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Змяніць глабальныя налады ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "П~у~ск"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Запусціць абраную гульню"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~З~агрузіць..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Загрузіць захаванне для абранай гульні"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~Д~адаць гульню..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Утрымвайце клавішу Shift, каб дадаць некалькі гульняў"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "Н~а~лады гульні..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Змяніць налады гульні"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "В~ы~даліць гульню"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Выдаліць гульню са спісу. Не выдаляе гульню з носьбіта"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~Д~адаць гульню..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "Н~а~лады гульні..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "В~ы~даліць гульню"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Пошук у спісе гульняў"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Пошук:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Загрузіць гульню:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Загрузіць"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -702,63 +702,63 @@ msgstr ""
"Вы сапраўды жадаеце запусціць дэтэктар усіх гульняў? Гэта патэнцыяльна можа "
"дадаць вялікую колькасць гульняў."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
"Гэта дырэкторыя пакуль не можа выкарыстоўвацца, у яе цяпер загружаюцца "
"дадзеныя!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Вы сапраўды жадаеце выдаліць налады для гэтай гульні?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Вы жадаеце загрузіць гульню?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Гэтая гульня не падтрымвае загрузку захаванняў праз галоўнае меню."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr "ScummVM не можа знайсці рухавічок для запуску абранай гульні!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM не можа знайсці гульню ў азначанай дырэкторыі!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Абярыце гульню:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Шмат гульняў..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Запіс..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... шукаю ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Пошук скончаны!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "Знойдзена %d новых гульняў, прапушчана %d раней дададзеных гульняў."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Прагледжана %d дырэкторый..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "Знойдзена %d новых гульняў, прапушчана %d раней дададзеных гульняў..."
@@ -1593,31 +1593,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Абярыце тэму"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Без графікі"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Без графікі"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Стандартны растарызатар"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Стандартны"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Растарызатар са згладжваннем"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Са згладжваннем"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Узнавіць гульню:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1640,7 +1668,7 @@ msgstr ""
msgid "Proceed"
msgstr "Працягнуць"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Ачысціць значэнне"
@@ -1783,23 +1811,6 @@ msgstr "Штомесяц"
msgid "<Bad value>"
msgstr "<Хібнае значэнне>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Здаецца, гульня ў '%s' ёсць невядомай гульнёй на рухавічку %s.\n"
-"\n"
-"Калі ласка, перадайце камандзе ScummVM на %s наступныя дадзеныя разам з "
-"назвай гульні, яе версіяй, мовай і інш.:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Магчымыя ID гульні:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "Працяг~н~уць"
@@ -1835,12 +1846,12 @@ msgstr "Г~а~лоўнае меню"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1855,12 +1866,12 @@ msgstr "Захаваць гульню:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1976,22 +1987,48 @@ msgstr ""
msgid "Start anyway"
msgstr "Усё адно запусціць"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Здаецца, гульня ў '%s' ёсць невядомай гульнёй на рухавічку %s.\n"
+"\n"
+"Калі ласка, перадайце камандзе ScummVM на %s наступныя дадзеныя разам з "
+"назвай гульні, яе версіяй, мовай і інш.:"
+
+#: engines/game.cpp:162
+#, fuzzy, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Магчымыя ID гульні:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Эмулятар AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Эмулятар MAME OPL"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Эмулятар DOSBox OPL"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Эмулятар Nuked OPL"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "Прамы FM ALSA"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr ""
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2785,7 +2822,7 @@ msgstr "Правяраю абнаўленні..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2793,7 +2830,7 @@ msgstr "Не атрымалася знайсці файл рухавічка %s."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2838,6 +2875,7 @@ msgstr "Выкарыстоўваць арыгінальныя экраны запісу/чытання гульні"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"Выкарыстоўваць арыгінальныя экраны чытання/захавання гульні замест ScummVM"
@@ -2888,9 +2926,9 @@ msgstr ""
"замест уводу ў рэальным часе."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2902,9 +2940,9 @@ msgid "Restore game:"
msgstr "Узнавіць гульню:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2915,7 +2953,7 @@ msgstr "Узнавіць гульню:"
msgid "Restore"
msgstr "Узнавіць"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2937,7 +2975,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2953,11 +2991,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Файл застаўкі '%s' не знойдзены!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Рэжым без колеру"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Уключыць рэжым для людзей са слабым успрыманнем колеру"
@@ -3252,16 +3290,16 @@ msgstr "Анімаваны інтэрфейс гульні"
msgid "Naughty game mode"
msgstr "Гарэзны рэжым гульні"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Прайграваць ролік пралёту над Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "Ролік пралёту над Myst не прайграваўся арыгінальным рухавічком."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Р~эжым хуткага пераходу актываваны"
@@ -3282,27 +3320,27 @@ msgstr "Паказаць ~к~арту"
msgid "Main Men~u~"
msgstr "Галоўнае мен~ю~"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~Э~фекты вады ўключаны"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Пераходы:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Вылучаны"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Хуткія"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Звычайныя"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Лепшыя"
@@ -3310,7 +3348,7 @@ msgstr "Лепшыя"
msgid "The game is paused. Press any key to continue."
msgstr "Гульня прыпынена. Каб працягнуць, націсніце любую кнопку."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3318,7 +3356,7 @@ msgstr ""
"Бракуе выканальнага файла Riven. Выканальны файл для Windows завецца 'riven."
"exe' ці 'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3326,14 +3364,14 @@ msgstr ""
"Замест яго падыдзе файл усталёўніка 'arcriven.z'. Таксама можна скарыстаць "
"выканальны файл 'Riven' для Mac."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
"Бракуе файла 'extras.mhk'. Замест яго можна скарыстаць файл 'arcriven.z'."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "Бракуе наступных файлаў гульні Riven:\n"
@@ -3681,7 +3719,7 @@ msgstr ""
"памылкі ў ScummVM не ўзнікаюць, таму рэкамендуецца выдаліць іх з тэчкі з "
"гульнёй, каб вымінуць неспадзяваныя праблемы надалей."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3694,7 +3732,7 @@ msgstr ""
"калі ласка, паведаміце камандзе ScummVM наступныя дадзеныя\n"
"разам з назвай гульні, яе версіяй, мовай і інш.:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3703,11 +3741,11 @@ msgstr ""
"Каб пазбегнуць пірацтва, Lite-версія гульні Putt-Putt Saves the Zoo для iOS\n"
"не падтрымваецца. Поўную версію гульні можна набыць у iTunes Store."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Паказваць радок аб'ектаў"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Паказваць назвы аб'ектаў унізе экрана"
@@ -4385,7 +4423,7 @@ msgstr ""
"Рэжым \"роднага\" MIDI патрабуе абнаўленне Roland Upgrade ад\n"
"LucasArts, але бракуе %s. Пераключаюся на AdLib."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4469,14 +4507,14 @@ msgstr "Уступ з дыскет"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Выкарыстоўваць уступ з гнуткіх дыскаў (толькі для CD-версіі гульні)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, fuzzy, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
"Няправільная версія файла рухавічка %s. Чакалася %d.%d, але знойдзена %d.%d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, fuzzy, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr "Не атрымалася знайсці файл рухавічка %s."
@@ -4600,27 +4638,39 @@ msgstr "Захаваная гульня №%d загружана"
msgid "Could not quick load the saved game #%d"
msgstr "Не атрымалася хутка загрузіць захаваную гульню №%d"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Паказаць лічыльнік кадраў у секунду"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "Паказаць у верхнім левым куце бягучую колькасць кадраў у секунду"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Білінейная фільтрацыя спрайтаў (марудна)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Ужываць білінейную фільтрацыю для індывідуальных спрайтаў"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Выкарыстоўваць арыгінальныя экраны запісу і захавання гульні замест "
-"зробленых у ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4656,7 +4706,7 @@ msgstr ""
"Выкарыстоўваць відэа MPEG з DVD-версіі замест відэа нізкага адрознення ў "
"фармаце AVI"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4665,6 +4715,11 @@ msgstr ""
"Гэты файл захаванай гульні мае версію %u, але рухавічок падтрымвае версіі да "
"%d. Вам патрэбна новая версія ScummVM для карыстання гэтым файлам."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Выкарыстоўваць арыгінальныя экраны запісу і захавання гульні замест "
+#~ "зробленых у ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr "(Вы заўсёды можаце ўключыць яе ў наладах на закладцы \"Рознае\")"
diff --git a/po/ca_ES.po b/po/ca_ES.po
index 04a7e15568..8c54a40672 100644
--- a/po/ca_ES.po
+++ b/po/ca_ES.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.6.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-02-20 14:15+0000\n"
-"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:09+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Catalan <https://translations.scummvm.org/projects/scummvm/"
"scummvm/ca/>\n"
"Language: ca_ES\n"
@@ -57,7 +57,7 @@ msgstr "Amunt"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Escull"
msgid "Select directory where to download game data"
msgstr "Seleccioneu el directori on descarregar les dades del joc"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Seleccioneu el directori amb les dades del joc"
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Sэ"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Sэ"
msgid "No"
msgstr "No"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM no ha pogut obrir el directori especificat!"
@@ -153,8 +153,8 @@ msgstr ""
"arxiu amb el mateix nom."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -169,7 +169,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "D'acord"
@@ -539,10 +539,10 @@ msgstr ""
"Realment voleu retorna tots els ajustos de FluidSynth als seus valors per "
"defecte?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Tanca"
@@ -591,113 +591,113 @@ msgstr "Premeu la tecla a associar"
msgid "Choose an action to map"
msgstr "SelЗleccioneu una acciѓ a assignar"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~T~anca"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Surt de ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "~Q~uant a..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Quant a ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~pcions..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Canvia les opcions globals de ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~I~nicia"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Iniciant el joc seleccionat"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~C~arrega..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Carrega una partida pel joc seleccionat"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~A~fegeix Joc..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Mantingueu premut Shift per a l'Addiciѓ Massiva"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~E~dita Joc..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Canvia les opcions del joc"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~S~uprimeix Joc"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr ""
"Elimina un joc de la llista. Els fitxers de dades del joc es mantenen "
"intactes"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~A~fegeix Joc..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~E~dita Joc..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~S~uprimeix"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Cerca a la llista de jocs"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Cerca:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Carrega partida:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Carrega"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -705,62 +705,62 @@ msgstr ""
"Esteu segur que voleu executar el detector massiu de jocs? Aixђ pot afegir "
"una gran quantitat de jocs."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Realment voleu suprimir la configuraciѓ d'aquest joc?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Desitges carregar la partida guardada?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Aquest joc no suporta la cрrrega de partides des del llanчador."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM no ha pogut trobar cap motor capaч d'executar el joc seleccionat!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM no ha pogut trobar cap joc al directori especificat!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Seleccioneu el joc:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Addiciѓ Massiva..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr ""
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... progrщs ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "S'ha acabat la cerca!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "S'han trobat %d jocs nous, s'han ignorat %d jocs afegits prшviament."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "S'han cercat %d directoris ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1595,34 +1595,62 @@ msgstr ""
msgid "Select a Theme"
msgstr "Seleccioneu un Tema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "GFX desactivats"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "GFX desactivats"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
#, fuzzy
msgid "Standard Renderer"
msgstr "Pintat estрndard (16bpp)"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Estрndard"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
#, fuzzy
msgid "Antialiased Renderer"
msgstr "Pintat amb antialias (16bpp)"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
#, fuzzy
msgid "Antialiased"
msgstr "Amb antialias (16bpp)"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Recupera la partida:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1640,7 +1668,7 @@ msgstr ""
msgid "Proceed"
msgstr ""
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Neteja el valor"
@@ -1783,19 +1811,6 @@ msgstr ""
msgid "<Bad value>"
msgstr "<Valor incorrecte>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~C~ontinua"
@@ -1831,12 +1846,12 @@ msgstr "~R~etorna al Llanчador"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1851,12 +1866,12 @@ msgstr "Desa la partida:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1970,22 +1985,44 @@ msgstr ""
msgid "Start anyway"
msgstr "Inicia de totes maneres"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Emulador d'AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Emulador OPL de MAME"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Emulador OPL de DOSBox"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Emulador OPL de Nuked"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr ""
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2774,7 +2811,7 @@ msgstr "Comprova les actualitzacions..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2782,7 +2819,7 @@ msgstr ""
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2827,6 +2864,7 @@ msgstr "Utilitza les pantalles originals de desat/cрrrega"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
@@ -2872,9 +2910,9 @@ msgid ""
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2886,9 +2924,9 @@ msgid "Restore game:"
msgstr "Recupera la partida:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2899,7 +2937,7 @@ msgstr "Recupera la partida:"
msgid "Restore"
msgstr "Restaura"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, fuzzy, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2921,7 +2959,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, fuzzy, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2937,12 +2975,12 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "No s'ha trobat el fitxer d'escena '%s'!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
#, fuzzy
msgid "Color Blind Mode"
msgstr "Mode clic"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr ""
@@ -3232,16 +3270,16 @@ msgstr ""
msgid "Naughty game mode"
msgstr ""
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr ""
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "Mode ~Z~ip activat"
@@ -3264,31 +3302,31 @@ msgstr "~M~ostra el mapa"
msgid "Main Men~u~"
msgstr "~M~enњ Principal"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~E~fecte de l'aigua activat"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
#, fuzzy
msgid "Transitions:"
msgstr "~T~ransicions activades"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
#, fuzzy
msgid "Disabled"
msgstr "GFX desactivats"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
#, fuzzy
msgid "Fastest"
msgstr "Mode rрpid"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
#, fuzzy
msgid "Normal"
msgstr "OpenGL Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3297,25 +3335,25 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr "Joc pausat. Premeu ESPAI per continuar."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
msgstr ""
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
msgstr ""
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3633,7 +3671,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3642,19 +3680,19 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
"The full version is available for purchase from the iTunes Store."
msgstr ""
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
#, fuzzy
msgid "Show Object Line"
msgstr "Mostra les etiquetes dels objectes"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr ""
@@ -4340,7 +4378,7 @@ msgstr ""
"El suport de MIDI natiu requereix l'actualitzaciѓ Roland de LucasArts,\n"
"perђ no s'ha trobat %s. S'utilitzarр AdLib."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
#, fuzzy
msgid ""
"Usually, Maniac Mansion would start now. But for that to work, the game "
@@ -4419,13 +4457,13 @@ msgid "Use the floppy version's intro (CD version only)"
msgstr ""
"Utilitza la introducciѓ de la versiѓ de disquets (nomщs per a la versiѓ CD)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4555,27 +4593,39 @@ msgstr ""
msgid "Could not quick load the saved game #%d"
msgstr "Voleu carregar o desar el joc?"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr ""
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr ""
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr ""
-#: engines/zvision/detection_tables.h:52
-#, fuzzy
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Utilitza les pantalles originals de desat/cрrrega, en lloc de les de ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4614,13 +4664,19 @@ msgstr ""
"Utilitza el conjunt alternatiu de cursors platejats, en lloc dels normals "
"daurats"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
"%d. You will need an updated version of the engine to use this saved game."
msgstr ""
+#, fuzzy
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Utilitza les pantalles originals de desat/cрrrega, en lloc de les de "
+#~ "ScummVM"
+
#~ msgid "Check for updates automatically"
#~ msgstr "Comprova les actualitzacions automрticament"
diff --git a/po/cs_CZ.po b/po/cs_CZ.po
index 6a57df8b65..f9132c37a2 100644
--- a/po/cs_CZ.po
+++ b/po/cs_CZ.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.7.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-11-29 07:42+0000\n"
-"Last-Translator: Zbynьk Schwarz <zbynek.schwarz@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:09+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Czech <https://translations.scummvm.org/projects/scummvm/"
"scummvm/cs/>\n"
"Language: cs_CZ\n"
@@ -59,7 +59,7 @@ msgstr "Jэt nahoru"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -83,7 +83,7 @@ msgstr "Zvolit"
msgid "Select directory where to download game data"
msgstr "Vyberte adresсј kam data her stсhnout"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Vyberte adresсј s daty hry"
@@ -118,7 +118,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -131,7 +131,7 @@ msgstr "Ano"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -142,7 +142,7 @@ msgstr "Ano"
msgid "No"
msgstr "Ne"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM nemohl tento adresсј otevјэt!"
@@ -155,8 +155,8 @@ msgstr ""
"nсzvem."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -171,7 +171,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -540,10 +540,10 @@ msgstr ""
"Opravdu chcete resetovat veЙkerс nastavenэ FluidSynth na jejich v§chozэ "
"hodnoty?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Zavјэt"
@@ -592,111 +592,111 @@ msgstr "Zmсшknьte klсvesu pro pјiјazenэ"
msgid "Choose an action to map"
msgstr "Zvolte шinnost k mapovсnэ"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~U~konшit"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Ukonшit ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "~O~ Programu..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "O ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~V~olby..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Zmьnit globсlnэ volby ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~S~pustit"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Spustit zvolenou hru"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~N~ahrсt..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Nahrсt uloОenou pozici pro zvolenou hru"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~P~јidat hru..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "PodrОte Shift pro Hromadnщ Pјidсnэ"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~U~pravit Hru..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Zmьnit volby hry"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~O~dstranit Hru"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Odstranit hru ze seznamu. Hernэ data zљstanou zachovсna"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~P~јidat hru..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~U~pravit hru..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~O~dstranit hru"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Hledat v seznamu her"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Hledat:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Nahrсt hru:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Nahrсt"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -704,61 +704,61 @@ msgstr ""
"Opravdu chcete spustit hromadnou detekci her? Toto by mohlo potenciсlnь "
"pјidat velkou spoustu her."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr "Tento adresсј prozatэm nejde pouОэt, je do nьj stahovсno!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Opravdu chcete odstranit nastavenэ tщto hry?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Chcete naшэst uloОenou pozici?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Tato hra nepodporuje spouЙtьnэ her ze spouЙtьшe."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
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!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM nemohl v zadanщm adresсјi najэt Осdnou hru!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Vybrat hru:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Hromadnщ Pјidсnэ..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Nahrсt..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... prљbьh ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Hledсnэ dokonшeno!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, 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."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Prohledсno %d adresсјљ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, 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 ..."
@@ -1596,31 +1596,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Vyberte Vzhled"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "GFX zakсzсno"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "GFX zakсzсno"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standardnэ Vykreslovaш"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Standardnэ"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Vykreslovaш s vyhlazen§mi hranami"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "S vyhlazen§mi hranami"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Obnovit hru:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1643,7 +1671,7 @@ msgstr ""
msgid "Proceed"
msgstr "Pokraшovat"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Vyшistit hodnotu"
@@ -1786,24 +1814,6 @@ msgstr "Mьsэшnь"
msgid "<Bad value>"
msgstr "<Љpatnс hodnota>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Hra nachсzejэcэ se v '%s' pravdьpodobnь vyuОэvс neznсmou variantu jсdra "
-"%s .\n"
-"\n"
-"Prosэm pјepoЙlete nсsledujэcэ data t§mu ScummVM na %s spolu s nсzvem hry, "
-"kterou jste chtьli pјidat, a jejэ verzэ, jazykem, atd.:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Shodnщ ID hry:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~P~okraшovat"
@@ -1839,12 +1849,12 @@ msgstr "~N~сvrat do SpouЙtьшe"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1859,12 +1869,12 @@ msgstr "UloОit hru:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1979,22 +1989,49 @@ msgstr ""
msgid "Start anyway"
msgstr "Pјesto spustit"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Hra nachсzejэcэ se v '%s' pravdьpodobnь vyuОэvс neznсmou variantu jсdra "
+"%s .\n"
+"\n"
+"Prosэm pјepoЙlete nсsledujэcэ data t§mu ScummVM na %s spolu s nсzvem hry, "
+"kterou jste chtьli pјidat, a jejэ verzэ, jazykem, atd.:"
+
+#: engines/game.cpp:162
+#, fuzzy, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Shodnщ ID hry:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "AdLib Emulсtor"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL Emulсtor"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "DOSBox OPL Emulсtor"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL Emulсtor"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Pјэmс FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2789,7 +2826,7 @@ msgstr "Zkontrolovat Aktualizace..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2797,7 +2834,7 @@ msgstr "Nelze najэt datovщ soubory jсdra '%s'."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2842,6 +2879,7 @@ msgstr "PouОэt pљvodnэ obrazovky naшtenэ/uloОenэ"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
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"
@@ -2889,9 +2927,9 @@ msgstr ""
"јсdku v reсlnщm шase."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2903,9 +2941,9 @@ msgid "Restore game:"
msgstr "Obnovit hru:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2916,7 +2954,7 @@ msgstr "Obnovit hru:"
msgid "Restore"
msgstr "Obnovit"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2938,7 +2976,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2954,11 +2992,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Soubor videa '%s' nenalezen'!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "ReОim pro barvoslepщ"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Standardnь zapэnat reОim pro barvoslepщ"
@@ -3252,16 +3290,16 @@ msgstr "Animovanщ hernэ rozhranэ"
msgid "Naughty game mode"
msgstr "Hanbat§ hernэ reОim"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Pјehrсt video pјeletu v the Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "Video pјeletu v The Myst pљvodnэ jсdro nepјehrсvalo."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~R~eОim SviЙtьnэ Aktivovсn"
@@ -3282,27 +3320,27 @@ msgstr "~Z~obrazit mapu"
msgid "Main Men~u~"
msgstr "~H~lavnэ nabэdka"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~E~fekt Vody Zapnut"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Pјechody:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Zakсzсno"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "NejrychlejЙэ"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normсlnэ"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "NejlepЙэ"
@@ -3310,7 +3348,7 @@ msgstr "NejlepЙэ"
msgid "The game is paused. Press any key to continue."
msgstr "Hra je pozastavena. Pro pokraшovanэ stisknьte libovolnou klсvesu."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3318,7 +3356,7 @@ msgstr ""
"Schсzэ vсm spustiteln§ soubor Riven. Ve Windows se soubor jmenuje 'riven."
"exe' nebo 'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3326,7 +3364,7 @@ msgstr ""
"Nebo mљОete takщ pouОэt soubor instalace 'arcriven.z'. Dсle lze takщ vyuОэt "
"spustiteln§ soubor ze systщmu Mac 'Riven'."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3334,7 +3372,7 @@ msgstr ""
"Schсzэ vсm soubor 'extras.mhk'. Mэsto toho lze pouОэt soubor instalace "
"'arcriven.z'."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "Chybэ vсm nсsledujэcэ potјebnщ datovщ soubory Riven:\n"
@@ -3674,7 +3712,7 @@ msgstr ""
"abyste vЙechny zсplaty tohoto typu odstranili z hernэ sloОky, abyste "
"pјedeЙli pozdьjЙэm v§skytљm neoшekсvan§ch chyb a problщmљ."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3687,7 +3725,7 @@ msgstr ""
"data t§mu ScummVM spolu s nсzvem hry, kterou jste chtьli pјidat, \n"
"a jejэ verzэ, jazykem, atd.:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3697,11 +3735,11 @@ msgstr ""
"pјedeЙlo nelegсlnэmu Йэјenэ.\n"
"Plnou verzi je moОno zakoupit v obchodь iTunes."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Zobrazit јсdek objektљ"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Zobrazit nсzvy objektљ v dolnэ шсsti obrazovky"
@@ -4379,7 +4417,7 @@ msgstr ""
"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:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4462,14 +4500,14 @@ msgstr "кvod z diskety"
msgid "Use the floppy version's intro (CD version only)"
msgstr "PouОэt verzi њvodu z diskety (Pouze verze CD)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, fuzzy, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
"Nalezena data jсdra '%s' s nesprсvnou verzэ. Oшekсvсna %d.%d, ale byla %d.%d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, fuzzy, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr "Nelze najэt datovщ soubory jсdra '%s'."
@@ -4587,25 +4625,39 @@ msgstr "UloОenс pozice #%d byla rychle naшtena"
msgid "Could not quick load the saved game #%d"
msgstr "UloОenou pozici #%d nelze rychle naшэst"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Zobrazit poшэtadlo FPS"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
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"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Bilineсrnэ filtrovсnэ spritљ (POMALЩ)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "U kaОdщho spritu pouОэt bilineсrnэ filtrovсnэ"
-#: 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"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
+msgstr ""
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4641,7 +4693,7 @@ msgstr ""
"PouОэt video MPEG pochсzejэcэ z DVD verze namэsto videa AVI v nэzkщm "
"rozliЙenэ"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4650,6 +4702,9 @@ msgstr ""
"Tato uloОenс hra je z verze %u, ale nejvyЙЙэ verze, kterщ toto jсdro "
"podporuje, je %d. Abyste tuto hru naшetli, musэte zэskat novьjЙэ verzi jсdra."
+#~ 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"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr "(Toto nastavenэ vОdy mљОete zmьnit ve Volbсch v kartь Rљznщ)"
diff --git a/po/da_DK.po b/po/da_DK.po
index 71ee0bfd99..f68569a109 100644
--- a/po/da_DK.po
+++ b/po/da_DK.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-12-07 19:59+0000\n"
-"Last-Translator: stevenew <steffen@nyeland.dk>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:10+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Danish <https://translations.scummvm.org/projects/scummvm/"
"scummvm/da/>\n"
"Language: da_DK\n"
@@ -57,7 +57,7 @@ msgstr "Gх op"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Vцlg"
msgid "Select directory where to download game data"
msgstr "Vцlg bibliotek hvor spil data skal gemmes"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Vцlg bibliotek med spil data"
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Ja"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Ja"
msgid "No"
msgstr "Nej"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM kunne ikke хbne det angivne bibliotek!"
@@ -153,8 +153,8 @@ msgstr ""
"fil med det samme navn."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -169,7 +169,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -540,10 +540,10 @@ msgstr ""
"Vil du virkelig nulstille alle FluidSynth indstillinger til deres standard "
"vцrdier?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Luk"
@@ -592,111 +592,111 @@ msgstr "Tryk tasten for at tilknytte"
msgid "Choose an action to map"
msgstr "Vцlg en handling at kortlцgge"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~A~fslut"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Slut ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "~O~m..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Om ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~I~ndstillinger..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Цndre globale ScummVM indstillinger"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~S~tart"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Start det valgte spil"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "Ind~l~цs..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Indlцs gemmer for det valgte spil"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~T~ilfјj spil..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Hold Skift for at tilfјje flere"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~R~ediger spil..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Цndre spil indstillinger"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~F~jern spil"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Fjerner spil fra listen. Spillets data filer forbliver uberјrt"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~T~ilfјj spil..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~R~ediger spil..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~F~jern spil"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Sјg i spil liste"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Sјg:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Indlцs spil:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Indlцs"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -704,62 +704,62 @@ msgstr ""
"Vil du virkelig kјre fler spils detektoren? Dette kunne potentielt tilfјje "
"et stort antal spil."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr "Denne mappe kan ikke bruges endnu, der downloades filer til den!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Vil du virkelig fjerne denne spil konfiguration?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Vil du indlцse gemmer?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Dette spil understјtter ikke indlцsning af spil fra spiloversigten."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM kunne ikke finde en motor, istand til at afvikle det valgte spil!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM kunne ikke finde noget spil i det angivne bibliotek!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Vцlg spillet:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Tilfјj flere..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Optag..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... fremskridt ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Skan gennemfјrt!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "Opdaget %d nye spil, ignorerede %d tidligere tilfјjede spil."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Gennemset %d biblioteker ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "Fundet %d nye spil, ignorer %d tidligere tilfјjede spil ..."
@@ -1591,31 +1591,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Vцlg et tema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Deaktiveret GFX"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Deaktiveret GFX"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standard renderer"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Standard"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Antialias renderer"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Antialias"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Gendan spil:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1638,7 +1666,7 @@ msgstr ""
msgid "Proceed"
msgstr "Fortsцt"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Slet vцrdi"
@@ -1781,23 +1809,6 @@ msgstr "Mхnedlig"
msgid "<Bad value>"
msgstr "<Forkert vцrdi>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Spillet i '%s' ser ud til at vцre en ukendt %s \"motor\" spil variant.\n"
-"\n"
-"Rapportщr venligst fјlgende data til ScummVM teamet pх %s, sammen med navnet "
-"pх spillet du prјvede at tilfјje, samt denne version, sprog, etc.:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Matchede spil-id'er:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "Gen~o~ptag"
@@ -1833,12 +1844,12 @@ msgstr "~R~etur til oversigt"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1853,12 +1864,12 @@ msgstr "Gemmer:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1973,22 +1984,48 @@ msgstr ""
msgid "Start anyway"
msgstr "Start alligevel"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Spillet i '%s' ser ud til at vцre en ukendt %s \"motor\" spil variant.\n"
+"\n"
+"Rapportщr venligst fјlgende data til ScummVM teamet pх %s, sammen med navnet "
+"pх spillet du prјvede at tilfјje, samt denne version, sprog, etc.:"
+
+#: engines/game.cpp:162
+#, fuzzy, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Matchede spil-id'er:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "AdLib emulator"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL emulator"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "DOSBox OPL emulator"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL emulator"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2781,7 +2818,7 @@ msgstr "Sјg efter opdateringer..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2789,7 +2826,7 @@ msgstr "Kan ikke finde '%s' \"motorens\" data fil."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2835,6 +2872,7 @@ msgstr "Brug original gem/indlцs skцrme"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
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"
@@ -2882,9 +2920,9 @@ msgstr ""
"en realtids prompt."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2896,9 +2934,9 @@ msgid "Restore game:"
msgstr "Gendan spil:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2909,7 +2947,7 @@ msgstr "Gendan spil:"
msgid "Restore"
msgstr "Gendan"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2931,7 +2969,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2947,11 +2985,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Filmsekvens fil '%s' ikke fundet!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Farveblind-tilstand"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Aktivщr Farveblind tilstand som standard"
@@ -3247,16 +3285,16 @@ msgstr "Animeret spil brugerflade"
msgid "Naughty game mode"
msgstr "Uhyggelig spiltilstand"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Afspil Myst \"fly by\" film"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "Myst \"fly by\" filmen blev ikke afspillet af den originale \"motor\"."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~ip tilstand aktiveret"
@@ -3277,27 +3315,27 @@ msgstr "Vis ~K~ort"
msgid "Main Men~u~"
msgstr "Hovedmen~u~"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~V~andeffekter aktiveret"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Overgange:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Deaktiveret"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Hurtigst"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Bedst"
@@ -3305,7 +3343,7 @@ msgstr "Bedst"
msgid "The game is paused. Press any key to continue."
msgstr "Spillet er sat pх pause. Tryk en tast for at fortsцtte."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3313,7 +3351,7 @@ msgstr ""
"Du mangler en Riven eksekverbar fil. Den Windows eksekverbare fil er 'riven."
"exe' eller 'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3321,7 +3359,7 @@ msgstr ""
"Brug af 'arcriven.z' installationsfilen fungerer ogsх. Derudover kan du "
"bruge Mac 'Riven' eksekverbar."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3329,7 +3367,7 @@ msgstr ""
"Du mangler 'extras.mhk'. Brug af 'arcriven.z' installationsfilen fungerer "
"ogsх."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "Du mangler fјlgende krцvede Riven data filer:\n"
@@ -3677,7 +3715,7 @@ msgstr ""
"ScummVM, sх det anbefales at fjerne denne rettelse fra din spilmappe for at "
"undgх uventede fejl og/eller problemer senere."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3691,7 +3729,7 @@ msgstr ""
"fјlgende data til ScummVM holdet sammen med navnet pх spillet du forsјgte\n"
"at tilfјje og dens version, sprog osv .:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3701,11 +3739,11 @@ msgstr ""
"undgх piratkopiering.\n"
"Den fulde version er tilgцngelig for kјb fra iTunes Store."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Vis Objekt Linje"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Vis navne pх objekter nederst pх skцrmen"
@@ -4383,7 +4421,7 @@ msgstr ""
"Indbygget MIDI understјttelse krцver Roland opgradering fra LucasArts,\n"
"men %s mangler. Bruger AdLib i stedet."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4465,7 +4503,7 @@ msgstr "Diskette intro"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Brug diskette versionens intro (kun CD version)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, fuzzy, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4473,7 +4511,7 @@ msgstr ""
"Ukorrekt version af '%s' \"motorens\" data fil fundet. Forventet %d.%d, men "
"fandt %d.%d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, fuzzy, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr "Kan ikke finde '%s' \"motorens\" data fil."
@@ -4594,27 +4632,39 @@ msgstr "Gemt spil pх plads #%d hurtig-indlцst"
msgid "Could not quick load the saved game #%d"
msgstr "Kunne ikke hurtig-indlцse det gemte spil #%d"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Vis FPS-tцller"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "Vis det nuvцrende antal billeder per sekund i јverste venstre hjјrne"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Sprite bilineцr filtrering (langsom)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Anvend bilinцr filtrering til individuelle sprites"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
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"
@@ -4648,7 +4698,7 @@ msgstr "Brug hјj oplјsning MPEG-video"
msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr "Brug MPEG-video fra DVD-versionen, i stedet for lavere oplјsning AVI"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4658,6 +4708,11 @@ msgstr ""
"til version %d. Du skal bruge en opdateret version af \"motoren\" for at "
"bruge dette gemte spil."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Brug de originale gem/indlцs skцrme, i stedet for dem fra ScummVM "
+#~ "brugerfladen"
+
#, fuzzy
#~ msgid "Check for updates automatically"
#~ msgstr "Sјg efter opdateringer..."
diff --git a/po/de_DE.po b/po/de_DE.po
index 832d0de2cc..c1c83545d5 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.10.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2018-03-07 21:17+0000\n"
-"Last-Translator: Lothar Serra Mari <rootfather@scummvm.org>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-05-30 14:00+0000\n"
+"Last-Translator: Lothar Serra Mari <serra@scummvm.org>\n"
"Language-Team: German <https://translations.scummvm.org/projects/scummvm/"
"scummvm/de/>\n"
"Language: de_DE\n"
@@ -58,7 +58,7 @@ msgstr "Pfad hoch"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -84,7 +84,7 @@ msgstr ""
"Wфhlen Sie das Verzeichnis, in welches die Spieldaten heruntergeladen werden "
"sollen"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Verzeichnis mit Spieldateien auswфhlen"
@@ -114,12 +114,12 @@ msgid ""
"It looks like your connection is limited. Do you really want to download "
"files with it?"
msgstr ""
-"Ihre Internetverbindung ist scheinbar eingeschrфnkt. Mіchten Sie mit dieser "
-"Verbindung wirklich die Dateien herunterladen?"
+"Ihre Internetverbindung ist scheinbar eingeschrфnkt. Mіchten Sie die Dateien "
+"wirklich ќber diese Verbindung herunterladen?"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -132,7 +132,7 @@ msgstr "Ja"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -143,7 +143,7 @@ msgstr "Ja"
msgid "No"
msgstr "Nein"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM konnte das gewфhlte Verzeichnis nicht іffnen!"
@@ -156,8 +156,8 @@ msgstr ""
"beinhaltet eine Datei mit dem gleichen Namen."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -172,7 +172,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -201,7 +201,7 @@ msgstr "Spiel"
#: gui/editgamedialog.cpp:137
msgid "ID:"
-msgstr "Kennung:"
+msgstr "ID:"
#: gui/editgamedialog.cpp:137 gui/editgamedialog.cpp:139
#: gui/editgamedialog.cpp:140
@@ -209,13 +209,13 @@ msgid ""
"Short game identifier used for referring to saved games and running the game "
"from the command line"
msgstr ""
-"Kurzer Spielname, um die Spielstфnde zuzuordnen und das Spiel von der "
+"Kurzer Spielname, um Spielstфnde zuzuordnen und das Spiel von der "
"Kommandozeile aus starten zu kіnnen"
#: gui/editgamedialog.cpp:139
msgctxt "lowres"
msgid "ID:"
-msgstr "Kennung:"
+msgstr "ID:"
#: gui/editgamedialog.cpp:144 gui/editrecorddialog.cpp:59
msgid "Name:"
@@ -224,7 +224,7 @@ msgstr "Name:"
#: gui/editgamedialog.cpp:144 gui/editgamedialog.cpp:146
#: gui/editgamedialog.cpp:147
msgid "Full title of the game"
-msgstr "Voller Name des Spiels"
+msgstr "Vollstфndiger Name des Spiels"
#: gui/editgamedialog.cpp:146
msgctxt "lowres"
@@ -422,12 +422,12 @@ msgid ""
"want your saved games to sync, use default directory."
msgstr ""
"Spielstand-Synchronisierung funktioniert nicht mit anderen Verzeichnissen. "
-"Wenn SieIhre Spielstфnde synchronisieren mіchten, verwenden Sie das Standard-"
-"Verzeichnis."
+"Wenn Sie Ihre Spielstфnde synchronisieren mіchten, verwenden Sie das "
+"Standard-Verzeichnis."
#: gui/editgamedialog.cpp:535
msgid "This game ID is already taken. Please choose another one."
-msgstr "Diese Spielkennung ist schon vergeben. Bitte eine andere wфhlen."
+msgstr "Diese Spiel-ID ist bereits vergeben. Bitte eine andere wфhlen."
#: gui/editrecorddialog.cpp:58
msgid "Author:"
@@ -479,7 +479,7 @@ msgstr "Intensitфt:"
#: gui/fluidsynth-dialog.cpp:101
msgid "Chorus"
-msgstr "Chor"
+msgstr "Chorus"
#: gui/fluidsynth-dialog.cpp:105
msgid "N:"
@@ -544,10 +544,10 @@ msgstr ""
"Mіchten Sie wirklich alle FluidSynth-Einstellungen auf ihre Standard-Werte "
"zurќcksetzen?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Schlieпen"
@@ -596,113 +596,113 @@ msgstr "Taste drќcken, um sie zuzuweisen"
msgid "Choose an action to map"
msgstr "Eine Aktion zum Zuweisen auswфhlen"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~B~eenden"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "ScummVM beenden"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "мbe~r~..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "мber ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~ptionen..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Globale ScummVM-Einstellungen фndern"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~S~tarten"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Ausgewфhltes Spiel starten"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~L~aden..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Spielstand fќr ausgewфhltes Spiel laden"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "Spiel ~h~inzufќgen..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr ""
"Umschalttaste (Shift) gedrќckt halten, um Verzeichnisse nach Spielen zu "
"durchsuchen"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "Spielo~p~tionen..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Spieloptionen фndern"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "Spiel ~e~ntfernen"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Spiel aus der Liste entfernen. Die Spieldateien bleiben erhalten"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~H~inzufќgen..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "Spielo~p~tion"
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~E~ntfernen"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "In Spieleliste suchen"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Suchen:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Spiel laden:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Laden"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -710,64 +710,64 @@ msgstr ""
"Mіchten Sie wirklich den PC nach Spielen durchsuchen? Mіglicherweise wird "
"dabei eine grіпere Menge an Spielen hinzugefќgt."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
"Dieses Verzeichnis kann noch nicht verwendet werden, da noch Dateien "
"heruntergeladen werden!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Mіchten Sie diese Spielkonfiguration wirklich entfernen?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Mіchten Sie einen Spielstand laden?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr ""
"Fќr dieses Spiel wird das Laden aus der Spieleliste heraus nicht unterstќtzt."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
-msgstr "ScummVM konnte keine Engine finden, um das Spiel zu starten!"
+msgstr "ScummVM konnte keine passende Engine fќr dieses Spiel finden!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM konnte im gewфhlten Verzeichnis kein Spiel finden!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Spiel auswфhlen:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Viele hinzufќgen..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Aufzeichnen..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... lфuft ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Suchlauf abgeschlossen!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "%d neue Spiele gefunden, %d bereits hinzugefќgte Spiele ignoriert."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "%d Ordner durchsucht..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "%d neue Spiele gefunden, %d bereits hinzugefќgte Spiele ignoriert..."
@@ -852,7 +852,7 @@ msgstr "Zeiger-Geschw.:"
#: gui/options.cpp:943 gui/options.cpp:945 gui/options.cpp:946
msgid "Speed for keyboard/joystick mouse pointer control"
-msgstr "Zeiger-Geschwindigkeit der Tastatur-/Joystick-Maus"
+msgstr "Zeiger-Geschwindigkeit der Tastatur- bzw. Joystick-Maus"
#: gui/options.cpp:945
msgctxt "lowres"
@@ -900,7 +900,7 @@ msgstr "Render-Modus:"
#: gui/options.cpp:1006 gui/options.cpp:1007
msgid "Special dithering modes supported by some games"
-msgstr "Spezielle Farbmischungsmethoden werden von manchen Spielen unterstќtzt"
+msgstr "Spezielle Dithering-Methoden unterstќtzt von manchen Spielen"
#: gui/options.cpp:1018 backends/graphics/openglsdl/openglsdl-graphics.cpp:588
#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2590
@@ -934,7 +934,7 @@ msgstr "Musikgerфt:"
#: gui/options.cpp:1032 gui/options.cpp:1034
msgid "Specifies preferred sound device or sound card emulator"
msgstr ""
-"Legt das bevorzugte Tonwiedergabe-Gerфt oder den Soundkarten-Emulator fest"
+"Legt das bevorzugte Audio-Wiedergabegerфt oder den Soundkarten-Emulator fest"
#: gui/options.cpp:1032 gui/options.cpp:1034 gui/options.cpp:1035
msgid "Specifies output sound device or sound card emulator"
@@ -1008,8 +1008,8 @@ msgstr "MT-32-Gerфt:"
#: gui/options.cpp:1130
msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
msgstr ""
-"Legt das standardmфпige Tonwiedergabe-Gerфt fќr die Ausgabe von Roland MT-32/"
-"LAPC1/CM32l/CM64 fest"
+"Legt das standardmфпige Audio-Wiedergabegerфt fќr die Ausgabe von Roland "
+"MT-32/LAPC1/CM32l/CM64 fest"
#: gui/options.cpp:1135
msgid "True Roland MT-32 (disable GM emulation)"
@@ -1140,12 +1140,12 @@ msgstr "FluidSynth-Einstellungen"
#: gui/options.cpp:1505
msgid "Theme Path:"
-msgstr "Themen:"
+msgstr "Themes:"
#: gui/options.cpp:1507
msgctxt "lowres"
msgid "Theme Path:"
-msgstr "Themen:"
+msgstr "Themes:"
#: gui/options.cpp:1513 gui/options.cpp:1515 gui/options.cpp:1516
msgid "Specifies path to additional data used by all games or ScummVM"
@@ -1169,7 +1169,7 @@ msgstr "Andere"
#: gui/options.cpp:1537
msgid "Theme:"
-msgstr "Thema:"
+msgstr "Theme:"
#: gui/options.cpp:1541
msgid "GUI Renderer:"
@@ -1244,7 +1244,7 @@ msgstr "Belegter Speicher:"
#: gui/options.cpp:1639
msgid "Space used by ScummVM's saved games on this storage"
msgstr ""
-"Von ScummVM-Spielstфnden beleger Speicherplatz auf diesem Cloud-Speicher"
+"Von ScummVM-Spielstфnden belegter Speicherplatz auf diesem Cloud-Speicher"
#: gui/options.cpp:1642
msgid "Last sync time:"
@@ -1356,7 +1356,7 @@ msgstr ""
#: gui/options.cpp:1944
msgid "Select directory for GUI themes"
-msgstr "Verzeichnis fќr Oberflфchen-Themen"
+msgstr "Verzeichnis fќr Oberflфchen-Themes"
#: gui/options.cpp:1954
msgid "Select directory for extra files"
@@ -1364,7 +1364,7 @@ msgstr "Verzeichnis fќr zusфtzliche Dateien auswфhlen"
#: gui/options.cpp:1965
msgid "Select directory for plugins"
-msgstr "Verzeichnis fќr Erweiterungen auswфhlen"
+msgstr "Verzeichnis fќr Plugins auswфhlen"
#: gui/options.cpp:1977
msgid "Select directory for Files Manager /root/"
@@ -1551,12 +1551,11 @@ msgstr "Rufen Sie folgende URL auf:"
#: gui/storagewizarddialog.cpp:61
msgid "Obtain the code from the storage, enter it"
-msgstr "Geben Sie den Code, den Sie von Ihrem Cloud-Speicher bekommen haben,"
+msgstr "Geben Sie den Code Ihres Cloud-Speichers in das"
#: gui/storagewizarddialog.cpp:62
msgid "in the following field and press 'Connect':"
-msgstr ""
-"geben Sie Ihn in das folgende Feld ein und klicken Sie auf 'Verbinden':"
+msgstr "folgende Feld ein und klicken Sie auf 'Verbinden':"
#: gui/storagewizarddialog.cpp:69
msgid "Open URL"
@@ -1616,33 +1615,62 @@ msgstr ""
#: gui/themebrowser.cpp:45
msgid "Select a Theme"
-msgstr "Thema auswфhlen"
+msgstr "Theme auswфhlen"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "GFX ausgeschaltet"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "GFX ausgeschaltet"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standard-Renderer"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Standard"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Kantenglфttung"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Kantenglфttung"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr "In Zwischenablage kopieren"
+
+#: gui/unknown-game-dialog.cpp:67
+msgid "Report game"
+msgstr "Spiel melden"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+"Verwenden Sie den untenstehenden Button, um die benіtigten Informationen in "
+"die Zwischenablage zu kopieren."
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr "Sie kіnnen das Spiel auch direkt an unseren Bug-Tracker melden."
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr "Alle benіtigten Informationen wurden in die Zwischenablage kopiert"
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr "Kopieren der Spielinformationen in die Zwischenablage fehlgeschlagen!"
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1665,7 +1693,7 @@ msgstr ""
msgid "Proceed"
msgstr "Fortfahren"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Wert lіschen"
@@ -1711,7 +1739,7 @@ msgstr "Spieldateien nicht gefunden"
#: common/error.cpp:42
msgid "Game id not supported"
-msgstr "Spielkennung nicht unterstќtzt"
+msgstr "Spiel-ID nicht unterstќtzt"
#: common/error.cpp:44
msgid "Unsupported color mode"
@@ -1731,7 +1759,7 @@ msgstr "Verzeichnis existiert nicht"
#: common/error.cpp:54
msgid "Path not a directory"
-msgstr "Ungќltiges Verzeichnis"
+msgstr "Pfad ist kein Verzeichnis"
#: common/error.cpp:56
msgid "Path not a file"
@@ -1768,11 +1796,11 @@ msgstr "Unbekannter Fehler"
#. I18N: Hercules is graphics card name
#: common/rendermode.cpp:35
msgid "Hercules Green"
-msgstr "Hercules Grќn"
+msgstr "Hercules-Grќn"
#: common/rendermode.cpp:36
msgid "Hercules Amber"
-msgstr "Hercules Bernstein"
+msgstr "Hercules-Bernstein"
#: common/rendermode.cpp:42
msgid "PC-9821 (256 Colors)"
@@ -1785,48 +1813,29 @@ msgstr "PC-9801 (16 Farben)"
#: common/rendermode.cpp:73
msgctxt "lowres"
msgid "Hercules Green"
-msgstr "Hercules Grќn"
+msgstr "Hercules-Grќn"
#: common/rendermode.cpp:74
msgctxt "lowres"
msgid "Hercules Amber"
-msgstr "Hercules Bernst."
+msgstr "Hercules-Bernst."
#: common/updates.cpp:58
msgid "Daily"
-msgstr "tфglich"
+msgstr "Tфglich"
#: common/updates.cpp:60
msgid "Weekly"
-msgstr "wіchentlich"
+msgstr "Wіchentlich"
#: common/updates.cpp:62
msgid "Monthly"
-msgstr "monatlich"
+msgstr "Monatlich"
#: common/updates.cpp:64
msgid "<Bad value>"
msgstr "<Fehlerhafter Wert>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Das Spiel in '%s' ist offenbar eine unbekannte Variante eines Spiels, dass "
-"die %s-Engine verwendet.\n"
-"\n"
-"Bitte teilen Sie dem ScummVM-Team unter %s die folgenden Informationen "
-"zusammen mit dem Namen, der Version und der Sprache des Spiels, welches Sie "
-"hinzufuegen moechten, mit:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Uebereinstimmende Spiele-Kennungen:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~F~ortsetzen"
@@ -1862,12 +1871,12 @@ msgstr "Zur Spiele~l~iste"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1882,12 +1891,12 @@ msgstr "Speichern:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1904,7 +1913,7 @@ msgid ""
"the README for basic information, and for instructions on how to obtain "
"further assistance."
msgstr ""
-"Leider bietet diese Engine keine Spielhilfe. Bitte lesen Sie die Liesmich-"
+"Leider bietet diese Engine keine Spielhilfe. Bitte lesen Sie die LIESMICH-"
"Datei fќr grundlegende Informationen und Anweisungen zu weiterer Hilfe."
#: engines/dialogs.cpp:234 engines/pegasus/pegasus.cpp:395
@@ -2005,22 +2014,50 @@ msgstr ""
msgid "Start anyway"
msgstr "Trotzdem starten"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Das Spiel in '%s' ist offenbar eine unbekannte Variante eines Spiels, dass "
+"die %s-Engine verwendet.\n"
+"\n"
+"Bitte teilen Sie dem ScummVM-Team unter %s die folgenden Informationen "
+"zusammen mit dem Namen, der Version und der Sprache des Spiels, welches Sie "
+"hinzufќgen mіchten, mit:"
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "мbereinstimmende Spiele-IDs fќr die Engine %s:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "AdLib-Emulator"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
-msgstr "MAME-OPL-Emulator"
+msgstr "MAME OPL-Emulator"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
-msgstr "DOSBox-OPL-Emulator"
+msgstr "DOSBox OPL-Emulator"
+
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL-Emulator"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2072,11 +2109,11 @@ msgstr "Keine Musik"
#: audio/softsynth/appleiigs.cpp:33
msgid "Apple II GS Emulator (NOT IMPLEMENTED)"
-msgstr "Apple-II-GS-Emulator (NICHT INTEGRIERT)"
+msgstr "Apple II GS-Emulator (NICHT INTEGRIERT)"
#: audio/softsynth/cms.cpp:350
msgid "Creative Music System Emulator"
-msgstr "Creative-Music-System-Emulator"
+msgstr "Creative Music System-Emulator"
#: audio/softsynth/fmtowns_pc98/towns_pc98_plugins.cpp:33
msgid "FM-Towns Audio"
@@ -2092,7 +2129,7 @@ msgstr "Initialisiere MT-32-Emulator"
#: audio/softsynth/mt32.cpp:437
msgid "MT-32 Emulator"
-msgstr "MT-32-Emulation"
+msgstr "MT-32-Emulator"
#: audio/softsynth/pcspk.cpp:139
msgid "PC Speaker Emulator"
@@ -2100,7 +2137,7 @@ msgstr "PC-Lautsprecher-Emulator"
#: audio/softsynth/pcspk.cpp:158
msgid "IBM PCjr Emulator"
-msgstr "IBM-PCjr-Emulator"
+msgstr "IBM PCjr-Emulator"
#: audio/softsynth/sid.cpp:1430
msgid "C64 Audio Emulator"
@@ -2164,19 +2201,19 @@ msgstr "Beenden"
#: backends/events/gph/gph-events.cpp:434
#: backends/events/openpandora/op-events.cpp:174
msgid "Touchscreen 'Tap Mode' - Left Click"
-msgstr "Berќhrungsbildschirm-Tipp-Modus - Linksklick"
+msgstr "Touchscreen-Tipp-Modus - Linksklick"
#: backends/events/gph/gph-events.cpp:393
#: backends/events/gph/gph-events.cpp:436
#: backends/events/openpandora/op-events.cpp:176
msgid "Touchscreen 'Tap Mode' - Right Click"
-msgstr "Berќhrungsbildschirm-Tipp-Modus - Rechtsklick"
+msgstr "Touchscreen-Tipp-Modus - Rechtsklick"
#: backends/events/gph/gph-events.cpp:395
#: backends/events/gph/gph-events.cpp:438
#: backends/events/openpandora/op-events.cpp:178
msgid "Touchscreen 'Tap Mode' - Hover (No Click)"
-msgstr "Berќhrungsbildschirm-Tipp-Modus - schweben (kein Klick)"
+msgstr "Touchscreen-Tipp-Modus - schweben (kein Klick)"
#: backends/events/gph/gph-events.cpp:415
msgid "Maximum Volume"
@@ -2204,7 +2241,7 @@ msgstr "Klicken deaktiviert"
#: backends/events/openpandora/op-events.cpp:180
msgid "Touchscreen 'Tap Mode' - Hover (DPad Clicks)"
-msgstr "Berќhrungsbildschirm-Tipp-Modus - schweben (DPad-Klicks)"
+msgstr "Touchscreen-Tipp-Modus - schweben (DPad-Klicks)"
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
msgid "Do you want to quit ?"
@@ -2388,7 +2425,7 @@ msgstr "Helligkeit:"
#: backends/platform/ds/arm9/source/dsoptions.cpp:121
msgid "High quality audio (slower) (reboot)"
-msgstr "Hohe Audioqualitфt (lansamer) (erfordert Neustart)"
+msgstr "Hohe Audioqualitфt (langsamer) (erfordert Neustart)"
#: backends/platform/ds/arm9/source/dsoptions.cpp:122
msgid "Disable power off"
@@ -2815,7 +2852,7 @@ msgstr "Suche nach Aktualisierungen..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2823,7 +2860,7 @@ msgstr "Engine-Datendatei '%s' kann nicht gefunden werden."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2869,6 +2906,7 @@ msgstr "Originale Spielstand-Menќs"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"Verwende die originalen Speicher- und Lade-Menќs statt der Menќs von ScummVM"
@@ -2915,13 +2953,13 @@ msgid ""
"Shows a command prompt window and pauses the game (like in SCI) instead of a "
"real-time prompt."
msgstr ""
-"Zeige eine Fenster mit einer Kommandozeile und pausiere das Spiel (wie in "
+"Zeige ein Fenster mit einer Kommandozeile und pausiere das Spiel (wie in "
"SCI) anstelle einer Eingabe in Echtzeit."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2933,9 +2971,9 @@ msgid "Restore game:"
msgstr "Spiel laden:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2946,7 +2984,7 @@ msgstr "Spiel laden:"
msgid "Restore"
msgstr "Laden"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2968,7 +3006,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2984,11 +3022,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Zwischensequenz \"%s\" nicht gefunden!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Modus fќr Farbenblinde"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Modus fќr Farbenblinde standardmфпig einschalten"
@@ -3216,10 +3254,10 @@ msgid ""
"General MIDI ones. It is still possible that\n"
"some tracks sound incorrect."
msgstr ""
-"Sie scheinen ein General-MIDI-Gerфt zu\n"
+"Sie scheinen ein General MIDI-Gerфt zu\n"
"verwenden, aber das Spiel unterstќtzt nur\n"
"Roland MT32 MIDI. Es wird versucht, die\n"
-"Roland-MT32-Instrumente denen von\n"
+"Roland MT32-Instrumente denen von\n"
"General MIDI zuzuordnen. Es ist dennoch\n"
"mіglich, dass ein paar Musikstќcke nicht\n"
"richtig abgespielt werden."
@@ -3286,20 +3324,20 @@ msgstr "Animierte Spieloberflфche"
#: engines/mads/detection.cpp:121 engines/mads/detection.cpp:122
msgid "Naughty game mode"
-msgstr "Unanstфndiger Spiel-Modus"
+msgstr "Unanstфndiger Spielmodus"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Video vom Anflug auf Myst abspielen"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
"Das Video, welches den Anflug auf Myst zeigt, wurde in der ursprќnglichen "
"Engine nicht abgespielt."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~ip-Modus aktiviert"
@@ -3320,27 +3358,27 @@ msgstr "~K~arte anzeigen"
msgid "Main Men~u~"
msgstr "Haupt~m~enќ"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~W~assereffekt aktiviert"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "мbergфnge:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Ausgeschaltet"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Schnellste"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Beste"
@@ -3348,7 +3386,7 @@ msgstr "Beste"
msgid "The game is paused. Press any key to continue."
msgstr "Das Spiel ist pausiert. Zum Weiterspielen beliebige Taste drќcken."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3356,7 +3394,7 @@ msgstr ""
"Ihnen fehlt eine Programmdatei von Riven. Die Windows-Programmdatei ist "
"'riven.exe' oder 'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3364,7 +3402,7 @@ msgstr ""
"Die Installationsdatei 'arcriven.z' kann ebenfalls verwendet werden. "
"Zusфtzlich kіnnen Sie auch die Mac-Programmdatei 'Riven' verwenden."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3372,7 +3410,7 @@ msgstr ""
"Die Datei 'extras.mhk' fehlt. Sie kіnnen auch die Installationsdatei "
"'arcriven.z verwenden."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "Ihnen fehlen die folgenden Spieldateien fќr Riven:\n"
@@ -3423,7 +3461,7 @@ msgid ""
"Can't save game in slot %i\n"
"\n"
msgstr ""
-"Kann Spiel nicht speichern auf Speicherplatz %i\n"
+"Kann Spiel nicht auf Speicherplatz %i speichern\n"
"\n"
#: engines/parallaction/saveload.cpp:194
@@ -3560,7 +3598,7 @@ msgstr "Digitale Gerфusch-Effekte bevorzugen"
#: engines/sci/detection.cpp:443
msgid "Prefer digital sound effects instead of synthesized ones"
-msgstr "Bevorzugt digitale Gerфusch-Effekte statt synthethisierter"
+msgstr "Bevorzugt digitale Gerфusch-Effekte statt synthetisierter"
#: engines/sci/detection.cpp:462
msgid "Use IMF/Yamaha FB-01 for MIDI output"
@@ -3571,7 +3609,7 @@ msgid ""
"Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI "
"output"
msgstr ""
-"Verwendet eine Music-Feature-Karte von IBM oder ein Yamaha-FB-01-FM-"
+"Verwendet eine Music Feature-Karte von IBM oder ein Yamaha FB-01 FM-"
"Synthetisierungsmodul fќr die MIDI-Ausgabe"
#: engines/sci/detection.cpp:473
@@ -3731,7 +3769,7 @@ msgstr ""
"Verzeichnis entfernen sollten, um unerwartete Fehler und/oder Probleme zu "
"verhindern."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3740,11 +3778,11 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
"Ihre Spiel-Version ist offenbar unbekannt. Wenn es sich *NICHT* um eine\n"
-"von Fans modifizierte Version (z.B. eine Fan-Uebersetzung) handelt, teilen\n"
+"von Fans modifizierte Version (z.B. eine Fan-мbersetzung) handelt, teilen\n"
"Sie bitte dem ScummVM-Team die folgenden Daten sowie den Namen des Spiels,\n"
-"welches Sie hinzufuegen wollten, dessen Version, Sprache usw. mit:\n"
+"welches Sie hinzufќgen wollten, dessen Version, Sprache usw. mit:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3755,11 +3793,11 @@ msgstr ""
"um Software-Piraterie zu verhindern. Die Vollversion ist im iTunes Store "
"erhфltlich."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Objektzeile zeigen"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Objektnamen und Verben am unteren Bildrand anzeigen"
@@ -3808,7 +3846,7 @@ msgstr "Sie mќssen eine Bezeichnung eingeben"
#: engines/scumm/dialogs.cpp:192
msgid "The game was NOT saved (disk full?)"
-msgstr "Spiel wurde NICHT gespeichert. (Datentrфger voll?)"
+msgstr "Spiel wurde NICHT gespeichert (Datentrфger voll?)"
#: engines/scumm/dialogs.cpp:193
msgid "The game was NOT loaded"
@@ -3869,7 +3907,7 @@ msgstr "Wфhle einen Schwierigkeitsgrad."
#: engines/scumm/dialogs.cpp:657
msgid "Refer to your Loom(TM) manual for help."
-msgstr "Fќr Hilfe schauen Sie ins Loom-Handbuch."
+msgstr "Fќr Hilfe schauen Sie ins Loom(TM)-Handbuch."
#: engines/scumm/dialogs.cpp:661
msgid "Practice"
@@ -4150,7 +4188,7 @@ msgstr "spiele A auf Stab"
#: engines/scumm/help.cpp:186
msgid "play B on distaff"
-msgstr "spiele B auf Stab"
+msgstr "spiele H auf Stab"
#: engines/scumm/help.cpp:187
msgid "play C major on distaff"
@@ -4438,7 +4476,7 @@ msgstr ""
"Roland-Upgrade von LucasArts, aber %s\n"
"fehlt. Stattdessen wird AdLib verwendet."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4475,14 +4513,14 @@ 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"
+msgstr "Bei Mausbewegung keine Hotspots 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"
+"Zeigt Hotspot-Namen nur nach Klick auf selbigen oder auf einen Aktionspunkt"
#: engines/sherlock/detection.cpp:101
msgid "Show character portraits"
@@ -4514,13 +4552,13 @@ msgstr "Die Engine-Datendatei \"sky.cpt\" hat eine falsche Grіпe."
#: engines/sky/detection.cpp:44
msgid "Floppy intro"
-msgstr "Disketten-Vorspann"
+msgstr "Vorspann der Diskettenversion"
#: engines/sky/detection.cpp:45
msgid "Use the floppy version's intro (CD version only)"
msgstr "Verwendet den Vorspann der Diskettenversion (nur bei CD-Version)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4528,7 +4566,7 @@ msgstr ""
"Falsche Version der Engine-Datendatei '%s' gefunden. %d erwartet, aber %d "
"bekommen."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4657,27 +4695,44 @@ msgstr "Spielstand #%d geladen"
msgid "Could not quick load the saved game #%d"
msgstr "Schnellladen des Spielstandes #%d nicht mіglich"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
-msgstr "Zфhler fќr Bilder pro Sekunde anzeigen"
+msgstr "FPS-Zфhler anzeigen"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
"Zeige die aktuelle Anzahl von Bildern pro Sekunde in der oberen linken Ecke"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Bilineare Filterung fќr Sprites (LANGSAM)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Bilineare Filterung auf einzelne Sprites anwenden"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr "Item-Kosten im Standard-Inventarmodus anzeigen"
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+"Zeigt die Gegenstandskosten im Standard-Inventarmodus an, um einen Vergleich "
+"der Gegenstфnde zu ermіglichen"
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr "Widerstandsfфhigere Rќstung"
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Verwendet die originalen Menќs zum Speichern und Laden statt der von ScummVM"
+"Rќstung zerbricht erst, wenn der Charakter -80HP besitzt und nicht bereits "
+"bei -10HP"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4713,7 +4768,7 @@ msgstr ""
"Verwende die hochauflіsendenden MPEG-Filme der DVD-Version anstelle der "
"niedriger aufgelіsten AVI-Filme"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4723,6 +4778,11 @@ msgstr ""
"Spielstфnde bis zu Version %d. Sie benіtigen eine aktualisierte Version der "
"Engine, um diesen Spielstand zu verwenden."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Verwendet die originalen Menќs zum Speichern und Laden statt der von "
+#~ "ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr ""
#~ "(Sie kіnnen diese auch jederzeit im Options-Dialog unter dem Reiter "
diff --git a/po/el.po b/po/el.po
index 723b3aebdb..b72e9a827e 100644
--- a/po/el.po
+++ b/po/el.po
@@ -6,9 +6,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.10.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-04-28 11:12+0000\n"
-"Last-Translator: Arius <alidop@pathfinder.gr>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:19+0000\n"
+"Last-Translator: Adrian Fruehwirth <bonki@scummvm.org>\n"
"Language-Team: Greek <https://translations.scummvm.org/projects/scummvm/"
"scummvm/el/>\n"
"Language: el\n"
@@ -56,7 +56,7 @@ msgstr "Ьхємтсѓч №мэљ"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -80,7 +80,7 @@ msgstr "Х№щыяуо"
msgid "Select directory where to download game data"
msgstr "Х№щынюєх імъхыя ущс эс ьхєсіяёєўѓхєх єс фхфяьнэс №сщїэщфщўэ"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Х№щынюєх імъхыя ьх фхфяьнэс №сщїэщфщя§"
@@ -115,7 +115,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -128,7 +128,7 @@ msgstr "Эсщ"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -139,7 +139,7 @@ msgstr "Эсщ"
msgid "No"
msgstr "Мїщ"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "дя ScummVM фх ь№ќёхѓх эс сэяпюхщ єя ъсшяёщѓьнэя імъхыя!"
@@ -152,8 +152,8 @@ msgstr ""
"імъхыяђ нїхщ нэс сёїхпя ьх єя пфщя ќэяьс."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -168,7 +168,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -545,10 +545,10 @@ msgstr ""
"Шныхєх №ёсуьсєщъм эс х№сэсінёхєх ќыхђ єщђ ёѕшьпѓхщђ єяѕ FluidSynth ѓєщђ "
"№ёяъсшяёщѓьнэхђ єяѕђ єщьнђ;"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Ъыхпѓщья"
@@ -597,113 +597,113 @@ msgstr "асєоѓєх єя №ыоъєёя ущс ѓѕѓїнєщѓч"
msgid "Choose an action to map"
msgstr "Х№щынюєх ьщс хэнёухщс ущс сэєщѓєяпїщѓч"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "И~ю~яфяђ"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Июяфяђ с№ќ єя ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "~а~хёп..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "ахёп єяѕ ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~Х~№щыяунђ..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Сыысуо ъсшяыщъўэ х№щыяуўэ єяѕ ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "Х~ъ~ъпэчѓч"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Хъъпэчѓч х№щыхуьнэяѕ №сщїэщфщя§"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~ж~ќёєљѓч..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "жќёєљѓч с№яшчъхѕьнэяѕ №сщїэщфщя§ ущс єя х№щыхуьнэя №сщїэпфщ"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~а~ёяѓшоъч асщїэщфщя§..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Ъёсєоѓєх №сєчьнэя єя Shift ущс Ьсцщъо аёяѓшоъч"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~Ф~щќёшљѓч асщїэщфщя§..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Сыысуо х№щыяуўэ №сщїэщфщя§"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~С~іспёхѓч асщїэщфщя§"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr ""
"Сіспёхѓч №сщїэщфщя§ с№ќ єч ыпѓєс. дс сёїхпс фхфяьнэљэ єяѕ №сщїэщфщя§ ьнэяѕэ "
"сэн№сіс"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~а~ёяѓш. асщїэ..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~Ф~щќёш. асщїэ..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~С~іспё. асщїэ"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Сэсцоєчѓч ѓєч ыпѓєс №сщїэщфщўэ"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Сэсцоєчѓч:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "жќёєљѓч №сщїэщфщя§:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "жќёєљѓч"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -711,68 +711,68 @@ msgstr ""
"Шныхєх №ёсуьсєщъм эс єёнюхєх єяэ ьсцщъќ сэщїэхѕєо №сщїэщфщўэ; Сѕєќ шс "
"ь№яёя§ѓх хэфхїяьнэљђ эс №ёяѓшнѓхщ нэс єхёмѓєщя сёщшьќ №сщїэщфщўэ."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
"Сѕєќђ я імъхыяђ фх ь№яёхп эс їёчѓщья№ящчшхп съќьч, упэхєсщ ьхєсіќёєљѓч ѓх "
"сѕєќэ!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Шныхєх №ёсуьсєщъм эс ѓтоѓхєх єщђ ёѕшьпѓхщђ сѕєя§ єяѕ №сщїэщфщя§;"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Шныхєх эс іяёєўѓхєх єя с№яшчъхѕьнэя №сщїэпфщ;"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Сѕєќ єя №сщїэпфщ фхэ ѕ№яѓєчёпцхщ іќёєљѓч №сщїэщфщўэ с№ќ єяэ №ёяљшчєо."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"дя ScummVM фх ь№ќёхѓх эс тёхп ъм№ящс ьчїсэо щъсэо эс хъєхынѓхщ єя х№щыхуьнэя "
"№сщїэпфщ!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr ""
"дя ScummVM фх ь№ќёхѓх эс тёхп ъм№ящя №сщїэпфщ ѓєяэ №ёяъсшяёщѓьнэя імъхыя!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Фщсынюєх єя №сщїэпфщ:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Ьсцщъо аёяѓшоъч..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Хууёсіо..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... №ёќяфяђ ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Ч ѓмёљѓч яыяъычёўшчъх!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr ""
"Сэсъсы§ішчъсэ %d энс №сщїэпфщс, суэяошчъсэ %d №сщїэпфщс №яѕ нїяѕэ офч "
"№ёяѓєхшхп."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "гсёўшчъсэ %d імъхыящ ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1621,31 +1621,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Х№щынюєх шньс"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "С№хэхёуя№ящчьнэс уёсіщъм"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "С№хэхёу. уёсіщъм"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Ъсэяэщъо С№хщъќэщѓч"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Ъсэяэщъќ"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Хюяьсыѕьнэч С№ќфяѓч"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Хюяьсыѕьнэч"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Х№сэсіяём №сщїэщфщя§:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
#, fuzzy
msgid ""
@@ -1668,7 +1696,7 @@ msgstr ""
msgid "Proceed"
msgstr "аёяїўёс"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "гтоѓщья єщьођ"
@@ -1813,24 +1841,6 @@ msgstr "Ьчэщспс"
msgid "<Bad value>"
msgstr "<Хѓісыьнэч єщьо>"
-#: engines/advancedDetector.cpp:330
-#, fuzzy, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"дя №сщїэпфщ ѓєя '%s' іспэхєсщ эс хпэсщ муэљѓєя.\n"
-"асёсъсыя§ьх, сэсінёхєх єс съќыяѕшс ѓєящїхпс ѓєчэ яьмфс ScummVM ьсцп ьх єя "
-"ќэяьс\n"
-"єяѕ №сщїэщфщя§ №яѕ №ёяѓ№сшоѓсєх эс №ёяѓшнѓхєх ъсщ єчэ нъфяѓч, єч уыўѓѓс єяѕ, "
-"ъы№.:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~г~ѕэнїхщс"
@@ -1866,12 +1876,12 @@ msgstr "Х№щѓ~є~ё. ѓєяэ Яфчучєо"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1886,12 +1896,12 @@ msgstr "С№яшоъхѕѓч №сщїэщфщя§:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -2010,22 +2020,49 @@ msgstr ""
msgid "Start anyway"
msgstr "Хъъпэчѓч я§єљђ о мыыљђ"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"дя №сщїэпфщ ѓєя '%s' іспэхєсщ эс хпэсщ муэљѓєя.\n"
+"асёсъсыя§ьх, сэсінёхєх єс съќыяѕшс ѓєящїхпс ѓєчэ яьмфс ScummVM ьсцп ьх єя "
+"ќэяьс\n"
+"єяѕ №сщїэщфщя§ №яѕ №ёяѓ№сшоѓсєх эс №ёяѓшнѓхєх ъсщ єчэ нъфяѓч, єч уыўѓѓс єяѕ, "
+"ъы№.:"
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Хюяьящљєођ Adlib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Хюяьящљєођ MAME OPL"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Хюяьящљєођ DOSBox OPL"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Хюяьящљєођ Nuked OPL"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2820,7 +2857,7 @@ msgstr "Иыхуїяђ Хэчьхёўѓхљэ..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2828,7 +2865,7 @@ msgstr "Фхэ оєсэ фѕэсєо ч х§ёхѓч єяѕ сёїхпяѕ №сщїэщфщя§ '%s'."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2874,6 +2911,7 @@ msgstr "зёоѓч сёїщъўэ яшяэўэ с№яшоъхѕѓчђ/іќёєљѓчђ"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"зёоѓч єљэ сёїщъўэ яшяэўэ с№яшоъхѕѓчђ/іќёєљѓчђ сэєп ущс сѕєнђ єяѕ ScummVM"
@@ -2924,9 +2962,9 @@ msgstr ""
"SCI) сэєп єчђ уёсььођ хэєяыўэ №ёсуьсєщъя§ їёќэяѕ."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2938,9 +2976,9 @@ msgid "Restore game:"
msgstr "Х№сэсіяём №сщїэщфщя§:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2951,7 +2989,7 @@ msgstr "Х№сэсіяём №сщїэщфщя§:"
msgid "Restore"
msgstr "Х№сэсіяём"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2973,7 +3011,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2989,11 +3027,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Фхэ тёншчъх єя сёїхпя хэфщмьхѓчђ ѓъчэођ (cutscene) '%s' !"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Ыхщєяѕёупс ущс Жєяьс ьх Сїёљьсєяјпс"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Хэхёуя№япчѓч ыхщєяѕёупсђ ущс Жєяьс ьх Сїёљьсєяјпс хю'яёщѓья§"
@@ -3292,18 +3330,18 @@ msgstr "Ъщэя§ьхэч фщх№сіо №сщїэщфщя§"
msgid "Naughty game mode"
msgstr "Ыхщєяѕёупс №сщїэщфщя§ ущс мєсъєяѕђ"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Сэс№сёсуљуо єчђ єсщэпсђ хэснёщсђ х№щѓъќ№чѓчђ єяѕ Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
"Ч єсщэпс хэснёщсђ х№щѓъќ№чѓчђ єяѕ Myst фхэ сэс№сёмїшчъх с№ќ єчэ №ёљєќєѕ№ч "
"ьчїсэо."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "Ыхщєяѕёупс ~Z~ip Хэхёуя№ящчьнэч"
@@ -3324,30 +3362,30 @@ msgstr "Хьімэщѓч ~з~мёєч"
msgid "Main Men~u~"
msgstr "Ъхэєёщъќ Ьхэя~§~"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "Хін ~Э~хёя§ Хэхёуя№ящчьнэя"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
#, fuzzy
msgid "Transitions:"
msgstr "~Ь~хєстмѓхщђ Хэхёуя№ящчьнэхђ"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
#, fuzzy
msgid "Disabled"
msgstr "С№хэхёуя№ящчьнэс уёсіщъм"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
#, fuzzy
msgid "Fastest"
msgstr "Х№щъќыычѓч"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr ""
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3356,7 +3394,7 @@ msgid "The game is paused. Press any key to continue."
msgstr ""
"дя №сщїэпфщ тёпѓъхєсщ ѓх №с§ѓч. асєоѓєх я№ящяфо№яєх ъяѕь№п ущс эс ѓѕэхїпѓхєх."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3364,7 +3402,7 @@ msgstr ""
"Ыхп№хщ єя хъєхынѓщья єяѕ Riven. дя хъєхынѓщья ущс Windows хпэсщ 'riven.exe' "
"о 'rivendemo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3372,7 +3410,7 @@ msgstr ""
"Ч їёоѓч єяѕ сёїхпяѕ хуъсємѓєсѓчђ 'arcriven.z' ыхщєяѕёухп х№пѓчђ. Х№щ№ыняэ, "
"ь№яёхпєх эс їёчѓщья№ящоѓхєх єя хъєхынѓщья єяѕ Mac 'Riven'."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3380,7 +3418,7 @@ msgstr ""
"гсђ ыхп№хщ єя 'extras.mhk'. Ч їёоѓч єяѕ сёїхпяѕ хуъсємѓєсѓчђ 'arcriven.z' "
"ыхщєяѕёухп х№пѓчђ."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3700,7 +3738,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3716,7 +3754,7 @@ msgstr ""
"№ёяѓ№сшоѓсєх\n"
"эс №ёяѓшнѓхєх ъсщ єчэ нъфяѓо єяѕ, єч уыўѓѓс єяѕ, ъы№.:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3726,11 +3764,11 @@ msgstr ""
"с№яіѕуо №хщёсєхпсђ.\n"
"Ч №ыоёчђ нъфяѓч хпэсщ фщсшнѓщьч ущс суяём с№ќ єя Ъсємѓєчьс iTunes."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "аёятяыо Уёсььођ Сэєщъхщьнэљэ"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "асёяѕѓпсѓч єљэ яэяьмєљэ єљэ сэєщъхщьнэљэ ѓєя ъмєљ ьнёяђ єчђ яшќэчђ"
@@ -4408,7 +4446,7 @@ msgstr ""
"Ч ѕ№яѓєоёщюч native MIDI с№сщєхп єчэ Сэстмшьщѓч Roland с№ќ єч LucasArts,\n"
"сыым єя %s ыхп№хщ. Упэхєсщ їёоѓч AdLib сэє 'сѕєя§."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4491,7 +4529,7 @@ msgstr "Хщѓсуљуо нъфяѓчђ фщѓънєсђ"
msgid "Use the floppy version's intro (CD version only)"
msgstr "зёоѓч єчђ хщѓсуљуођ с№ќ єчэ нъфяѓч фщѓънєсђ (нъфяѓч CD ьќэя)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, fuzzy, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4499,7 +4537,7 @@ msgstr ""
"Тёншчъх ысэшсѓьнэч нъфяѓч єяѕ '%s' сёїхпяѕ №сщїэщфщя§. Сэсьхэќьхэч %d.%d "
"сыым тёншчъх ч %d.%d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, fuzzy, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr "Фхэ оєсэ фѕэсєо ч х§ёхѓч єяѕ сёїхпяѕ №сщїэщфщя§ '%s'."
@@ -4626,28 +4664,41 @@ msgstr "дя с№яшчъхѕьнэч №сщїэпфщ #%d іяёєўшчъх уёоуяёс"
msgid "Could not quick load the saved game #%d"
msgstr "Фхэ оєсэ фѕэсєо ч уёоуяёч іќёєљѓч єяѕ с№яшчъхѕьнэяѕ №сщїэщфщя§ #%d"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "аёятяыо ьхєёчєо FPS"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
"Хьімэщѓч єяѕ єёнїяэєяђ сёщшья§ ъсён сэм фхѕєхёќых№єя ѓєчэ х№мэљ сёщѓєхёо "
"уљэпс"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Фщуёсььщъќ іщыєёмёщѓьс ѓєящїхпљэ (СбУЯ)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Хісёьяуо фщуёсььщъя§ іщыєёсёпѓьсєяђ ѓх ьхьяэљьнэс ѓєящїхпс"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"зёчѓщья№ящоѓєх єщђ сёїщънђ яшќэхђ с№яшоъхѕѓчђ/іќёєљѓчђ сэєп сѕєўэ єяѕ ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4682,7 +4733,7 @@ msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr ""
"зёоѓч тпэєхя MPEG с№ќ єчэ нъфяѓч DVD сэєп ущс єя їсьчыќєхёчђ сэмыѕѓчђ AVI"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4692,6 +4743,11 @@ msgstr ""
"ѕ№яѓєчёпцхщ ьќэя ьнїёщ єчэ нъфяѓч%d. Шс їёхщсѓєхпєх ьщс хэчьхёљьнэч нъфяѓч "
"єчђ ьчїсэођ ущс эс їёчѓщья№ящоѓхєх сѕєќ єя с№яшчъхѕьнэя №сщїэпфщ."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "зёчѓщья№ящоѓєх єщђ сёїщънђ яшќэхђ с№яшоъхѕѓчђ/іќёєљѓчђ сэєп сѕєўэ єяѕ "
+#~ "ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr ""
#~ "(Ь№яёхпєх №мэєс эс єчэ хэхёуя№ящоѓхєх ѓєя №сёмшѕёя фщсыќуяѕ Х№щыяунђ ѓєчэ "
diff --git a/po/es_ES.po b/po/es_ES.po
index cdfa1e0523..d874115379 100644
--- a/po/es_ES.po
+++ b/po/es_ES.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.4.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-12-01 22:51+0000\n"
-"Last-Translator: TomasM <truido@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:10+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Spanish <https://translations.scummvm.org/projects/scummvm/"
"scummvm/es/>\n"
"Language: es_ES\n"
@@ -57,7 +57,7 @@ msgstr "Arriba"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Aceptar"
msgid "Select directory where to download game data"
msgstr "Selecciona el directorio donde descargar los archivos de juego"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Selecciona el directorio con los datos del juego"
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Sэ"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Sэ"
msgid "No"
msgstr "No"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ЁScummVM no ha podido abrir el directorio!"
@@ -153,8 +153,8 @@ msgstr ""
"un archivo con el mismo nombre."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -169,7 +169,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "Aceptar"
@@ -540,10 +540,10 @@ msgstr ""
"ПSeguro que quieres volver a los valores por defecto de las opciones de "
"FluidSynth?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Cerrar"
@@ -592,111 +592,111 @@ msgstr "Pulsa una tecla para asignarla"
msgid "Choose an action to map"
msgstr "Elige una acciѓn para asociarla"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~S~alir"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Salir de ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "Acerca ~d~e..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Acerca de ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~pciones..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Cambiar opciones generales de ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~J~ugar"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Jugar al juego seleccionado"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~C~argar..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Cargar partida del juego seleccionado"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~A~ёadir juego..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Mantщn pulsado Mayњs para aёadir varios juegos"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~E~ditar juego..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Cambiar opciones de juego"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "E~l~iminar juego"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Eliminar el juego de la lista. Los archivos no se borran"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~A~ёadir..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~E~ditar..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "E~l~iminar"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Buscar en la lista de juegos"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Buscar:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Cargar juego:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Cargar"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -704,64 +704,64 @@ msgstr ""
"ПSeguro que quieres ejecutar la detecciѓn masiva? Puede que se aёada un gran "
"nњmero de juegos."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
"ЁEste directorio se estс utilizando para una descarga y todavэa no puede "
"usarse!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "ПSeguro que quieres eliminar la configuraciѓn de este juego?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "ПQuieres cargar la partida guardada?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Este juego no permite cargar partidas desde el lanzador."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ЁScummVM no ha podido encontrar ningњn motor capaz de ejecutar el juego!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ЁScummVM no ha encontrado ningњn juego en el directorio!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Elige el juego:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Aёadir varios..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Grabar..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... progreso..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "ЁBњsqueda completada!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "%d juegos nuevos encontrados. %d juegos ignorados (ya aёadidos)."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Se ha buscado en %d directorios..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1332,7 +1332,7 @@ msgstr "ЁEl Tema no soporta el lenguaje seleccionado!"
#: gui/options.cpp:1896
msgid "Theme cannot be loaded!"
-msgstr "No se ha podido cargar el tema."
+msgstr "ЁNo se ha podido cargar el tema!"
#: gui/options.cpp:1899
msgid ""
@@ -1606,31 +1606,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Selecciona un tema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Grсf. desactivados"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Grсf. desactivados"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Estсndar"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Estсndar"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Suavizado"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Suavizado"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Cargar partida:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1653,7 +1681,7 @@ msgstr ""
msgid "Proceed"
msgstr "Aplicar"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Eliminar valor"
@@ -1796,24 +1824,6 @@ msgstr "Mensualmente"
msgid "<Bad value>"
msgstr "<Valor incorrecto>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Parece que el juego que se encuentra en '%s' utiliza una versiѓn desconocida "
-"del motor %s.\n"
-"\n"
-"Por favor, envэa la siguiente informaciѓn al equipo de ScummVM en %s, junto "
-"al nombre del juego, su versiѓn, el idioma, etcщtera:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Juegos disponibles:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~R~eanudar"
@@ -1849,12 +1859,12 @@ msgstr "~V~olver al lanzador"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1869,12 +1879,12 @@ msgstr "Guardar partida:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1989,22 +1999,49 @@ msgstr ""
msgid "Start anyway"
msgstr "Jugar aun asэ"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Parece que el juego que se encuentra en '%s' utiliza una versiѓn desconocida "
+"del motor %s.\n"
+"\n"
+"Por favor, envэa la siguiente informaciѓn al equipo de ScummVM en %s, junto "
+"al nombre del juego, su versiѓn, el idioma, etcщtera:"
+
+#: engines/game.cpp:162
+#, fuzzy, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Juegos disponibles:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Emulador de AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Emulador OPL de MAME"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Emulador OPL de DOSBox"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Emulador OPL de Nuked"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2798,7 +2835,7 @@ msgstr "Buscar actualizaciones..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2806,7 +2843,7 @@ msgstr "No se puede localizar el archivo de datos del motor '%s'."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2852,6 +2889,7 @@ msgstr "Usar pantallas de guardar/cargar originales"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr "Usar los menњs originales de guardar/cargar en vez de los de ScummVM"
@@ -2899,9 +2937,9 @@ msgstr ""
"en vez de una ventana en tiempo real."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2913,9 +2951,9 @@ msgid "Restore game:"
msgstr "Cargar partida:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2926,7 +2964,7 @@ msgstr "Cargar partida:"
msgid "Restore"
msgstr "Cargar"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2947,7 +2985,7 @@ msgstr ""
"Fallo al guardar la partida al archivo:\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2963,11 +3001,11 @@ msgstr ""
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
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Modo para daltѓnicos"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Activar por defecto el modo para daltѓnicos"
@@ -3261,17 +3299,17 @@ msgstr "Interfaz de juego animada"
msgid "Naughty game mode"
msgstr "Modo de juego picante"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Reproducir el vuelo de reconocimiento de Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
"El vuelo de reconocimiento de Myst no se mostraba en el motor original."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "Modo ~Z~ip activado"
@@ -3292,27 +3330,27 @@ msgstr "~M~ostrar el mapa"
msgid "Main Men~u~"
msgstr "Menњ ~p~rincipal"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "Efecto ag~u~a activado"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Transiciones:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Desactivado"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Rсpido"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Mejor"
@@ -3320,7 +3358,7 @@ msgstr "Mejor"
msgid "The game is paused. Press any key to continue."
msgstr "Juego pausado. Pulsa cualquier tecla para continuar."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3328,7 +3366,7 @@ msgstr ""
"El ejecutable de Riven no ha sido encontrado. El ejecutable de Windows es "
"'riven.exe' o 'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3336,7 +3374,7 @@ msgstr ""
"Usar el archivo de instalacion 'arcriven.z' es funcional. Tambien puedes "
"utilizar el ejecutable de Mac."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3344,7 +3382,7 @@ msgstr ""
"Falta el fichero 'extras.mhk'. Tambiщn es posible usar el fichero instalador "
"'arcriven.z'."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "Te faltan estos archivos de Riven:\n"
@@ -3693,7 +3731,7 @@ msgstr ""
"es recomendable que los elimines de la carpeta del juego para evitar "
"problemas."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3708,7 +3746,7 @@ msgstr ""
"que\n"
"se intentѓ aёadir y su versiѓn, lenguaje, etc.:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3718,11 +3756,11 @@ msgstr ""
"para prevenir pirateria\n"
"La version completa puede ser comprada en la tienda de iTunes."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Mostrar etiquetas de objetos"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Mostrar los nombres de los objetos en la parte inferior de la pantalla"
@@ -4400,7 +4438,7 @@ msgstr ""
"El soporte MIDI nativo requiere la actualizaciѓn Roland de LucasArts,\n"
"pero %s no estс disponible. Se usarс AdLib."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4485,7 +4523,7 @@ msgid "Use the floppy version's intro (CD version only)"
msgstr ""
"Usa la introducciѓn de la versiѓn en disquete (solo para la versiѓn CD)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, fuzzy, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4493,7 +4531,7 @@ msgstr ""
"Se ha encontrado una versiѓn incorrecta del archivo de datos del motor '%s'. "
"Se esperaba %d.%d pero se encontrѓ %d.%d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, fuzzy, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr "No se puede localizar el archivo de datos del motor '%s'."
@@ -4619,27 +4657,40 @@ msgstr "Se cargѓ la partida guardada rсpida #%d"
msgid "Could not quick load the saved game #%d"
msgstr "No es posible cargar la partida guardada rсpida #%d"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Mostrar contador de FPS"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
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/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Filtrado bilineal de sprites (LENTO)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Aplicar filtrado bilineal a sprites individuales"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Usar los menњs originales para guardar/cargar, en vez de los de ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4674,7 +4725,7 @@ msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr ""
"Usar los vэdeos MPEG de la versiѓn DVD en vez de los AVI de baja resoluciѓn"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4684,6 +4735,10 @@ msgstr ""
"versiѓn %d. Serс necesaria una versiѓn atualizada del motor para poder "
"usarla."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Usar los menњs originales para guardar/cargar, en vez de los de ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr ""
#~ "(Puedes activar esta funciѓn en la pestaёa Otras del menњ de opciones)"
diff --git a/po/eu.po b/po/eu.po
index bd7b5eb8d0..0e2a441941 100644
--- a/po/eu.po
+++ b/po/eu.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.5.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2016-12-04 13:27+0000\n"
-"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:12+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Basque <https://translations.scummvm.org/projects/scummvm/"
"scummvm/eu/>\n"
"Language: eu\n"
@@ -57,7 +57,7 @@ msgstr "Joan gora"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -82,7 +82,7 @@ msgstr "Aukeratu"
msgid "Select directory where to download game data"
msgstr "Jokoaren direktorioa aukeratu"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Jokoaren direktorioa aukeratu"
@@ -115,7 +115,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -128,7 +128,7 @@ msgstr "Bai"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -139,7 +139,7 @@ msgstr "Bai"
msgid "No"
msgstr "Ez"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM-k ezin izan du zehazturiko direktorioa ireki!"
@@ -150,8 +150,8 @@ msgid ""
msgstr ""
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -166,7 +166,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "Ados"
@@ -530,10 +530,10 @@ msgid ""
"Do you really want to reset all FluidSynth settings to their default values?"
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
-#: engines/scumm/help.cpp:166 engines/scumm/help.cpp:192
-#: engines/scumm/help.cpp:210
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Itxi"
@@ -582,111 +582,111 @@ msgstr "Sakatu esleituko den tekla"
msgid "Choose an action to map"
msgstr "Aukeratu esleituko den ekintza"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~I~rten"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Irten ScummVM-tik"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "Ho~n~i buruz..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "ScummVM-i buruz"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~A~ukerak..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "ScummVM-ren aukera globalak aldatu"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~H~asi"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Aukeraturiko jokora jolastu"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~K~argatu..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Aukeraturiko jokorako partida gordea kargatu"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~G~ehitu..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Shift mantendu sakaturik hainbat joko gehitzeko"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~E~ditatu..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Aldatu jokoaren aukerak"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~K~endu jokoa"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Jokoa zerrendatik kendu. Jokoaren fitxategiak ez dira ezabatzen"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~G~ehitu..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~E~ditatu..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~K~endu"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Bilatu joko-zerrendan"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Bilatu:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Jokoa kargatu:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Kargatu"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -694,64 +694,64 @@ msgstr ""
"Joko detektatzaile masiboa exekutatu nahi al duzu? Honek joko kantitate "
"handia gehitu dezake."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Benetan ezabatu nahi duzu joko-konfigurazio hau?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Gordetako jokoa kargatu?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Joko honek ez du uzten partidak abiarazletik kargatzen."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM-k ezin izan du aukeraturiko jokoa exekutatzeko gai den motorerik "
"aurkitu!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM-k ezin izan du jokorik aurkitu zehazturiko direktorioan!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Jokoa aukeratu:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Gehitu hainbat..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Grabatu..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... aurrerapena ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Bilaketa amaitua!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr ""
"%d joko berri aurkitu dira, aurretik gehituriko %d ez dira kontuan hartu."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "%d direktorio eskaneatu dira ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1601,31 +1601,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Gaia aukeratu"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "GFX desgaituta"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "GFX desgaituta"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Errendatzaile estandarra"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Estandarra"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Errendatzaile lausotua"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Lausotua"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Jokoa kargatu:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1643,7 +1671,7 @@ msgstr ""
msgid "Proceed"
msgstr ""
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Balioa kendu"
@@ -1788,19 +1816,6 @@ msgstr ""
msgid "<Bad value>"
msgstr "Balioa kendu:"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~J~arraitu"
@@ -1836,12 +1851,12 @@ msgstr "It~z~uli abiarazlera"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1856,12 +1871,12 @@ msgstr "Gorde jokoa:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1976,22 +1991,44 @@ msgstr ""
msgid "Start anyway"
msgstr "Jolastu berdin-berdin"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "AdLib emuladorea"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL emuladorea"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "DOSBox OPL emuladorea"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL emuladorea"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA FM zuzena"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2786,7 +2823,7 @@ msgstr "Eguneraketak bilatzen..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2794,7 +2831,7 @@ msgstr ""
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2840,6 +2877,7 @@ msgstr "Erabili jatorrizko gorde/kargatu pantailak"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
@@ -2888,9 +2926,9 @@ msgid ""
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2902,9 +2940,9 @@ msgid "Restore game:"
msgstr "Jokoa kargatu:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2915,7 +2953,7 @@ msgstr "Jokoa kargatu:"
msgid "Restore"
msgstr "Kargatu"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, fuzzy, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2937,7 +2975,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, fuzzy, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2953,11 +2991,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "'%s' bideo fitxategia ez da aurkitu!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Daltonikoentzako modua"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Gaitu daltonikoentzako modua lehenetsi modura"
@@ -3260,16 +3298,16 @@ msgstr ""
msgid "Naughty game mode"
msgstr ""
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr ""
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~ip modua aktibaturik"
@@ -3292,31 +3330,31 @@ msgstr "~M~apa erakutsi"
msgid "Main Men~u~"
msgstr "Menu ~n~agusia"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~U~r-efektua gaituta"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
#, fuzzy
msgid "Transitions:"
msgstr "~T~rantsizioak gaituta"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
#, fuzzy
msgid "Disabled"
msgstr "GFX desgaituta"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
#, fuzzy
msgid "Fastest"
msgstr "Modu bizkorra"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
#, fuzzy
msgid "Normal"
msgstr "OpenGL normala"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3325,25 +3363,25 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr "Joko pausatua. Sakatu ZURIUNEA jarraitzeko."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
msgstr ""
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
msgstr ""
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3658,7 +3696,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3667,19 +3705,19 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
"The full version is available for purchase from the iTunes Store."
msgstr ""
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
#, fuzzy
msgid "Show Object Line"
msgstr "Erakutsi objektuen etiketak"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr ""
@@ -4359,7 +4397,7 @@ msgstr ""
"MIDI euskarri natiboak LucasArts-en Roland eguneraketa behar du,\n"
"baina %s ez dago eskuragarri. AdLib erabiliko da."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4442,13 +4480,13 @@ msgstr "Floppy introa"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Erabili floppy bertsioko sarrera (CD bertsioa soilik)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4575,26 +4613,39 @@ msgstr ""
msgid "Could not quick load the saved game #%d"
msgstr "Gordetako jokoa kargatu?"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Erakutsi FPS kontatzailea"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "Erakutsi momentuko FPS (frames per second) goiko ezkerreko ertzean"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr ""
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr ""
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Erabili jatorrizko gorde/kargatu pantailak ScummVM interfazearenak beharrean"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4629,13 +4680,18 @@ msgstr "Erabili bereizmen altuko MPEG bideoa"
msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr "Erabili DVD bertsioko MPEG bideoa, bereizmen baxuagoko AVI-a beharrean"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
"%d. You will need an updated version of the engine to use this saved game."
msgstr ""
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Erabili jatorrizko gorde/kargatu pantailak ScummVM interfazearenak "
+#~ "beharrean"
+
#, fuzzy
#~ msgid "Check for updates automatically"
#~ msgstr "Eguneraketak bilatzen..."
diff --git a/po/fi_FI.po b/po/fi_FI.po
index 75b34c9462..30dac9ef75 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.6.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2018-01-24 16:16+0000\n"
-"Last-Translator: Timo Mikkolainen <tmikkola@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-06-01 15:55+0000\n"
+"Last-Translator: jepael <kermespersialainen@gmail.com>\n"
"Language-Team: Finnish <https://translations.scummvm.org/projects/scummvm/"
"scummvm/fi/>\n"
"Language: fi_FI\n"
@@ -57,7 +57,7 @@ msgstr "Siirry ylіs"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Valitse"
msgid "Select directory where to download game data"
msgstr "Valitse hakemisto pelilataukselle"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Valitse pelin hakemisto"
@@ -115,7 +115,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -128,7 +128,7 @@ msgstr "Kyllф"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -139,7 +139,7 @@ msgstr "Kyllф"
msgid "No"
msgstr "Ei"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM ei voi avata kyseistф hakemistoa!"
@@ -152,8 +152,8 @@ msgstr ""
"tiedosto samalla nimellф."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -168,7 +168,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -537,10 +537,10 @@ msgid ""
"Do you really want to reset all FluidSynth settings to their default values?"
msgstr "Haluatko varmasti palauttaa FluidSynth vakioasetukset?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Sulje"
@@ -589,111 +589,111 @@ msgstr "Paina haluamaasi nappia"
msgid "Choose an action to map"
msgstr "Valitse toiminto"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~L~opeta"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Lopeta ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "~T~ietoa..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Tietoa ScummVM:stф"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~A~setukset..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Muuta globaaleja ScummVM:n asetuksia"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~P~elaa"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Pelaa valittua peliф"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~L~ataa..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Lataa pelitallennus valitulle pelille"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~L~isфф peli..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Pidф Shift-nфppфintф pohjassa lisфtфksesi useita pelejф kerralla"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~M~uokkaa peliф..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Muuta pelin asetuksia"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "P~o~ista peli"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Poista peli listasta. Pelin tiedostoja ei poisteta levyltф"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "Lisфф peli..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~M~uokkaa peliф..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "P~o~ista peli"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Etsi peliф listasta"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Etsi:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Lataa peli:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Lataa"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -701,63 +701,63 @@ msgstr ""
"Haluatko varmasti lisфtф pelejф alihakemistoineen? Tфmф voi lisфtф suuren "
"mффrфn pelejф."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr "Tфtф kansiota ei voi kфyttфф vielф, siihen ladataan tiedostoja!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Haluatko varmasti poistaa pelin asetuksineen listalta?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Haluatko ladata tallennetun pelin?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Tфmф peli ei tue pelitallennuksien lataamista pelin ulkopuolelta."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr "ScummVM ei lіytфnyt pelimoottoria joka tukee valittua peliф!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM ei lіytфnyt yhtффn peliф kyseisestф hakemistosta!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Valitse peli:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Lisфф monta..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Nauhoita..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... skannaa ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Skannaus on valmis!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr ""
"%d uutta peliф lіytyi, jфtettiin %d peliф huomiotta, koska ne oli jo lisфtty "
"aiemmin."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Skannattiin %d hakemistoa ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1595,31 +1595,58 @@ msgstr ""
msgid "Select a Theme"
msgstr "Valitse teema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Disabloitu GFX"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Disabloitu GFX"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standardirenderіijф"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Standardi"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Antialiasoitu renderіijф"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Antialiasoitu"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr "Kopioi leikepіydфlle"
+
+#: gui/unknown-game-dialog.cpp:67
+msgid "Report game"
+msgstr "Tee ilmoitus pelistф"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr "Kфytф allaolevaa painiketta kopioidaksesi pelin tiedot leikepіydфlle."
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr "Voit myіs ilmoittaa pelisi suoraan Bug Trackeriin."
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr "Tarpeelliset tiedot pelistфsi on kopioitu leikepіydфlle"
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr "Pelin tietojen kopiointi leikepіydфlle epфonnistui!"
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1642,7 +1669,7 @@ msgstr ""
msgid "Proceed"
msgstr "Jatka"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Tyhjennф arvo"
@@ -1785,24 +1812,6 @@ msgstr "Kuukausittain"
msgid "<Bad value>"
msgstr "<Huono arvo>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Peli kansiossa \"%s\" nфyttфф olevan tuntematon %s pelimoottorin "
-"pelivariantti.\n"
-"Ole kiltti ja raportoi seuraavat tiedot ScummVM:n kehittфjille osoitteessa "
-"%s pelin nimen,\n"
-"version, kielen, yms. kera:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Tarkastetut peli ID:t:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~J~atka"
@@ -1838,12 +1847,12 @@ msgstr "Palaa p~e~livalitsimeen"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1858,12 +1867,12 @@ msgstr "Tallenna peli:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1975,22 +1984,48 @@ msgstr ""
msgid "Start anyway"
msgstr "Pelaa silti"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Peli kansiossa \"%s\" nфyttфф olevan tuntematon pelivariantti.\n"
+"Ole hyvф ja raportoi seuraavat tiedot ScummVM:n kehittфjille osoitteessa %s "
+"pelin nimen,\n"
+"version, kielen, yms. kera:"
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Tфsmффvфt tunnisteet pelimoottorille %s:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "AdLib emulaattori"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL emulaattori"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "DOSBox OPL emulaattori"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL emulaattori"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2787,7 +2822,7 @@ msgstr "Tarkista pфivitykset..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2795,7 +2830,7 @@ msgstr "\"%s\" pelimoottorin datatiedostoa ei lіydetty."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2841,6 +2876,7 @@ msgstr "Kфytф alkuperфisiф tallenna/lataa valikkoja"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr "Kфytф alkuperфisiф tallenna/lataa valikkoja ScummVM valikoiden sijaan"
@@ -2887,9 +2923,9 @@ msgstr ""
"kehoitteen sijaan."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2901,9 +2937,9 @@ msgid "Restore game:"
msgstr "Lataa pelitallenne:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2914,7 +2950,7 @@ msgstr "Lataa pelitallenne:"
msgid "Restore"
msgstr "Lataa tallenne"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2936,7 +2972,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2952,11 +2988,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Videotiedostoa '%s' ei lіytynyt!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Vфrisokeustila"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Aktivoi vфrisokeustila vakiona"
@@ -3248,16 +3284,16 @@ msgstr "Animoitu pelikфyttіliittymф"
msgid "Naughty game mode"
msgstr "Tuhma pelitila"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Soita Myst fly by-video"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "Alkuperфinen pelimoottori ei toistanut Myst fly by-videota."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~ip moodi valittu"
@@ -3278,27 +3314,27 @@ msgstr "Nфytф ~K~artta"
msgid "Main Men~u~"
msgstr "Pффvalikko ~u~"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~V~esiefekti pффllф"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Siirtymфt:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Pois pффltф"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Nopein"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normaali"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Paras"
@@ -3306,7 +3342,7 @@ msgstr "Paras"
msgid "The game is paused. Press any key to continue."
msgstr "Pause. Paina mitф tahansa nappia jatkaaksesi."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3314,7 +3350,7 @@ msgstr ""
"Sinulta puuttuu Riven ohjelmatiedosto. WIndowsissa tiedosto on nimeltффn "
"\"riven.exe\" tai \"rivendmo.exe\". "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3322,7 +3358,7 @@ msgstr ""
"\"archriven.z\" asennustiedoston kфyttі toimii myіs. Lisфksi voit kфyttфф "
"Macin \"Riven\"-ohjelmatiedostoa."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3330,7 +3366,7 @@ msgstr ""
"Sinulta puuttuu \"extras.mhk\". \"archriven.z\" asennustiedoston kфyttі "
"toimii myіs."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "Sinulta puuttuu seuraavat vaaditut Rivenin datatiedostot:\n"
@@ -3671,7 +3707,7 @@ msgstr ""
"suosittelemme ettф poistatte nфmф korjaukset pelikansiosta jotteivфt ne "
"aiheuttaisi ongelmia."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3684,7 +3720,7 @@ msgstr ""
"kehittфjille pelin nimen,\n"
"version, kielen, yms. kera.\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3694,11 +3730,11 @@ msgstr ""
"ehkфisemiseksi.\n"
"Kokoversion voi ostaa iTunes-kaupasta."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Nфytф esineiden tiedot"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Nфytф esineiden nimet nфytіn alalaidassa"
@@ -4376,7 +4412,7 @@ msgstr ""
"Suora MIDI tuki vaatii Roland pфivityksen LucasArtsilta, mutta\n"
"%s puuttuu. Kфytetффn AdLibia sen sijaan."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4459,7 +4495,7 @@ msgstr "Levykeversion intro"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Kфytф levykeversion introa (vain CD versiossa)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4467,7 +4503,7 @@ msgstr ""
"Pelimoottorin \"%s\" datatiedostosta lіytyi vффrф versio. Odotettu versio "
"%d, lіytynyt versio %d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr "Kielen %s tekstejф ei lіydetty tiedostosta '%s'."
@@ -4590,30 +4626,46 @@ msgstr "Pelitallenne #%d pikaladattu"
msgid "Could not quick load the saved game #%d"
msgstr "Tallennuksen #%d pikalataus epфonnistui"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Nфytф FPS-laskuri"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "Nфytф tфmфnhetkinen kuvia/sekunti mффrф vasemmassa ylфnurkassa"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Spritejen bilineaarinen suodatus (HIDAS)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Kфytф bilineaarista suodatusta yksittфisiin spriteihin"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr "Nфytф esineiden hinnat normaalissa inventoriossa"
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+"Nфyttфф esineiden hinnat normaalissa inventoriossa, mahdollistaen arvojen "
+"vertailun"
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr "Kestфvфmmфt suojavarusteet"
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Kфytф alkuperфisiф tallenna/lataa valikkoja ScummVM kфyttіliittymфn sijaan"
+"Suojavaruste hajoaa vasta hahmon ollessa -80HP:ssф normaalin -10HP sijasta"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr "Tupla FPS"
+msgstr "Kaksinkertaista FPS"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
@@ -4645,7 +4697,7 @@ msgstr ""
"Kфytф DVD-version MPEG videoita matalampiresoluutioisten AVI-tiedostojen "
"sijaan"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4655,6 +4707,10 @@ msgstr ""
"vain versioon %d asti. Tarvitset pфivitetyn version tфstф pelimoottorista "
"kфyttффksesi tфtф pelitallennusta."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Kфytф alkuperфisiф tallenna/lataa valikkoja ScummVM kфyttіliittymфn sijaan"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr "(Voit aina laittaa sen pффlle asetusvalikon \"Muut\"-vфlilehdestф)"
diff --git a/po/fr_FR.po b/po/fr_FR.po
index a8aa9b61de..d6525c099f 100644
--- a/po/fr_FR.po
+++ b/po/fr_FR.po
@@ -7,11 +7,11 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2018-03-09 21:04+0000\n"
-"Last-Translator: Thierry Crozat <criezy@scummvm.org>\n"
-"Language-Team: French <https://translations.scummvm.org/projects/scummvm/"
-"scummvm/fr/>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-06-03 14:49+0000\n"
+"Last-Translator: Donovan Watteau <tsoomi@gmail.com>\n"
+"Language-Team: French "
+"<https://translations.scummvm.org/projects/scummvm/scummvm/fr/>\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
@@ -23,7 +23,7 @@ msgstr ""
#: gui/about.cpp:94
#, c-format
msgid "(built on %s)"
-msgstr "(compilщ sur %s)"
+msgstr "(compilщ le %s)"
#: gui/about.cpp:101
msgid "Features compiled in:"
@@ -57,7 +57,7 @@ msgstr "Remonter"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Choisir"
msgid "Select directory where to download game data"
msgstr "Sщlectionner le rщpertoire dans lequel tщlщcharger les donnщes du jeu"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Sщlectionner le rщpertoire contenant les donnщes du jeu"
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Oui"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Oui"
msgid "No"
msgstr "Non"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM n'a pas pu ouvrir le rщpertoire sщlectionnщ !"
@@ -153,8 +153,8 @@ msgstr ""
"mъme nom existe dщjр."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -169,7 +169,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -237,8 +237,8 @@ msgid ""
"Language of the game. This will not turn your Spanish game version into "
"English"
msgstr ""
-"Langue du jeu. Cela ne traduira pas en anglais par magie votre version "
-"espagnole du jeu."
+"Langue du jeu. Ceci ne traduira pas automatiquement une version щtrangшre du "
+"jeu."
#: gui/editgamedialog.cpp:152 gui/editgamedialog.cpp:166 gui/options.cpp:995
#: gui/options.cpp:1008 gui/options.cpp:1573 audio/null.cpp:41
@@ -542,10 +542,10 @@ msgstr ""
"Voulez-vous vraiment remettre tous les rщglages FluidSynth р leurs valeurs "
"par dщfaut ?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Fermer"
@@ -594,112 +594,112 @@ msgstr "Appuyez sur la touche р associer"
msgid "Choose an action to map"
msgstr "Sщlectionnez une action р affecter"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~Q~uitter"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Quitter ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "Р ~P~ropos..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Р propos de ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~ptions..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Change les options globales de ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~D~щmarrer"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Dщmarre le jeu sщlectionnщ"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~C~harger..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Charge une sauvegarde pour le jeu sщlectionnщ"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~A~jouter..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr ""
"Ajoute un jeu р la Liste. Maintenez Shift enfoncщe pour un Ajout Massif"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~E~diter..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Change les options du jeu"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~S~upprimer"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Supprime le jeu de la liste. Les fichiers sont conservщs"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~A~jouter..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~E~diter..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~S~upprimer"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Recherche dans la liste de jeux"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Filtre :"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Charger le jeu :"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Charger"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -707,64 +707,64 @@ msgstr ""
"Voulez-vous vraiment lancer la dщtection automatique des jeux ? Cela peut "
"potentiellement ajouter un grand nombre de jeux."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
"Ce rщpertoire est en cours de tщlщchargement et ne peut pas encore ъtre "
"utilisщ !"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Voulez-vous vraiment supprimer ce jeu ?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Voulez-vous charger le jeu ?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr ""
"Le chargement de sauvegarde depuis le lanceur n'est pas supportщ pour ce jeu."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr "ScummVM n'a pas pu trouver de moteur pour lancer le jeu sщlectionnщ !"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM n'a pas trouvщ de jeu dans le rщpertoire sщlectionnщ !"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Choisissez le jeu :"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Ajout Massif..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Enregistrer..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... en cours ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Examen terminщ !"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "%d nouveaux jeux trouvщs, %d jeux ignorщs (dщjр ajoutщs prщcщdemment)."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "%d rщpertoires examinщs ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1612,31 +1612,64 @@ msgstr ""
msgid "Select a Theme"
msgstr "Sщlectionnez un Thшme"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "GFX dщsactivщ"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "GFX dщsactivщ"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Rendu Standard"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Normal"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Rendu Anti-crщnelщ"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Anti-crщnelщ"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr "Copier Informations"
+
+#: gui/unknown-game-dialog.cpp:67
+msgid "Report game"
+msgstr "Signaler le jeu"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+"Utilisez le bouton ci-dessous pour copier les informations requises dans le "
+"presse-papiers."
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+"Vous pouvez щgalement directement signaler votre jeu dans notre Tracker de "
+"Bogues."
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+"Toutes les informations nщcessaires sur votre jeu ont щtщ copiщes dans le "
+"presse-papiers"
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr "La copie des informations du jeu dans le presse-papiers a щchouщe !"
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1659,7 +1692,7 @@ msgstr ""
msgid "Proceed"
msgstr "Appliquer"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Effacer la valeur"
@@ -1802,25 +1835,6 @@ msgstr "Une fois pas mois"
msgid "<Bad value>"
msgstr "<Valeur invalide>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Le jeu dans '%s' semble ъtre une version inconnue d'un jeu supportщ par le "
-"moteur %s.\n"
-"\n"
-"Veuillez reporter les informations ci-dessous р l'щquipe de ScummVM sur %s "
-"ainsi que le nom du jeu que vous avez essayщ d'ajouter, sa version, la "
-"langue, etc... :"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Jeux possibles :"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~R~eprendre"
@@ -1856,12 +1870,12 @@ msgstr "Retour au ~L~anceur"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1876,12 +1890,12 @@ msgstr "Sauvegarde :"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1969,7 +1983,7 @@ msgid ""
msgstr ""
"Ce jeu possшde des pistes audio sur le CD. Pour\n"
"profiter de la musique, ces pistes doivent ъtre\n"
-"extraite du CD et rщencodщe en utilisant un\n"
+"extraites du CD et rщencodщes en utilisant un\n"
"logiciel appropriщ.\n"
"Lisez le fichier README pour plus de dщtails."
@@ -1988,7 +2002,7 @@ msgid ""
"ScummVM. As such, it is likely to be unstable, and any saved game you make "
"might not work in future versions of ScummVM."
msgstr ""
-"Attention : le jeu que vous vous apprъtez р jouer n'est pas encore "
+"Attention : le jeu que vous vous apprъtez р lancer n'est pas encore "
"complшtement supportщ par ScummVM. Il est donc instable et les sauvegardes "
"peuvent ne pas marcher avec une future version de ScummVM."
@@ -1996,22 +2010,49 @@ msgstr ""
msgid "Start anyway"
msgstr "Je comprends"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Le jeu dans '%s' semble ъtre une version inconnue d'un jeu supportщ.\n"
+"\n"
+"Veuillez fournir les informations ci-dessous р l'щquipe de ScummVM sur %s "
+"ainsi que le nom du jeu que vous avez essayщ d'ajouter, sa version, la "
+"langue, etc... :"
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Jeux possibles pour le moteur %s :"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Щmulateur AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Щmulateur MAME OPL"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Щmulateur DOSBox OPL"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Щmulateur OPL Nuked"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2806,7 +2847,7 @@ msgstr "Recherche des mises р jour..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2814,7 +2855,7 @@ msgstr "Le fichier de donnщes '%s' n'a pu ъtre trouvщ."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2860,6 +2901,7 @@ msgstr "Dialogues sauvegarde/chargement d'origine"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"Utiliser les dialogues sauvegarde/chargement d'origine plutєt que ceux de "
@@ -2910,9 +2952,9 @@ msgstr ""
"les jeux SCI) р la place d'un champ de saisie en temps rщel."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2924,9 +2966,9 @@ msgid "Restore game:"
msgstr "Charger le jeu :"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2937,7 +2979,7 @@ msgstr "Charger le jeu :"
msgid "Restore"
msgstr "Charger"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2959,7 +3001,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2975,11 +3017,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Fichier de sщquence '%s' non trouvщ !"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Mode Daltonien"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Activer le mode Daltonien par dщfaut"
@@ -3274,16 +3316,16 @@ msgstr "Interface du jeu animщe"
msgid "Naughty game mode"
msgstr "Mode coquin"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Jouer la vidщo du survol de Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "La vidщo du survol de Myst n'щtait pas jouщe par le moteur originel."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "Mode ~Z~ip Activщ"
@@ -3304,27 +3346,27 @@ msgstr "Afficher la ~C~arte"
msgid "Main Men~u~"
msgstr "~M~enu Principal"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~E~ffets de l'Eau Activщs"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Transitions :"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Dщsactivщ"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Rapide"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Meilleur"
@@ -3332,7 +3374,7 @@ msgstr "Meilleur"
msgid "The game is paused. Press any key to continue."
msgstr "Jeu en pause. Appuyer sur une touche pour Reprendre."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3340,7 +3382,7 @@ msgstr ""
"Il vous manque l'exщcutable de Riven. L'exщcutable pour Windows se nomme "
"'rivent.exe' ou 'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3348,7 +3390,7 @@ msgstr ""
"Utiliser le fichier archive 'arcriven.z' marche щgalement. Vous pouvez "
"щgalement utiliser l'exщcutable pour Mac qui se nomme 'Riven'."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3356,7 +3398,7 @@ msgstr ""
"Il vous manque le fichier 'extras.mhk'. Utiliser le fichier archive "
"'arcriven.z' marche щgalement."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
"Il vous manque les fichiers de donnщes obligatoires suivants pour Riven :\n"
@@ -3525,7 +3567,7 @@ msgstr "Activer les vidщos avec traits noirs"
#: engines/sci/detection.cpp:421
msgid "Draw black lines over videos to increase their apparent sharpness"
-msgstr "Affiche des lignes noirs sur les vidщos pour les rendre plus nets"
+msgstr "Affiche des lignes noires sur les vidщos pour les rendre plus nettes"
#: engines/sci/detection.cpp:431
msgid "Use high-quality video scaling"
@@ -3710,14 +3752,14 @@ msgid ""
"remove this patch from your game folder in order to avoid having unexpected "
"errors and/or issues later on."
msgstr ""
-"Votre jeu contient un correctifs de script fait par des fans. Ces correctifs "
+"Votre jeu contient un correctif de script fait par des fans. Ces correctifs "
"peuvent modifier les scripts du jeu en profondeur et sont connus pour "
-"introduire des problшmes. De plus les problшmes corrigщs par ces correctifs "
-"sont dщjр corrigщ par ScummVM, donc nous recommandons d'enlever ces "
+"introduire des problшmes. De plus, les problшmes corrigщs par ces correctifs "
+"sont dщjр corrigщs par ScummVM, nous recommandons donc d'enlever ces "
"correctifs de votre rщpertoire contenant les donnщes du jeu pour щviter tout "
"problшme."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3731,7 +3773,7 @@ msgstr ""
"ci-dessous р l'щquipe de ScummVM ainsi que le nom du jeu que vous avez\n"
"essayщ d'ajouter, sa version, la langue, etc... :\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3741,11 +3783,11 @@ msgstr ""
"щviter le piratage.\n"
"La version complшte peut-ъtre achetщe sur l'iTunes Store."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Afficher la barre d'objets"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Afficher le nom des objets en bas de l'щcran"
@@ -4420,10 +4462,10 @@ msgid ""
"Native MIDI support requires the Roland Upgrade from LucasArts,\n"
"but %s is missing. Using AdLib instead."
msgstr ""
-"Support MIDI natif requiшre la mise р jour Roland de LucasArt,\n"
+"Support MIDI natif requiert la mise р jour Roland de LucasArts,\n"
"mais %s manque. Utilise AdLib р la place."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4510,7 +4552,7 @@ msgstr "Intro disquette"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Utiliser l'intro de la version disquette (version CD uniquement)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4518,7 +4560,7 @@ msgstr ""
"La bonne version du fichier de donnщes '%s' n'a pu ъtre trouvщe. Version "
"attendue : %d ; version trouvщe : %d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4529,7 +4571,7 @@ msgstr ""
#, c-format
msgid "PSX stream cutscene '%s' cannot be played in paletted mode"
msgstr ""
-"La scшne cinщmatique PSX '%s' ne peut pas ъtre lu avec 256 couleurs ou moins"
+"La scшne cinщmatique PSX '%s' ne peut pas ъtre lue avec 256 couleurs ou moins"
#: engines/sword1/animation.cpp:545 engines/sword2/animation.cpp:445
msgid "DXA cutscenes found but ScummVM has been built without zlib"
@@ -4619,7 +4661,7 @@ msgid ""
"The teenagent.dat file is compressed and zlib hasn't been included in this "
"executable. Please decompress it"
msgstr ""
-"Le fichier teenagent.dat est compressщ et cet exщcutable n'inclus pas zlib. "
+"Le fichier teenagent.dat est compressщ et cet exщcutable n'inclut pas zlib. "
"Veuillez le dщcompresser."
#: engines/tony/tony.cpp:258
@@ -4648,28 +4690,44 @@ msgstr "Chargement rapide depuis l'emplacement #%d"
msgid "Could not quick load the saved game #%d"
msgstr "Erreur lors du chargement rapide depuis l'emplacement #%d"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Afficher le compteur FPS"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
"Affiche le nombre d'images par seconde (FPS) dans le coin en haut р gauche"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Filtrage bilinщaire des images-objets (LENT)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Applique un filtrage bilinщaire р chaque image-objet"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr "Afficher le prix des objets dans l'inventaire en mode standard"
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
msgstr ""
-"Utiliser les dialogues sauvegarde/chargement d'origine plutєt que ceux de "
-"ScummVM"
+"Affiche le prix des objets dans l'inventaire en mode standard, ce qui permet "
+"de comparer la valeur des objets"
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr "Armure plus durable"
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
+msgstr ""
+"L'armure ne se brisera pas avant que le personnage ne soit р -80HP, au lieu "
+"de -10HP"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4705,7 +4763,7 @@ msgstr ""
"Utiliser les vidщos MPEG du DVD р la place des vidщos AVI de plus basse "
"rщsolution"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4715,6 +4773,11 @@ msgstr ""
"les versions %d ou infщrieures. Vous devez utiliser une version plus rщcente "
"de ScummVM pour pouvoir charger cette sauvegarde."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Utiliser les dialogues sauvegarde/chargement d'origine plutєt que ceux de "
+#~ "ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr ""
#~ "(Vous pouvez aussi activer cette option dans le tab 'Divers'\n"
diff --git a/po/gl_ES.po b/po/gl_ES.po
index 4034c62df6..2e5d5da536 100644
--- a/po/gl_ES.po
+++ b/po/gl_ES.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-11-23 12:42+0000\n"
-"Last-Translator: Santiago G. Sanz <santiagogarciasanz@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:12+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Galician <https://translations.scummvm.org/projects/scummvm/"
"scummvm/gl/>\n"
"Language: gl_ES\n"
@@ -57,7 +57,7 @@ msgstr "Arriba"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Elixir"
msgid "Select directory where to download game data"
msgstr "Selecciona un directorio para descargar os datos de xogo"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Selecciona un directorio con datos de xogo"
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Si"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Si"
msgid "No"
msgstr "Non"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM non foi quen de abrir o directorio!"
@@ -153,8 +153,8 @@ msgstr ""
"ten un ficheiro co mesmo nome."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -169,7 +169,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "Aceptar"
@@ -540,10 +540,10 @@ msgstr ""
"Seguro que queres restablecer a configuraciѓn de FluidSynth aos seus valores "
"predefinidos?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Pechar"
@@ -592,111 +592,111 @@ msgstr "Preme a tecla para asociala"
msgid "Choose an action to map"
msgstr "Elixe unha acciѓn para asignala"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~S~aэr"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Saэr de ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "Ace~r~ca de..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Acerca de ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~pciѓns..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Cambiar as opciѓns de ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~I~niciar"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Iniciar o xogo seleccionado"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~C~argar..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Cargar partida do xogo seleccionado"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "Eng~a~dir xogo..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Manter premido MAIкS para engadir en masa"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~E~ditar xogo..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Cambiar as opciѓns do xogo"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "Elimina~r~ xogo"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Eliminar o xogo da lista. Os ficheiros de datos non se modifican"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "Eng~a~dir xogo..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~E~ditar xogo..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "Elimina~r~ xogo"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Buscar na lista de xogos"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Buscar:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Cargar partida:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Cargar"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -704,61 +704,61 @@ msgstr ""
"Queres executar o detector de xogos en masa? Щ posible que se engada un gran "
"nњmero de xogos."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr "Aэnda non se pode empregar este directorio. A descarga non rematou!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Seguro que queres eliminar esta configuraciѓn de xogo?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Queres cargar a partida gardada?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "O xogo non permite cargar partidas dende o iniciador."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr "ScummVM non foi quen de atopar un motor para executar o xogo!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM non foi quen de atopar xogos no directorio!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Elixe o xogo:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Engadir en masa..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Gravar..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... progreso..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Anсlise finalizada!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "%d xogos novos atopados; %d xogos xa engadidos ignorados."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "%d directorios analizados..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "%d xogos novos atopados; %d xogos xa engadidos ignorados..."
@@ -1600,31 +1600,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Seleccionar tema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Efectos grсficos desactivados"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Efectos desactivados"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Procesamento estсndar"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Estсndar"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Procesamento antidistorsiѓn"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Antidistorsiѓn"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Restaurar xogo:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1647,7 +1675,7 @@ msgstr ""
msgid "Proceed"
msgstr "Continuar"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Limpar valor"
@@ -1790,23 +1818,6 @@ msgstr "Mensualmente"
msgid "<Bad value>"
msgstr "<Valor errѓneo>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"O xogo en %s semella ser unha variante descoёecida do motor %s.\n"
-"\n"
-"Por favor, envэa os seguintes datos ao equipo de ScummVM en %s xunto co nome "
-"do xogo que tentaches engadir, a sњa versiѓn, lingua, etc.:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "ID de xogo emparellados:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~R~etomar"
@@ -1842,12 +1853,12 @@ msgstr "~V~olver ao Iniciador"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1862,12 +1873,12 @@ msgstr "Gardar partida:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1982,22 +1993,48 @@ msgstr ""
msgid "Start anyway"
msgstr "Iniciar de todos os xeitos"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"O xogo en %s semella ser unha variante descoёecida do motor %s.\n"
+"\n"
+"Por favor, envэa os seguintes datos ao equipo de ScummVM en %s xunto co nome "
+"do xogo que tentaches engadir, a sњa versiѓn, lingua, etc.:"
+
+#: engines/game.cpp:162
+#, fuzzy, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "ID de xogo emparellados:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Emulador de AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Emulador de OPL de MAME"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Emulador de OPL de DOSBox"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Emulador de OPL de Nuked"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2790,7 +2827,7 @@ msgstr "Buscar actualizaciѓns..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2798,7 +2835,7 @@ msgstr "Non se puido localizar o ficheiro de datos do motor %s."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2844,6 +2881,7 @@ msgstr "Empregar pantallas orixinais de gardado e carga"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"Emprega as pantallas orixinais de gardado e carga, no canto das de ScummVM."
@@ -2892,9 +2930,9 @@ msgstr ""
"facelo en tempo real."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2906,9 +2944,9 @@ msgid "Restore game:"
msgstr "Restaurar xogo:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2919,7 +2957,7 @@ msgstr "Restaurar xogo:"
msgid "Restore"
msgstr "Restaurar"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2941,7 +2979,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2957,11 +2995,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Non se atopou o ficheiro de secuencia %s!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Modo accesible para daltonismo"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Activa o modo accesible para daltonismo de xeito predeterminado."
@@ -3257,16 +3295,16 @@ msgstr "Interface de xogo animada"
msgid "Naughty game mode"
msgstr "Modo de xogo rebelde"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Reproducir o filme de imaxes aщreas de Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "O filme de imaxes aщreas de Myst non se reproduciu co motor orixinal."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "Modo ~C~omprimido activado"
@@ -3287,27 +3325,27 @@ msgstr "Mostrar ~m~apa"
msgid "Main Men~u~"
msgstr "Menњ ~p~rincipal"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "Efecto de ~a~uga activado"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Transiciѓns:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Desactivados"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Mсis rсpido"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Mellor"
@@ -3315,7 +3353,7 @@ msgstr "Mellor"
msgid "The game is paused. Press any key to continue."
msgstr "Xogo en pausa. Pulsa calquera tecla para continuar."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3323,7 +3361,7 @@ msgstr ""
"Falta un executable de Riven. O executable de Windows щ riven.exe ou "
"rivendmo.exe. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3331,7 +3369,7 @@ msgstr ""
"Tamщn podes empregar o ficheiro do instalador arcriven.z ou o executable de "
"Mac."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3339,7 +3377,7 @@ msgstr ""
"Falta o ficheiro extras.mhk. Tamщn podes empregar o ficheiro do instalador "
"arcriven.z."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "Faltan os seguintes ficheiros de datos requiridos de Riven:\n"
@@ -3688,7 +3726,7 @@ msgstr ""
"en ScummVM, polo que recomendamos que elimines este parche do cartafol do "
"xogo para evitar erros ou problemas inesperados mсis adiante."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3701,7 +3739,7 @@ msgstr ""
"afeccionados), envэa os seguintes datos ao equipo de ScummVM,\n"
"xunto co nome do xogo que tentaches engadir, a sњa versiѓn, lingua, etc.:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3711,11 +3749,11 @@ msgstr ""
"piraterэa.\n"
"A versiѓn completa estс dispoёэbel para mercar na tenda de iTunes."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Mostrar liёa de obsecto"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Mostra os nomes dos obxectos na parte inferior da pantalla"
@@ -4393,7 +4431,7 @@ msgstr ""
"A compatibilidade nativa con MIDI precisa a actualizaciѓn de Roland\n"
"de LucasArts, mais falla %s. Empregarase AdLib."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4475,7 +4513,7 @@ msgstr "Intro de disquete"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Emprega a introduciѓn da versiѓn en disquete (sѓ versiѓn en CD)."
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, fuzzy, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4483,7 +4521,7 @@ msgstr ""
"Atopouse unha versiѓn incorrecta do ficheiro de datos do motor %s. Ficheiro "
"esperado: %d.%d. Ficheiro atopado: %d.%d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, fuzzy, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr "Non se puido localizar o ficheiro de datos do motor %s."
@@ -4608,27 +4646,39 @@ msgstr "Carga rсpida exitosa da partida gardada %d."
msgid "Could not quick load the saved game #%d"
msgstr "Erro de carga rсpida da partida gardada %d."
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Mostrar FPS"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "Mostra o nњmero actual de FPS na esquina superior esquerda."
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Filtraxe bilineal de sprites (LENTA)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Aplica a flitraxe bilineal a cada sprite."
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Empregar as pantallas orixinais de gardado e carga, no canto da interface de "
-"ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4663,7 +4713,7 @@ msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr ""
"Emprega o vэdeo MPEG da versiѓn en DVD, no canto do AVI de menor resoluciѓn."
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4673,6 +4723,11 @@ msgstr ""
"compatэbel atщ a versiѓn %d. Cѓmpre descargar unha versiѓn actualizada do "
"motor para empregar esta partida gardada."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Empregar as pantallas orixinais de gardado e carga, no canto da interface "
+#~ "de ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr "(Podes actэvalo no diсlogo de opciѓn da pestana Misc.)"
diff --git a/po/hu_HU.po b/po/hu_HU.po
index 6e462338fe..2fc90bccbe 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.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2018-01-24 04:01+0000\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-05-29 03:00+0000\n"
"Last-Translator: George Kormendi <grubycza@hotmail.com>\n"
"Language-Team: Hungarian <https://translations.scummvm.org/projects/scummvm/"
"scummvm/hu/>\n"
@@ -57,7 +57,7 @@ msgstr "Feljebb"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Vсlaszt"
msgid "Select directory where to download game data"
msgstr "Vсlassz mappсt, ahonnan letіlthetѕk a jсtщk adatok"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Jсtщkok helyщnek kivсlasztсsa"
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Igen"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Igen"
msgid "No"
msgstr "Nem"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM nem tudja megnyitni a vсlasztott mappсt!"
@@ -153,8 +153,8 @@ msgstr ""
"ugyanazzal a nщvvel."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -169,7 +169,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -537,10 +537,10 @@ msgid ""
msgstr ""
"Biztos visszaсllэtassz minden FluidSynth beсllэtсst alapщrtelmezett щrtщkre?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Bezсr"
@@ -589,111 +589,111 @@ msgstr "Nyomj egy billentyћt a tсrsэtсshoz"
msgid "Choose an action to map"
msgstr "Vсlassz mћveletet a kiosztсshoz"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "Kilщpщs"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "ScummVM bezсrсsa"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "Nщvjegy..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "ScummVM nщvjegy"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~pciѓk..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Globсlis ScummVM opciѓk cserщje"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "Indэtсs"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "A vсlasztott jсtщk indэtсsa"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~B~etіlt..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Kimentett jсtщkсllсs betіltщse"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "Jсtщk hozzсadсs..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Tratsd lenyomva a Shift-et a Masszэv mѓdhoz"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "Jсtщkopciѓk..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Jсtщk beсllэtсsok megvсltoztatсsa"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "Jсtщk tіrlщse"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Tіrli a jсtщk nevщt a listсrѓl. A jсtщkfсjlok megmaradnak"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "Jсtщk hozzсadсs..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "Jсtщkopciѓk..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "Jсtщk tіrlщse"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Keresщs a jсtщklistсban"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Keresщs:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Jсtщk betіltщse:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Betіltщs"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -701,62 +701,62 @@ msgstr ""
"Biztos hogy futtatod a Masszэv jсtщkdetektort? Ez potenciсlisan sok jсtщkot "
"hozzсad a listсhoz."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr "Ez a mappa nem hasznсlhatѓ mщg, щppen letіltщs van folyamatban!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Biztosan tіrіlni akarod ezt a jсtщkkonfigurсciѓt?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Akarod hogy betіltщsem a jсtщkсllсst?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Ez a jсtщk nem tсmogatja a jсtщkсllсs betіltщst az indэtѓbѓl."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM nem talсlt olyan jсtщkmotort ami a vсlasztott jсtщkot tсmogatja!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "A ScummVM nem talсlt egy jсtщkot sem a vсlasztott mappсban!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Vсlassztott jсtщk:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Masszэv mѓd..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Felvщtel..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... folyamatban ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Vizsgсlat kщsz!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "%d њj jсtщkot talсltam, %d elѕzѕleg hozzсadott jсtщk kihagyva..."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "%d Mappa сtvizsgсlva..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "%d њj jсtщkot talсltam, %d elѕzѕleg hozzсadott jсtщk kihagyva..."
@@ -1589,31 +1589,60 @@ msgstr ""
msgid "Select a Theme"
msgstr "Vсlassz tщmсt"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "GFX letiltva"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "GFX letiltva"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standard lekщpezѕ"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Сtlagos"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Щlsimэtсsos lekщpezѕ"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Щlsimэtott"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr "Mсsolсs a vсgѓlapra"
+
+#: gui/unknown-game-dialog.cpp:67
+msgid "Report game"
+msgstr "Jсtщk jelentщse"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+"Az alсbbi gombra kattintva a szќksщges jсtщkinformсciѓkat a vсgѓlapra "
+"mсsolja."
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr "A jсtщkot kіzvetlenќl a Bug Tracker-re is bejelentheti."
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr "Minden szќksщges informсciѓ a jсtщkrѓl a vсgѓlapra mсsolva"
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr "A jсtщkinformсciѓk mсsolсsa a vсgѓlapra nem sikerќlt!"
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1636,7 +1665,7 @@ msgstr ""
msgid "Proceed"
msgstr "Folyamatban"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Щrtщk tіrlщse"
@@ -1779,23 +1808,6 @@ msgstr "Havonta"
msgid "<Bad value>"
msgstr "<Rossz щrtщk>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"A (z) '%s' jсtщk egy ismeretlen %s motor jсtщk vсltozatnak tћnik.\n"
-"\n"
-"Kщrjќk, jelentse a kіvetkezѕ adatokat a ScummVM csapatnak %s a jсtщk nevщvel "
-"egyќtt, amelyet megprѓbсlt hozzсadni, щs annak verziѓjсt, nyelvщt stb.:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Egyezѕ jсtщkazonosэtѓk:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "Folytatсs"
@@ -1831,12 +1843,12 @@ msgstr "Visszatщrщs az indэtѓba"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1851,12 +1863,12 @@ msgstr "Jсtщk mentщse:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1971,22 +1983,48 @@ msgstr ""
msgid "Start anyway"
msgstr "Indэtсs эgy is"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"A(z) '%s' jсtщk egy ismeretlen jсtщkvсltozatnak tћnik.\n"
+"\n"
+"Kщrjќk, jelentse a kіvetkezѕ adatokat a ScummVM csapatnak %s a jсtщk nevщvel "
+"egyќtt, amelyet megprѓbсlt hozzсadni, щs annak verziѓjсt, nyelvщt stb.:"
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Megfelelѕ jсtщkazonosэtѓk a %s motorhoz:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "AdLib Emulсtor"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL emulсtor"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "DOSBox OPL emulсtor"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL emulсtor"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2775,7 +2813,7 @@ msgstr "Frissэtщsek keresщse..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2783,7 +2821,7 @@ msgstr "Nem talсlhatѓ a(z) '%s' motorhoz adat fсjl."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2829,6 +2867,7 @@ msgstr "Eredeti ment/tіlt kщpernyѕk hasznсlata"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr "Hasznсld az eredeti mentщs/betіltщs kщpernyѕt a ScummVM fщle helyett"
@@ -2876,9 +2915,9 @@ msgstr ""
"idejќ parancs helyett."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2890,9 +2929,9 @@ msgid "Restore game:"
msgstr "Jсtщkmenet visszaсllэtсsa:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2903,7 +2942,7 @@ msgstr "Jсtщkmenet visszaсllэtсsa:"
msgid "Restore"
msgstr "Visszaсllэtсs"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2925,7 +2964,7 @@ msgstr ""
"\n"
"%s fсjlba"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2941,11 +2980,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "'%s' сtvezetѕ fсjl nem talсlhatѓ!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Szэnvak Mѓd"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Szinvak mѓd engedщlyezve alapщrtelmezett"
@@ -3239,16 +3278,16 @@ msgstr "Animсlt jсtщk felќlet"
msgid "Naughty game mode"
msgstr "Pajkos jсtщkmѓd"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Myst bevezetѕ film lejсtszсsa"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "A Myst bevezetѕ filmet nem jсtszotta le az eredeti motor."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~ip Mѓd aktivсlva"
@@ -3269,27 +3308,27 @@ msgstr "~M~ Tщrkщp nщzet"
msgid "Main Men~u~"
msgstr "Fѕ Menќ ~u~"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "Vэzeffektus engedщlyezve"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Сtmenetek:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Letiltva"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Leggyorsabb"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normсl"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Legjobb"
@@ -3297,7 +3336,7 @@ msgstr "Legjobb"
msgid "The game is paused. Press any key to continue."
msgstr "A jсtщk szќnetel. Nyomj egy gombot a folytatсshoz."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3305,7 +3344,7 @@ msgstr ""
"Hiсnyzik a Riven futtathatѓ сllomсny. A Windows fсjlok neve 'riven.exe' vagy "
"'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3313,14 +3352,14 @@ msgstr ""
"Az 'arcriven.z' telepэtѕ fсjl is hasznсlhatѓ. Ezen felќl hasznсlhatѓ mщg a "
"'Riven' Mac indэtѓfсjl."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
"Hiсnyzik az 'extras.mhk'. A telepэtѕ 'arcriven.z' fсjlja is hasznсlhatѓ mщg."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "A kіvetkezѕ szќksщges Riven adatfсjlok hiсnyoznak:\n"
@@ -3665,7 +3704,7 @@ msgstr ""
"ScummVM-ben, ezщrt javasoljuk, tсvolэtsa el ezt a javэtсst a jсtщk "
"mappсjсbѓl, hogy elkerќlje a vсratlan щs / vagy kщsѕbbi hibсkat."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3678,7 +3717,7 @@ msgstr ""
" a kapcsolatot a ScummVM csapatсban щs rщszletesen\n"
" эrd meg a jсtщk nevщt, verziѓjсt , stb...\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3687,11 +3726,11 @@ msgstr ""
"A Putt-Putt Saves the Zoo iOS Lite verziѓja nem tсmogatott.\n"
"A teljes vсltozat elщrhetѕ az iTunes Сruhсzban."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Tсrgynщv sor lсthatѓ"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Tсrgyak neveinek megjelenэtщse a kщpernyѕ aljсn"
@@ -4369,7 +4408,7 @@ msgstr ""
"Native MIDI tсmogatсshoz kell a Roland Upgrade a LucasArts-tѓl,\n"
"a %s hiсnyzik. AdLib-ot hasznсlok helyette."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4452,7 +4491,7 @@ msgstr "Floppy intro"
msgid "Use the floppy version's intro (CD version only)"
msgstr "A floppy verziѓ intro hasznсlata (csak CD verziѓnсl)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4460,7 +4499,7 @@ msgstr ""
"Hibсs verziѓjњ '%s' motor adatfсjlt talсltam. Elvсrt %d helyett ez %d "
"talсlhatѓ."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4584,26 +4623,42 @@ msgstr "Jсtщkсllсs nem menthetѕ %d slotba"
msgid "Could not quick load the saved game #%d"
msgstr "Nem tіrtщnt meg a #%d mentett jсtщk gyors betіltщse"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "FPS szсmlсlѓ lсtszik"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
"A jelenlegi mсsodpercenkщnti kщpkocka szсm kijelzщse a bal felsѕ sarokban"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Sprite bilineсris szћrщs (LASSк)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Bilineсris szћrщs alkalmazсsa egyes sprite-okhoz"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "Hasznсld az eredeti mentщs/tіltщs kщpet a ScummVM felќlet helyett"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr "Elem kіltsщgek megjelenэtщse a szokсsos leltсri mѓdban"
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+"Az elem kіltsщgeket a szokсsos leltсri mѓdban mutatja, lehetѕvщ tщve az elem "
+"щrtщkek іsszehasonlэtсsсt"
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr "Tartѓsabb pсncщl"
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
+msgstr "A pсncщl nem szakad el, karakter -80 HP-nсl, hanem csak -10 HP-nсl"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4638,7 +4693,7 @@ msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr ""
"A DVD verziѓ MPEG videѓjсnak hasznсlata, a kisebb felbontсsњ AVI helyett"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4648,6 +4703,9 @@ msgstr ""
"tсmogat. Szќksщged van a motor frissэtett verziѓjсra, hogy hasznсld a "
"mentett jсtщkсllсst."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr "Hasznсld az eredeti mentщs/tіltщs kщpet a ScummVM felќlet helyett"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr "(Bсrmikor engedщlyezheti a beсllэtсsok ablakban az Egyщb fќlnщl)"
diff --git a/po/it_IT.po b/po/it_IT.po
index bd33fc428c..2ce24628e1 100644
--- a/po/it_IT.po
+++ b/po/it_IT.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2018-03-11 11:12+0000\n"
-"Last-Translator: Jennifer McMurray <mcmurray.jennifer@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-05-30 14:23+0000\n"
+"Last-Translator: Paolo Bossi <pbossi86@gmail.com>\n"
"Language-Team: Italian <https://translations.scummvm.org/projects/scummvm/"
"scummvm/it/>\n"
"Language: it_IT\n"
@@ -57,7 +57,7 @@ msgstr "Su"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Scegli"
msgid "Select directory where to download game data"
msgstr "Seleziona la cartella dove scaricare i file dati del gioco"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Seleziona la cartella con i file dati del gioco"
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Sь"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Sь"
msgid "No"
msgstr "No"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM non ha potuto aprire la cartella specificata!"
@@ -153,8 +153,8 @@ msgstr ""
"stesso nome."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -169,7 +169,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -541,10 +541,10 @@ msgstr ""
"Sei sicuro di voler ripristinare tutte le impostazioni di FluidSynth al loro "
"valore predefinito?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Chiudi"
@@ -593,111 +593,111 @@ msgstr "Premi il tasto da associare"
msgid "Choose an action to map"
msgstr "Scegli un'azione da mappare"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "C~h~iudi"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Esci da ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "~I~nfo..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Informazioni su ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~pzioni..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Modifica le opzioni globali di ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~G~ioca"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Esegue il gioco selezionato"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~C~arica..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Carica un salvataggio del gioco selezionato"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~A~ggiungi gioco..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Tieni premuto Shift per l'aggiunta in massa"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~M~odifica gioco..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Modifica le opzioni di gioco"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~R~imuovi gioco"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Rimuove il gioco dalla lista. I file del gioco rimarranno intatti"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~A~gg. gioco..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~M~odif. gioco..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~R~im. gioco"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Cerca nella lista dei giochi"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Cerca:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Carica gioco:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Carica"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -705,66 +705,66 @@ msgstr ""
"Vuoi davvero eseguire il rilevatore di giochi in massa? Potrebbe aggiungere "
"un numero enorme di giochi."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
"Questa cartella ш in fase di download e non puђ essere ancora utilizzata!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Sei sicuro di voler rimuovere questa configurazione di gioco?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Vuoi caricare il salvataggio?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr ""
"Questo gioco non supporta il caricamento di salvataggi dalla schermata di "
"avvio."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM non ha potuto trovare un motore in grado di eseguire il gioco "
"selezionato!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM non ha potuto trovare nessun gioco nella cartella specificata!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Scegli il gioco:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Agg. in massa..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Registra..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... in corso..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Scansione completata!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "Rilevati %d nuovi giochi, ignorati %d giochi aggiunti in precedenza."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "%d cartelle analizzate..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "Rilevati %d nuovi giochi, ignorati %d giochi aggiunti in precedenza..."
@@ -1603,31 +1603,62 @@ msgstr ""
msgid "Select a Theme"
msgstr "Seleziona un tema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Grafica disattivata"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Grafica disattivata"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Renderer standard"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Normale"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Renderer con antialiasing"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Con antialiasing"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr "Copia negli appunti"
+
+#: gui/unknown-game-dialog.cpp:67
+msgid "Report game"
+msgstr "Segnala gioco"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+"Usa il pulsante sottostante per copiare le informazioni di gioco richieste "
+"negli appunti."
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr "Puoi anche segnalare direttamente il tuo gioco al Bug Tracker."
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+"Tutte le informazioni necessarie sul tuo gioco sono state copiate negli "
+"appunti"
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr "Copia delle informazioni del gioco negli appunti fallita!"
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1651,7 +1682,7 @@ msgstr ""
msgid "Proceed"
msgstr "Procedi"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Cancella"
@@ -1795,24 +1826,6 @@ msgstr "Una volta al mese"
msgid "<Bad value>"
msgstr "<Valore non valido>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Il gioco in '% s' non ш noto. Sembra essere una variante di un gioco che "
-"utilizza il '% s' motore di gioco.\n"
-"\n"
-"Per favore riporta i seguenti dati al team ScummVM a %s insieme al nome del "
-"gioco che hai provato ad aggiungere e alla sua versione, lingua, etc.:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Identificatori di gioco corrispondenti:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~R~ipristina"
@@ -1848,12 +1861,12 @@ msgstr "~V~ai a elenco giochi"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1868,12 +1881,12 @@ msgstr "Salva gioco:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1989,22 +2002,48 @@ msgstr ""
msgid "Start anyway"
msgstr "Avvia comunque"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Il gioco in '%s' sembra essere una variante sconosciuta.\n"
+"\n"
+"Per favore riporta i seguenti dati al team ScummVM a '%s' insieme al nome "
+"del gioco che hai provato ad aggiungere e alla sua versione, lingua, etc.:"
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Identificatori di gioco corrispondenti per il motore %s:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Emulatore AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Emulatore OPL MAME"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Emulatore OPL DOSBox"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Emulatore OPL Nuked"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2797,7 +2836,7 @@ msgstr "Cerca aggiornamenti..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2805,7 +2844,7 @@ msgstr "File dati del motore '%s' non trovato."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2851,6 +2890,7 @@ msgstr "Usa schermate di salvataggio originali"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"Usa le schermate originali di salvataggio e caricamento, al posto di quelle "
@@ -2900,9 +2940,9 @@ msgstr ""
"SCI), anzichщ usare un prompt dei comandi in tempo reale."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2914,9 +2954,9 @@ msgid "Restore game:"
msgstr "Ripristina partita:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2927,7 +2967,7 @@ msgstr "Ripristina partita:"
msgid "Restore"
msgstr "Ripristina"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2949,7 +2989,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2965,11 +3005,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "File della sequenza di intermezzo '%s' non trovato!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Modalitр daltonici"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Abilita di default la modalitр daltonici"
@@ -3263,18 +3303,18 @@ msgstr "Animazioni interfaccia di gioco"
msgid "Naughty game mode"
msgstr "Modalitр osщ"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Riproduci il volo panoramico di Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
"Il filmato del volo panoramico di Myst non veniva riprodotto dal motore "
"originale del gioco."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "Modalitр ~Z~ip attivata"
@@ -3295,27 +3335,27 @@ msgstr "Mostra ~M~appa"
msgid "Main Men~u~"
msgstr "~M~enu principale"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~E~ffetto acqua attivo"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Transizioni:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Disattivato"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "II piљ veloce possibile"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normale"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Migliore"
@@ -3323,7 +3363,7 @@ msgstr "Migliore"
msgid "The game is paused. Press any key to continue."
msgstr "Gioco in pausa. Premi un tasto per continuare."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3331,7 +3371,7 @@ msgstr ""
"File eseguibile di Riven non trovato. L'eseguibile per la versione Windows ш "
"'riven.exe' o 'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3339,7 +3379,7 @@ msgstr ""
"Ш anche possibile usare il file di installazione 'arcriven.z', o "
"l'eseguibile 'Riven' per la versione Mac."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3347,7 +3387,7 @@ msgstr ""
"File 'extras.mhk' non trovato. Ш anche possibile usare il file di "
"installazione 'arcriven.z'."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "I seguenti file di dati di Riven non sono stati trovati:\n"
@@ -3701,7 +3741,7 @@ msgstr ""
"E' pertanto consigliabile rimuoverle dalla cartella del gioco per evitare "
"errori inaspettati in seguito."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3716,7 +3756,7 @@ msgstr ""
"comunica le seguenti informazioni al team di ScummVM, indicando il nome del\n"
"gioco e la versione, lingua, eccetera:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3726,11 +3766,11 @@ msgstr ""
"evitarne la pirateria.\n"
"La versione completa ш disponibile per l'acquisto sull'iTunes Store."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Mostra riga nomi oggetti"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Mostra i nomi degli oggetti nella parte inferiore dello schermo"
@@ -4408,7 +4448,7 @@ msgstr ""
"Il supporto nativo MIDI richiede il Roland Upgrade della LucasArts,\n"
"ma %s non ш presente. Verrр usato AdLib."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4493,7 +4533,7 @@ msgstr "Intro floppy"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Usa la versione floppy dell'intro (solo versione CD)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4501,7 +4541,7 @@ msgstr ""
"Versione del file di dati del motore '%s' non corretta. La versione "
"compatibile ш la %d ma ш stata rilevata la %d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4631,29 +4671,45 @@ msgstr "Caricato salvataggio rapido #%d"
msgid "Could not quick load the saved game #%d"
msgstr "Impossibile caricare il salvataggio rapido #%d"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Mostra contatore FPS"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
"Mostra il numero di frame al secondo nell'angolo in alto a sinistra dello "
"schermo"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Applica filtro bilineare agli sprite (LENTO)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Applica un filtro grafico bilineare ad ogni sprite"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr "Mostra il prezzo degli oggetti nell'inventario in modalitр standard"
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
msgstr ""
-"Usa le schermate originali di salvataggio e caricamento, al posto di quelle "
-"di ScummVM"
+"Mostra il prezzo degli oggetti nell'inventario in modalitр standard, "
+"permettendo cosь di confrontare il valore degli oggetti"
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr "Armatura piљ durevole"
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
+msgstr ""
+"L'armatura non si romperр finchщ il personaggio non raggiungerр -80HP, "
+"anzichщ -10HP"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4689,7 +4745,7 @@ msgstr ""
"Usa i filmati MPEG della versione DVD, anzichщ i filmati AVI a risoluzione "
"inferiore"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4699,6 +4755,11 @@ msgstr ""
"versione %d o inferiori. Procurati una motore aggiornato per usare questo "
"salvataggio."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Usa le schermate originali di salvataggio e caricamento, al posto di "
+#~ "quelle di ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr ""
#~ "(E' possibile attivarla in qualsiasi momento tramite la scheda \"Varie\" "
diff --git a/po/nb_NO.po b/po/nb_NO.po
index 5953a19ef5..3617cd5f96 100644
--- a/po/nb_NO.po
+++ b/po/nb_NO.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2016-12-26 17:36+0000\n"
-"Last-Translator: Einar Johan Trјan Sјmхen <einarjohants@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:01+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Norwegian Bokmхl <https://translations.scummvm.org/projects/"
"scummvm/scummvm/nb_NO/>\n"
"Language: nb_NO\n"
@@ -58,7 +58,7 @@ msgstr "Oppover"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -82,7 +82,7 @@ msgstr "Velg"
msgid "Select directory where to download game data"
msgstr "Velg mappe for nedlasting av spilldata"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Velg mappe med spilldata"
@@ -117,7 +117,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -130,7 +130,7 @@ msgstr "Ja"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -141,7 +141,7 @@ msgstr "Ja"
msgid "No"
msgstr "Nei"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM kunne ikke хpne den valgte mappa!"
@@ -154,8 +154,8 @@ msgstr ""
"samme navn."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -170,7 +170,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -476,7 +476,7 @@ msgstr "Nivх:"
#: gui/fluidsynth-dialog.cpp:101
msgid "Chorus"
-msgstr ""
+msgstr "Chorus"
#: gui/fluidsynth-dialog.cpp:105
msgid "N:"
@@ -540,10 +540,10 @@ msgid ""
msgstr ""
"Vil du virkelig nullstille alle FluidSynth-instillinger til standardverdier?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Lukk"
@@ -592,111 +592,111 @@ msgstr "Trykk tasten som skal kobles"
msgid "Choose an action to map"
msgstr "Velg en handling for kobling"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~A~vslutt"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Avslutt ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "~O~m..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Om ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~V~alg..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Endre globale ScummVM-innstillinger"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~S~tart"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Start valgt spill"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~Х~pne..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Хpne lagret spill for det valgte spillet"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~L~egg til spill..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Hold Shift for х legge til flere"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~R~ediger spill..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Endre spillinstillinger"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~F~jern spill"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Fjern spill fra listen. Spilldataene forblir intakte"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~L~egg til spill..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~R~ediger spill..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~F~jern spill"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Sјk i spilliste"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Sјk:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Хpne spill:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Хpne"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -704,63 +704,63 @@ msgstr ""
"Vil du virkelig kjјre flerspill-finneren? Dette kan potensielt legge til et "
"stort antall spill."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr "Denne mappa kan ikke brukes ennх, den blir lastet ned til!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Vil du virkelig fjerne denne spillkonfigurasjonen?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Vil du laste et lagret spill?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Dette spillet stјtter ikke lasting av spill fra oppstarteren."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM kunne ikke finne noen motor som kunne kjјre det valgte spillet!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM kunne ikke finne noe spill i den valgte mappen!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Velg spill:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Legg til flere..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr ""
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... fremdrift ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Sјk fullfјrt!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr ""
"Fant %d nye spill, ignorerte %d spill som har blitt lagt til tidligere."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Sjekket %d mapper ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1597,31 +1597,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Velg et tema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Deaktivert GFX"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Deaktivert GFX"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standard tegner"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Standard"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Kantutjevnet tegner"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Kantutjevnet"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Gjennopprett spill:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
#, fuzzy
msgid ""
@@ -1644,7 +1672,7 @@ msgstr ""
msgid "Proceed"
msgstr "Fortsett"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Tјm verdi"
@@ -1787,19 +1815,6 @@ msgstr "Mхnedlig"
msgid "<Bad value>"
msgstr "<Ugyldig verdi>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~F~ortsett"
@@ -1835,12 +1850,12 @@ msgstr "~T~ilbake til oppstarter"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1855,12 +1870,12 @@ msgstr "Lagret spill:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1975,22 +1990,44 @@ msgstr ""
msgid "Start anyway"
msgstr "Start allikevel"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
-msgstr "AdLib Emulator"
+msgstr "AdLib emulator"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL emulator"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "DOSBox OPL emulator"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL emulator"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2784,7 +2821,7 @@ msgstr "Sjekk for oppdateringer..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2792,7 +2829,7 @@ msgstr ""
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2836,6 +2873,7 @@ msgstr "Bruk originale lagre/laste-skjermer"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr "Bruk de originale lagre/laste-skjermene, istedenfor ScummVM-variantene"
@@ -2881,9 +2919,9 @@ msgid ""
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2895,9 +2933,9 @@ msgid "Restore game:"
msgstr "Gjennopprett spill:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2908,7 +2946,7 @@ msgstr "Gjennopprett spill:"
msgid "Restore"
msgstr "Gjenopprett"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, fuzzy, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2930,7 +2968,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, fuzzy, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2946,11 +2984,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Fant ikke cutscenefil '%s'!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Fargeblindmodus"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Aktiver fargeblindmodus som standard"
@@ -3252,16 +3290,16 @@ msgstr ""
msgid "Naughty game mode"
msgstr ""
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr ""
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~ipmodus aktivert"
@@ -3283,31 +3321,31 @@ msgstr "Vi~s~ Kart"
msgid "Main Men~u~"
msgstr "Hoved~m~eny"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~V~anneffekt aktivert"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
#, fuzzy
msgid "Transitions:"
msgstr "~O~verganger aktivert"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
#, fuzzy
msgid "Disabled"
msgstr "Deaktivert GFX"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
#, fuzzy
msgid "Fastest"
msgstr "Lim inn"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
#, fuzzy
msgid "Normal"
msgstr "OpenGL Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3315,25 +3353,25 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr "Spillet er satt pх pause. Trykk en tast for х fortsette."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
msgstr ""
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
msgstr ""
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3642,7 +3680,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3651,18 +3689,18 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
"The full version is available for purchase from the iTunes Store."
msgstr ""
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Vis objektlinje"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr ""
@@ -4342,7 +4380,7 @@ msgstr ""
"Ekte MIDI-stјtte krever ЋRoland UpgradeЛ fra LucasArts,\n"
"men %s mangler. Bruker AdLib istedet."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4424,13 +4462,13 @@ msgstr "Diskett-intro"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Bruk diskettversjonens intro (Kun for CD-versjon)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4553,28 +4591,41 @@ msgstr ""
msgid "Could not quick load the saved game #%d"
msgstr "Vil du laste et lagret spill?"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Vis FPS-teller"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
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/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr ""
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr ""
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Bruk de originale lagre/laste-skjermene istedenfor ScummVM-grensesnittet"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4610,13 +4661,17 @@ msgstr ""
"Bruk MPEG-video fra DVD-versjonen istedenfor AVI-versjonen med lavere "
"opplјsning"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
"%d. You will need an updated version of the engine to use this saved game."
msgstr ""
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Bruk de originale lagre/laste-skjermene istedenfor ScummVM-grensesnittet"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr "(Du kan alltids aktivere dette i valgdialogen i Diverse-fanen)"
diff --git a/po/nl_NL.po b/po/nl_NL.po
index a540bf7eb1..5967fb3090 100644
--- a/po/nl_NL.po
+++ b/po/nl_NL.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.9.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2018-03-08 09:03+0000\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-05-30 08:25+0000\n"
"Last-Translator: Ben Castricum <github@bencastricum.nl>\n"
"Language-Team: Dutch <https://translations.scummvm.org/projects/scummvm/"
"scummvm/nl/>\n"
@@ -58,7 +58,7 @@ msgstr "Ga omhoog"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -82,7 +82,7 @@ msgstr "Selecteer"
msgid "Select directory where to download game data"
msgstr "Selecteer map voor de te downloaden speldata"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Selecteer map met speldata"
@@ -115,7 +115,7 @@ msgstr "Uw verbinding lijkt beperkt. Wilt u echt bestanden ermee downloaden?"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -128,7 +128,7 @@ msgstr "Ja"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -139,7 +139,7 @@ msgstr "Ja"
msgid "No"
msgstr "Nee"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM kon de opgegeven map niet openen!"
@@ -152,8 +152,8 @@ msgstr ""
"met dezelfde naam."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -168,7 +168,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -539,10 +539,10 @@ msgstr ""
"Wilt u echt alle FluidSynth instellingen terugzetten naar de standaard "
"waarden?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Sluiten"
@@ -591,111 +591,111 @@ msgstr "Druk op de te associыren toets"
msgid "Choose an action to map"
msgstr "Selecteer een actie om te koppelen"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~S~toppen"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Hiermee verlaat u ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "O~v~er..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Over ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~pties..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Algemene ScummVM opties"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~S~tarten"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Start het geselecteerde spel"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~L~aad Spel..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Laad een eerder opgeslagen spel voor het geselecteerde spel"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "Spel ~T~oevoegen..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Houd Shift ingedrukt voor het toevoegen van grote hoeveelheden spellen"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "Spel ~B~ewerken..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Verander spel opties"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "Spel ~V~erwijderen"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Verwijder dit spel uit de lijst. De spel data bestanden blijven intact"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~T~oevoegen..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~B~ewerken..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~V~erwijderen"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Zoek in lijst met spellen"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Zoeken:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Laad spel:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Laden"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -703,65 +703,65 @@ msgstr ""
"Wilt u echt de bulk spel import draaien? Dit voegt potentieel een groot "
"aantal spellen toe."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr "Deze map kan nog niet gebruikt worden, er wordt al in gedownload!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Wilt u echt deze spelconfiguratie verwijderen?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Wilt u het opgeslagen spel laden?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Dit spel ondersteunt het laden van spelen vanaf het startmenu niet."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM heeft geen engine gevonden die in staat was het geselecteerde spel "
"te spelen!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM kon geen enkel spel vinden in de opgegeven map!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Kies het spel:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Bulk Import..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Opnemen..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... voortgang ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Klaar met zoeken!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr ""
"%d nieuwe spellen ontdekt, %d spellen die al eerder waren toegevoegd "
"genegeerd."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "%d directories doorgezocht ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1596,31 +1596,61 @@ msgstr "URL openen mislukt! Navigeer a.u.b. handmatig naar deze pagina."
msgid "Select a Theme"
msgstr "Selecteer een thema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "GFX uitgeschakeld"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "GFX uitgeschakeld"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standaard Renderer"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Standaard"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Antialiased Renderer"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Antialiased"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr "Kopiыer naar clipboard"
+
+#: gui/unknown-game-dialog.cpp:67
+msgid "Report game"
+msgstr "Rapporteer spel"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+"Gebruik de onderstaande knop om de benodigde spelinformatie naar het "
+"clipboard te kopiыren."
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr "Je kan ook direct je spel in de Bug Tracker rapporteren."
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+"Alle benodigde informatie van jouw spel is naar het clipboard gekopiыerd"
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr "Kopiыren van de spelinformatie naar het clipboard is mislukt!"
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1644,7 +1674,7 @@ msgstr ""
msgid "Proceed"
msgstr "Ga verder"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Veld leegmaken"
@@ -1788,23 +1818,6 @@ msgstr "Maandelijks"
msgid "<Bad value>"
msgstr "<Ongeldige waarde>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Het spel in '%s' lijkt een onbekende spel variant van de %s engine te zijn.\n"
-"Rapporteer a.u.b. de volgende gegevens aan het ScummVM team op %s samen\n"
-"met de naam van het spel die u probeerde toe te voegen en zijn versie, taal, "
-"etc. :"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Matchende game IDs:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~H~ervatten"
@@ -1840,12 +1853,12 @@ msgstr "S~t~artmenu"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1860,12 +1873,12 @@ msgstr "Spel opslaan:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1942,7 +1955,7 @@ msgstr ""
"U lijkt het spel direct van CD the spelen.\n"
"Hiervan is bekend dat dit problemen veroorzaakt.\n"
"Het wordt daarom aangeraden om de data\n"
-"bestanden naar uw harddisk te kopieren.\n"
+"bestanden naar uw harddisk te kopiыren.\n"
"Voor details kijk in de README."
#: engines/engine.cpp:450
@@ -1983,22 +1996,48 @@ msgstr ""
msgid "Start anyway"
msgstr "Evengoed starten"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Het spel in '%s' lijkt een onbekende spel variant te zijn.\n"
+"Rapporteer a.u.b. de volgende gegevens aan het ScummVM team op %s samen\n"
+"met de naam van het spel die u probeerde toe te voegen en zijn versie, taal, "
+"etc. :"
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Matchende game IDs voor de %s engine:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
-msgstr "AdLib Emulator"
+msgstr "AdLib emulator"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL emulator"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "DOSBox OPL emulator"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL emulator"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2793,7 +2832,7 @@ msgstr "Controleren op updates..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2801,7 +2840,7 @@ msgstr "Kon de '%s' engine data file niet vinden."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2847,6 +2886,7 @@ msgstr "Gebruik originele opslaan/laad schermen"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"Gebruik de originele opslaan/laden schermen in plaats van die van ScummVM"
@@ -2897,9 +2937,9 @@ msgstr ""
"van een real-time prompt."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2911,9 +2951,9 @@ msgid "Restore game:"
msgstr "Laad opgeslagen spel:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2924,7 +2964,7 @@ msgstr "Laad opgeslagen spel:"
msgid "Restore"
msgstr "Laad"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2946,7 +2986,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2962,11 +3002,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Cutscene bestand '%s' niet gevonden!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Kleurenblind Modus"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Schakel Kleurenblind modus standaard in"
@@ -3261,16 +3301,16 @@ msgstr "Geanimeerde spel interface"
msgid "Naughty game mode"
msgstr "Ondeugende spelmodus"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Speel de Myst fly by film"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "De Myst fly by file werd niet door de originele engine afgespeeld."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~ip Modus Aangezet"
@@ -3291,27 +3331,27 @@ msgstr "~T~oon Map"
msgid "Main Men~u~"
msgstr "~H~oofdmenu"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~W~ater Effect Aangezet"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "~O~vergangen:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Uitgeschakeld"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Snelst"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normaal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Beste"
@@ -3319,7 +3359,7 @@ msgstr "Beste"
msgid "The game is paused. Press any key to continue."
msgstr "Spel is gepauzeerd. Druk op een toets om verder te gaan."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3327,7 +3367,7 @@ msgstr ""
"Een Riven executable ontbreekt. De Windows executable heet 'riven.exe' of "
"'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3335,7 +3375,7 @@ msgstr ""
"Het installatiebestand 'arcriven.z' werkt ook. U kunt ook de Mac executable "
"'Riven' gebruiken."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3343,7 +3383,7 @@ msgstr ""
"Het bestand 'extras.mhk' ontbreekt. Het installatiebestand 'arcriven.z' kan "
"ook gebruikt worden."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "U mist de volgende vereiste Riven gegevensbestanden:\n"
@@ -3701,7 +3741,7 @@ msgstr ""
"ScummVM, het wordt dus aangeraden de patch te verwijderen uit uw spelfolder "
"om onverwachtse fouten en/of issues later te voorkomen."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3714,7 +3754,7 @@ msgstr ""
"rapporteer a.u.b. de volgende data aan het ScummVM team, samen met naam van "
"het spel die u probeerde toe te voegen, zijn versie, de taal, etc.:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3724,11 +3764,11 @@ msgstr ""
"piraterij te voorkomen.\n"
"De volledige versie is te koop in de iTunes Store."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Toon Object Regel"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Toon de namen van de objecten onderaan het scherm"
@@ -4406,7 +4446,7 @@ msgstr ""
"Voor MIDI support is de Roland Upgrade van Lucasarts vereist,\n"
"maar %s ontbreekt. Er wordt nu AdLib gebruikt."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4489,7 +4529,7 @@ msgstr "Floppy intro"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Gebruik de floppy versie van de intro (alleen voor de CD versie)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
@@ -4497,7 +4537,7 @@ msgstr ""
"Verkeerde versie van de '%s' engine data file gevonden. Verwacht werd %d "
"maar vond %d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4619,27 +4659,43 @@ msgstr "Opgeslagen spel #%d snel geladen"
msgid "Could not quick load the saved game #%d"
msgstr "Snel laden van opgeslagen spel #%d mislukt"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Toon FPS-teller"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "Toon de huidige Frames Per Second teller in de linkerbovenhoek"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Sprite bilineair filteren (langzaam)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Pas bilineair filteren toe op individuele sprites"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr "Toon voorwerp kosten in standaard inventaris mode"
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
msgstr ""
-"Gebruik de originele opslaan/laden schermen, in plaats van die van de "
-"ScummVM interface"
+"Toont kosten van voorwerpen in standaard inventaris mode, om de waarden van "
+"voorwerpen te kunnen vergelijken"
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr "Duurzamere harnas"
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
+msgstr ""
+"Harnas zal niet breken voordat de personage op -80HP staat, in plaats van "
+"slechts -10HP"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4674,7 +4730,7 @@ msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr ""
"Gebruik de MPEG video van de DVD versie in plaats van de lagere resolutie AVI"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4684,6 +4740,11 @@ msgstr ""
"tot versie %d. U heeft een nieuwere versie van deze engine nodig om dit "
"opgeslagen te gebruiken."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Gebruik de originele opslaan/laden schermen, in plaats van die van de "
+#~ "ScummVM interface"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr ""
#~ "(U kunt dit altijd inschakelen in de opties dialoog van de Misc tab)"
diff --git a/po/nn_NO.po b/po/nn_NO.po
index 480e28e18c..6809f00e2c 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.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2016-12-18 18:23+0000\n"
-"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:13+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Norwegian Nynorsk <https://translations.scummvm.org/projects/"
"scummvm/scummvm/nn/>\n"
"Language: nn_NO\n"
@@ -58,7 +58,7 @@ msgstr "Oppover"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -83,13 +83,13 @@ msgstr "Vel"
msgid "Select directory where to download game data"
msgstr "Vel mappe med speldata"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Vel mappe med speldata"
#: gui/downloaddialog.cpp:52 gui/downloaddialog.cpp:264
msgid "From: "
-msgstr ""
+msgstr "Frх: "
#: gui/downloaddialog.cpp:53 gui/downloaddialog.cpp:265
msgid "To: "
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Ja"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Ja"
msgid "No"
msgstr "Nei"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM kunne ikkje хpne den velde mappa!"
@@ -151,8 +151,8 @@ msgid ""
msgstr ""
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -167,7 +167,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -469,7 +469,7 @@ msgstr "Nivх:"
#: gui/fluidsynth-dialog.cpp:101
msgid "Chorus"
-msgstr ""
+msgstr "Chorus"
#: gui/fluidsynth-dialog.cpp:105
msgid "N:"
@@ -533,10 +533,10 @@ msgid ""
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
-#: engines/scumm/help.cpp:166 engines/scumm/help.cpp:192
-#: engines/scumm/help.cpp:210
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Steng"
@@ -585,173 +585,173 @@ msgstr "Trykk tasten du vil kople"
msgid "Choose an action to map"
msgstr "Vel ei handling for kopling"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~A~vslutt"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Avslutt ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "~O~m..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Om ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~V~al..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Endre globale ScummVM-instillingar"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~S~tart"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Start det velde spelet"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~Х~pne..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Хpne eit lagra spel for the velde spelet"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~L~egg til spel..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Hold Shift nede for х legge til fleire"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~R~ediger spel..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Endre spelinstillingar"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~F~jern spel"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Fjern spel frх lista. Speldataene forblir intakte"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~L~egg til spel..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~R~ediger spel..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~F~jern spel"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Sјk i spelliste"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Sјk:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Хpne spel:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Хpne"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
msgstr ""
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Vil du verkeleg fjerne denne spelkonfigurasjonen?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Vil du laste det lagra spelet?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Dette spelet stјttar ikkje хpning av lagra spel frх oppstartaren."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM kunne ikkje finne nokon motor som var i stand til х kјyre det velde "
"spelet!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM kunne ikkje finne noko spel i den velde mappa!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Vel spelet:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Legg til fleire..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr ""
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... fremdrift ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Sјk fullfјrt!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr ""
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Sјkt i %d mappar ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1594,31 +1594,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Vel eit tema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Deaktivert GFX"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Deaktivert GFX"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standardteiknar"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Standard"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Kantutjevna teiknar"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Kantutjevna"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Gjenopprett spel:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1636,7 +1664,7 @@ msgstr ""
msgid "Proceed"
msgstr ""
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Tјm verdi"
@@ -1781,19 +1809,6 @@ msgstr ""
msgid "<Bad value>"
msgstr "Tјm verdi"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~F~ortsett"
@@ -1829,12 +1844,12 @@ msgstr "Tilbake til Oppsta~r~tar"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1849,12 +1864,12 @@ msgstr "Lagra spel:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1967,22 +1982,44 @@ msgstr ""
msgid "Start anyway"
msgstr "Start allikevel"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
-msgstr "AdLib Emulator"
+msgstr "AdLib emulator"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL emulator"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "DOSBox OPL emulator"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL emulator"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2775,7 +2812,7 @@ msgstr "SJх etter oppdateringar..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2783,7 +2820,7 @@ msgstr ""
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2829,6 +2866,7 @@ msgstr "Nytt opprinnelege skjermar for lagring/lasting"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
@@ -2874,9 +2912,9 @@ msgid ""
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2888,9 +2926,9 @@ msgid "Restore game:"
msgstr "Gjenopprett spel:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2901,7 +2939,7 @@ msgstr "Gjenopprett spel:"
msgid "Restore"
msgstr "Gjenopprett"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, fuzzy, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2917,7 +2955,7 @@ msgid ""
"%s"
msgstr "Klarte ikkje lagre speltilstand til fil."
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2930,11 +2968,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr ""
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Fargeblindmodus"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Slх pх fargeblindmodus som standard"
@@ -3218,16 +3256,16 @@ msgstr ""
msgid "Naughty game mode"
msgstr ""
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr ""
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~ipmodus aktivert"
@@ -3250,31 +3288,31 @@ msgstr "~S~yn Kart"
msgid "Main Men~u~"
msgstr "Hoved~m~eny"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~V~anneffekt aktivert"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
#, fuzzy
msgid "Transitions:"
msgstr "~O~vergangar aktivert"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
#, fuzzy
msgid "Disabled"
msgstr "Deaktivert GFX"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
#, fuzzy
msgid "Fastest"
msgstr "Rask modus"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
#, fuzzy
msgid "Normal"
msgstr "OpenGL Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3283,25 +3321,25 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr "Spelet er pausa. Trykk MELLOMROM for х fortsette."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
msgstr ""
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
msgstr ""
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3605,7 +3643,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3614,19 +3652,19 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
"The full version is available for purchase from the iTunes Store."
msgstr ""
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
#, fuzzy
msgid "Show Object Line"
msgstr "Syn objektmerkelappar"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr ""
@@ -4304,7 +4342,7 @@ msgid ""
"but %s is missing. Using AdLib instead."
msgstr ""
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4384,13 +4422,13 @@ msgstr "Diskettintro"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Nytt diskettversjonens хpning (Kun CD-versjon)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4514,28 +4552,40 @@ msgstr ""
msgid "Could not quick load the saved game #%d"
msgstr "Vil du laste det lagra spelet?"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Syn FPS-teller"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
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/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr ""
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr ""
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Nytt opprinnelege skjermar for lagring/lasting istadenfor ScummVM "
-"grensesnittet"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4572,13 +4622,18 @@ msgstr ""
"Nytt MPEG video frх DVD-versjonen, framfor AVI-versjonen med lхgare "
"opplјysning"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
"%d. You will need an updated version of the engine to use this saved game."
msgstr ""
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Nytt opprinnelege skjermar for lagring/lasting istadenfor ScummVM "
+#~ "grensesnittet"
+
#, fuzzy
#~ msgid "Check for updates automatically"
#~ msgstr "SJх etter oppdateringar..."
diff --git a/po/pl_PL.po b/po/pl_PL.po
index a8d9d6c633..28778a9dff 100644
--- a/po/pl_PL.po
+++ b/po/pl_PL.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-01-25 12:49+0000\n"
-"Last-Translator: RafaГ Rzepecki <divided.mind@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:13+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Polish <https://translations.scummvm.org/projects/scummvm/"
"scummvm/pl/>\n"
"Language: pl_PL\n"
@@ -62,7 +62,7 @@ msgstr "W gѓrъ"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -86,7 +86,7 @@ msgstr "Wybierz"
msgid "Select directory where to download game data"
msgstr "Wybierz katalog, do ktѓrego pobrane zostanБ pliki gry"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Wybierz katalog z plikami gry"
@@ -121,7 +121,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -134,7 +134,7 @@ msgstr "Tak"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -145,7 +145,7 @@ msgstr "Tak"
msgid "No"
msgstr "Nie"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM nie moПe otworzyц katalogu!"
@@ -158,8 +158,8 @@ msgstr ""
"jednakowej nazwie."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -174,7 +174,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -542,10 +542,10 @@ msgid ""
msgstr ""
"Na pewno chcesz przywrѓciц domyЖlne wartoЖci wszystkich ustawieё FluidSynth?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Zamknij"
@@ -594,172 +594,172 @@ msgstr "WciЖnij klawisz do przypisania"
msgid "Choose an action to map"
msgstr "Wybierz akcjъ do przypisania"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~Z~akoёcz"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Zakoёcz ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "I~n~formacje..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "KsiБПka ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~pcje..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Zmieё ustawienia ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~S~tart"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Rozpocznij wybranБ grъ"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~W~czytaj..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Wczytaj zapis wybranej gry"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~D~odaj grъ..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Przytrzymaj Shift, by dodawaц zbiorowo"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~E~dytuj grъ..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Zmieё opcje gry"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~U~suё grъ"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Usuwa grъ z listy. Pliki gry pozostajБ nietkniъte"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~D~odaj grъ..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~E~dytuj grъ..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~U~suё grъ"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Wyszukaj grъ na liЖcie"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Szukaj:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Wczytaj grъ:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Wczytaj"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
msgstr ""
"Chcesz uruchomiц masowy detektor gier? MoПe dodaц wiele tytuГѓw do listy."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr "Z tego katalogu nie moПna jeszcze korzystaц, trwa pobieranie!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Na pewno chcesz usunБц tъ grъ z konfiguracji?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Chcesz wczytaц zapis stanu gry?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Ta gra nie wspiera wczytywania z launchera."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr "ScummVM nie znalazГ silnika zdolnego uruchomiц wybranБ grъ!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM nie znalazГ Пadnej gry w tym katalogu!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Wybierz grъ:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Przeszukaj..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Nagraj..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... postъp ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Skanowanie zakoёczone!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "Wykryto %d nowБ grъ, zignorowano %d poprzednio dodanych."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Przeskanowano %d katalog..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "Wykryto %d nowБ grъ, zignorowano %d poprzednio dodanych..."
@@ -1599,31 +1599,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Wybierz styl"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "WyГБczona grafika"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "WyГБczona grafika"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standardowy renderer"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Standardowy"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "WygГadzany renderer"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "WygГadzany"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Wznѓw grъ:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
#, fuzzy
msgid ""
@@ -1646,7 +1674,7 @@ msgstr ""
msgid "Proceed"
msgstr "Kontynuuj"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "WyczyЖц"
@@ -1790,22 +1818,6 @@ msgstr "Co miesiБc"
msgid "<Bad value>"
msgstr "<NieprawidГowa wartoЖц>"
-#: engines/advancedDetector.cpp:330
-#, fuzzy, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Nie udaГo siъ rozpoznaц gry w \"%s\".\n"
-"Proszъ wysГaц poniПsze informacje do zespoГu ScummVM, razem z\n"
-"nazwБ gry, ktѓrБ prѓbowano dodaц i jej numerem wersji i wersjБ jъzykowБ:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~W~znѓw"
@@ -1841,12 +1853,12 @@ msgstr "~P~owrѓt do launchera"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1861,12 +1873,12 @@ msgstr "Zapis:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1977,22 +1989,47 @@ msgstr ""
msgid "Start anyway"
msgstr "WГБcz mimo tego"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Nie udaГo siъ rozpoznaц gry w \"%s\".\n"
+"Proszъ wysГaц poniПsze informacje do zespoГu ScummVM, razem z\n"
+"nazwБ gry, ktѓrБ prѓbowano dodaц i jej numerem wersji i wersjБ jъzykowБ:"
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Emulator AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Emulator OPL MAME"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Emulator OPL DOSBox"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Emulator OPL Nuked"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "BezpoЖrednie FM Alsa"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2785,7 +2822,7 @@ msgstr "SprawdМ aktualizacjъ..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2793,7 +2830,7 @@ msgstr ""
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2839,6 +2876,7 @@ msgstr "UПyj oryginalnych ekranѓw odczytu/zapisu"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr "UПyj oryginalnych ekranѓw odczytu/zapisu zamiast tych ze ScummVM"
@@ -2886,9 +2924,9 @@ msgid ""
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2900,9 +2938,9 @@ msgid "Restore game:"
msgstr "Wznѓw grъ:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2913,7 +2951,7 @@ msgstr "Wznѓw grъ:"
msgid "Restore"
msgstr "Wznѓw"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, fuzzy, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2935,7 +2973,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, fuzzy, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2951,11 +2989,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Nie znaleziono pliku przerywnika '%s'!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Tryb dla daltonistѓw"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "DomyЖlnie wГБcz tryb dla daltonistѓw"
@@ -3255,16 +3293,16 @@ msgstr ""
msgid "Naughty game mode"
msgstr ""
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr ""
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~T~ryb turbo aktywny"
@@ -3287,31 +3325,31 @@ msgstr "~P~okaП mapъ"
msgid "Main Men~u~"
msgstr "~M~enu gГѓwne"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~E~fekty wody wГБczone"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
#, fuzzy
msgid "Transitions:"
msgstr "~P~rzejЖcia wГБczone"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
#, fuzzy
msgid "Disabled"
msgstr "WyГБczona grafika"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
#, fuzzy
msgid "Fastest"
msgstr "Wklej"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
#, fuzzy
msgid "Normal"
msgstr "OpenGL (normalny)"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3320,25 +3358,25 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr "Gra wstrzymana. NaciЖnij spacjъ, aby wznowiц."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
msgstr ""
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
msgstr ""
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3650,7 +3688,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3659,19 +3697,19 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
"The full version is available for purchase from the iTunes Store."
msgstr ""
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
#, fuzzy
msgid "Show Object Line"
msgstr "PokaП etykiety obiektѓw"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr ""
@@ -4351,7 +4389,7 @@ msgstr ""
"Natywne wsparcie MIDI wymaga aktualizacji Rolanda od LucasArts,\n"
"ale brakuje %s. PrzeГБczam na tryb AdLib."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4433,13 +4471,13 @@ msgstr "Intro z wersji dyskietkowej"
msgid "Use the floppy version's intro (CD version only)"
msgstr "UПyj intra z wersji dyskietkowej (tylko dla wersji CD)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4570,25 +4608,39 @@ msgstr ""
msgid "Could not quick load the saved game #%d"
msgstr "Chcesz wczytaц zapis stanu gry?"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "PokaП licznik klatek na sekundъ"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "WyЖwietl aktualnБ liczbъ klatek na sekundъ w lewym, gѓrnym logu"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr ""
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr ""
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "UПyj oryginalnych ekranѓw odczytu/zapisu zamiast interfejsu ScummVM"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
+msgstr ""
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4623,13 +4675,16 @@ msgstr "UПyj wideo MPEG w wysokiej rozdzielczoЖci"
msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr "UПyj wideo MPEG z wersji DVD zamiast AVI niПszej rozdzielczoЖci"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
"%d. You will need an updated version of the engine to use this saved game."
msgstr ""
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr "UПyj oryginalnych ekranѓw odczytu/zapisu zamiast interfejsu ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr "(MoПna jБ wГБczyц pѓМniej w opcjach, w zakГadce \"RѓПne\".)"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index ee08201bc0..fed78a51f8 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.3.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-03-03 22:26+0000\n"
-"Last-Translator: rafaelmessias <rmmartins@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:13+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Portuguese (Brazil) <https://translations.scummvm.org/"
"projects/scummvm/scummvm/pt_BR/>\n"
"Language: pt_BR\n"
@@ -60,7 +60,7 @@ msgstr "Acima"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -84,7 +84,7 @@ msgstr "Escolher"
msgid "Select directory where to download game data"
msgstr "Selecione a pasta para baixar os arquivos do jogo"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Selecione a pasta com os arquivos do jogo"
@@ -118,7 +118,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -131,7 +131,7 @@ msgstr "Sim"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -142,7 +142,7 @@ msgstr "Sim"
msgid "No"
msgstr "Nуo"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM nуo conseguiu abrir a pasta especificada!"
@@ -155,8 +155,8 @@ msgstr ""
"arquivo com o mesmo nome."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -171,7 +171,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -476,7 +476,7 @@ msgstr ""
#: gui/fluidsynth-dialog.cpp:101
msgid "Chorus"
-msgstr ""
+msgstr "Chorus"
#: gui/fluidsynth-dialog.cpp:105
msgid "N:"
@@ -509,7 +509,7 @@ msgstr "Outros"
#: gui/fluidsynth-dialog.cpp:141
msgid "Interpolation:"
-msgstr ""
+msgstr "Interpolaчуo:"
#: gui/fluidsynth-dialog.cpp:144
msgid "None (fastest)"
@@ -541,10 +541,10 @@ msgid ""
"Do you really want to reset all FluidSynth settings to their default values?"
msgstr "Vocъ realmente deseja voltar para o menu principal?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Fechar"
@@ -594,112 +594,112 @@ msgstr "Pressione a tecla para associar"
msgid "Choose an action to map"
msgstr "Selecione uma aчуo para mapear"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~S~air"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Sair do ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "So~b~re..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Sobre o ScumnmVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~pчѕes..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Alterar opчѕes globais do ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~I~niciar"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Iniciar jogo selecionado"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~C~arregar..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Carregar jogo salvo do jogo selecionado"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~A~dicionar Jogo..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Segure Shift para Multi-Adiчуo"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~E~ditar Jogo..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Alterar opчѕes do jogo"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~R~emover Jogo"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr ""
"Remover jogo da lista. Os arquivos de dados do jogo permanecem intactos"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~A~dicionar Jogo..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~E~ditar Jogo..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~R~emover Jogo"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Pesquisar na lista de jogos"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Pesquisar:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Carregar jogo:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Carregar"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -707,66 +707,66 @@ msgstr ""
"Vocъ realmente deseja adicionar vсrios jogos ao mesmo tempo? Isso poderс "
"resultar em uma adiчуo gigantesca de jogos."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Vocъ deseja realmente remover a configuraчуo deste jogo?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
#, fuzzy
msgid "Do you want to load saved game?"
msgstr "Vocъ deseja carregar ou salvar o jogo?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Este jogo nуo suporta abrir jogos a partir do menu principal."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM nуo conseguiu encontrar qualquer programa capaz de rodar o jogo "
"selecionado!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM nуo encontrou nenhum jogo na pasta especificada!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Escolha o jogo:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Multi-Adiчуo..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr ""
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... progresso ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Busca completa!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr ""
"Encontrado(s) %d novo(s) jogo(s, ignorados %d previamente adicionados "
"jogos..."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "%d pasta(s) pesquisada(s) ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1625,35 +1625,63 @@ msgstr ""
msgid "Select a Theme"
msgstr "Selecione um Tema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "GFX desabilitado"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "GFX desabilitado"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
#, fuzzy
msgid "Standard Renderer"
msgstr "Renderizador padrуo (16bpp)"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
#, fuzzy
msgid "Standard"
msgstr "Padrуo (16bpp)"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
#, fuzzy
msgid "Antialiased Renderer"
msgstr "Renderizador Anti-Serrilhamento (16bpp)"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
#, fuzzy
msgid "Antialiased"
msgstr "Anti-Serrilhamento (16bpp)"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Restaurar jogo:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1671,7 +1699,7 @@ msgstr ""
msgid "Proceed"
msgstr ""
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Limpar valor"
@@ -1818,19 +1846,6 @@ msgstr ""
msgid "<Bad value>"
msgstr "Limpar valor"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~V~oltar ao jogo"
@@ -1866,12 +1881,12 @@ msgstr "~V~oltar ao menu"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1886,12 +1901,12 @@ msgstr "Salvar jogo:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -2009,22 +2024,44 @@ msgstr ""
msgid "Start anyway"
msgstr "Iniciar de qualquer maneira"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Emulador AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Emulador MAME OPL"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Emulador DOSBox OPL"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Emulador Nuked OPL"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr ""
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2827,7 +2864,7 @@ msgstr "Procurar por Atualizaчѕes..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2835,7 +2872,7 @@ msgstr ""
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2879,6 +2916,7 @@ msgstr ""
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
@@ -2921,9 +2959,9 @@ msgid ""
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2935,9 +2973,9 @@ msgid "Restore game:"
msgstr "Restaurar jogo:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2948,7 +2986,7 @@ msgstr "Restaurar jogo:"
msgid "Restore"
msgstr "Restaurar"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, fuzzy, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2970,7 +3008,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, fuzzy, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2986,11 +3024,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Arquivo de vэdeo '%s' nуo encontrado!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr ""
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr ""
@@ -3296,16 +3334,16 @@ msgstr ""
msgid "Naughty game mode"
msgstr ""
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr ""
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "Modo ~Z~ip ativado"
@@ -3328,31 +3366,31 @@ msgstr "~E~xibir Mapa"
msgid "Main Men~u~"
msgstr "~M~enu Principal ScummVM"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "Modo ~E~feitos de сgua ativado"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
#, fuzzy
msgid "Transitions:"
msgstr "Modo ~T~ransiчѕes ativado"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
#, fuzzy
msgid "Disabled"
msgstr "GFX desabilitado"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
#, fuzzy
msgid "Fastest"
msgstr "Modo rсpido"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
#, fuzzy
msgid "Normal"
msgstr "OpenGL Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3361,25 +3399,25 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr "Jogo pausado. Pressione ESPAЧO para continuar."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
msgstr ""
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
msgstr ""
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3688,7 +3726,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3697,18 +3735,18 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
"The full version is available for purchase from the iTunes Store."
msgstr ""
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr ""
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr ""
@@ -4394,7 +4432,7 @@ msgstr ""
"LucasArts,\n"
"mas %s estс faltando. Utilizando AdLib ao invщs."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
#, fuzzy
msgid ""
"Usually, Maniac Mansion would start now. But for that to work, the game "
@@ -4473,13 +4511,13 @@ msgstr ""
msgid "Use the floppy version's intro (CD version only)"
msgstr ""
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4608,24 +4646,38 @@ msgstr ""
msgid "Could not quick load the saved game #%d"
msgstr "Vocъ deseja carregar ou salvar o jogo?"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr ""
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr ""
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr ""
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
#: engines/zvision/detection_tables.h:61
@@ -4662,7 +4714,7 @@ msgstr "Usar vэdeos MPEG de alta resoluчуo"
msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr "Usar vэdeo MPEG da versуo em DVD em vez do AVi de resoluчуo mais baixa"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
diff --git a/po/pt_PT.po b/po/pt_PT.po
index a225dc93a1..f0c03bce9c 100644
--- a/po/pt_PT.po
+++ b/po/pt_PT.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.10.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-01-30 14:50+0000\n"
-"Last-Translator: Vitor Santos <vitorhgsantos90@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 14:10+0000\n"
+"Last-Translator: Fred Almeida <fred_pj@hotmail.com>\n"
"Language-Team: Portuguese (Portugal) <https://translations.scummvm.org/"
"projects/scummvm/scummvm/pt_PT/>\n"
"Language: pt_PT\n"
@@ -57,7 +57,7 @@ msgstr "Acima"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Escolher"
msgid "Select directory where to download game data"
msgstr "Seleccione a directoria de descarga dos arquivos do jogo"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Seleccione a directoria com os arquivos do jogo"
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Sim"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Sim"
msgid "No"
msgstr "Nуo"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM nуo conseguiu abrir a directoria especificada!"
@@ -153,8 +153,8 @@ msgstr ""
"especificada possui um arquivo com o mesmo nome."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -169,7 +169,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -543,10 +543,10 @@ msgstr ""
"Deseja mesmo restaurar todas as configuraчѕes FluidSynth para os valores de "
"origem?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Fechar"
@@ -595,112 +595,112 @@ msgstr "Pressione a tecla para associar"
msgid "Choose an action to map"
msgstr "Escolha uma acчуo para definir"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~S~air"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Sair do ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "So~b~re..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Sobre o ScumnmVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~pчѕes..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Alterar opчѕes gerais do ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~I~niciar"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Iniciar jogo seleccionado"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~C~arregar..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Carregar jogo salvo do jogo selecionado"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~A~dicionar Jogo..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Pressionar Shift para Adiчуo em Massa"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~E~ditar Jogo..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Alterar opчѕes do jogo"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~R~emover Jogo"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr ""
"Remover jogo da lista. Os ficheiros de dados do jogo permanecem intactos"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~A~dicionar Jogo..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~E~ditar Jogo..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~R~emover Jogo"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Pesquisar na lista de jogos"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Pesquisar:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Carregar jogo:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Carregar"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -708,68 +708,68 @@ msgstr ""
"Deseja mesmo executar o detector de adiчуo em massa? Tal poderс, "
"potencialmente, adicionar um elevado nњmero de jogos."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
"De momento, esta directoria nуo pode ser utilizada, existe uma descarga em "
"curso!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Deseja mesmo remover a configuraчуo deste jogo?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Deseja carregar o jogo salvo?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Este jogo nуo permite carregar jogos a partir do menu principal."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"O ScummVM nуo conseguiu encontrar nenhum motor de jogo capaz de correr o "
"jogo seleccionado!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr ""
"O ScummVM nуo conseguiu encontrar nenhum jogo na directoria especificada!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Escolha o jogo:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Adiчуo em Massa..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Gravar..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... progressуo ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Busca completa!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr ""
"Encontrado(s) %d novo(s) jogo(s), ignorado(s) %d jogo(s) adicionado(s) "
"anteriormente."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Pesquisada(s) %d directoria(s) ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -980,7 +980,7 @@ msgstr ""
#: gui/options.cpp:1109
msgid "SoundFont:"
-msgstr ""
+msgstr "SoundFont:"
#: gui/options.cpp:1109 gui/options.cpp:1111 gui/options.cpp:1112
msgid "SoundFont is supported by some audio cards, FluidSynth and Timidity"
@@ -989,11 +989,11 @@ msgstr ""
#: gui/options.cpp:1111
msgctxt "lowres"
msgid "SoundFont:"
-msgstr ""
+msgstr "SoundFont:"
#: gui/options.cpp:1117
msgid "Mixed AdLib/MIDI mode"
-msgstr ""
+msgstr "Modo misturado AdLib/MIDI"
#: gui/options.cpp:1117
msgid "Use both MIDI and AdLib sound generation"
@@ -1046,7 +1046,7 @@ msgstr ""
#: gui/options.cpp:1180 gui/options.cpp:1190
msgid "Speech"
-msgstr ""
+msgstr "Diсlogo"
#: gui/options.cpp:1181 gui/options.cpp:1191
msgid "Subtitles"
@@ -1593,31 +1593,58 @@ msgstr ""
msgid "Select a Theme"
msgstr ""
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr ""
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr ""
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr ""
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr ""
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr ""
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr ""
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+msgid "Report game"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1635,7 +1662,7 @@ msgstr ""
msgid "Proceed"
msgstr ""
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr ""
@@ -1778,19 +1805,6 @@ msgstr ""
msgid "<Bad value>"
msgstr ""
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr ""
@@ -1826,12 +1840,12 @@ msgstr ""
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1846,12 +1860,12 @@ msgstr ""
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1946,22 +1960,44 @@ msgstr ""
msgid "Start anyway"
msgstr ""
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr ""
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr ""
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr ""
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr ""
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr ""
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr ""
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2738,7 +2774,7 @@ msgstr ""
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2746,7 +2782,7 @@ msgstr ""
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2790,6 +2826,7 @@ msgstr ""
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
@@ -2831,9 +2868,9 @@ msgid ""
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2845,9 +2882,9 @@ msgid "Restore game:"
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2858,7 +2895,7 @@ msgstr ""
msgid "Restore"
msgstr ""
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2874,7 +2911,7 @@ msgid ""
"%s"
msgstr ""
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2887,11 +2924,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr ""
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr ""
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr ""
@@ -3161,16 +3198,16 @@ msgstr ""
msgid "Naughty game mode"
msgstr ""
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr ""
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr ""
@@ -3191,27 +3228,27 @@ msgstr ""
msgid "Main Men~u~"
msgstr ""
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr ""
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr ""
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr ""
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr ""
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr ""
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3219,25 +3256,25 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr ""
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
msgstr ""
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
msgstr ""
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3525,7 +3562,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3534,18 +3571,18 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
"The full version is available for purchase from the iTunes Store."
msgstr ""
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr ""
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr ""
@@ -4221,7 +4258,7 @@ msgid ""
"but %s is missing. Using AdLib instead."
msgstr ""
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4294,13 +4331,13 @@ msgstr ""
msgid "Use the floppy version's intro (CD version only)"
msgstr ""
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4407,24 +4444,38 @@ msgstr ""
msgid "Could not quick load the saved game #%d"
msgstr ""
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr ""
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr ""
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr ""
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
#: engines/zvision/detection_tables.h:61
@@ -4459,7 +4510,7 @@ msgstr ""
msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr ""
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
diff --git a/po/ru_RU.po b/po/ru_RU.po
index 6d73a593fc..3af5e2721d 100644
--- a/po/ru_RU.po
+++ b/po/ru_RU.po
@@ -6,9 +6,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.8.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-11-28 17:59+0300\n"
-"Last-Translator: Ivan Lukyanov <greencis@mail.ru>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:17+0000\n"
+"Last-Translator: Adrian Fruehwirth <bonki@scummvm.org>\n"
"Language-Team: Russian <https://translations.scummvm.org/projects/scummvm/"
"scummvm/ru/>\n"
"Language: ru_RU\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 2.0.4\n"
+"X-Generator: Weblate 2.9\n"
"X-Language-name: Russian\n"
#: gui/about.cpp:94
@@ -57,7 +57,7 @@ msgstr "Вверх"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -81,7 +81,7 @@ msgstr "Выбрать"
msgid "Select directory where to download game data"
msgstr "Выберите директорию для скачивания данных игры"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Выберите директорию с файлами игры"
@@ -116,7 +116,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -129,7 +129,7 @@ msgstr "Да"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -140,7 +140,7 @@ msgstr "Да"
msgid "No"
msgstr "Нет"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM не может открыть указанную директорию!"
@@ -153,8 +153,8 @@ msgstr ""
"содержит файл с таким же именем."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -169,7 +169,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -540,10 +540,10 @@ msgstr ""
"Вы действительно хотите сбросить все установки FluidSynth в значения по "
"умолчанию?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Закрыть"
@@ -592,111 +592,111 @@ msgstr "Нажмите клавишу для назначения"
msgid "Choose an action to map"
msgstr "Выберите действие для назначения"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~В~ыход"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Завершить ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "О п~р~ограмме..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "О программе ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~Н~астройки..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Изменить глобальные настройки ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "П~у~ск"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Запустить выбранную игру"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~З~агрузить..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Загрузить сохранение для выбранной игры"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~Д~обавить игру..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Удерживайте клавишу Shift, чтобы добавить несколько игр"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "Н~а~стройки игры..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Изменить настройки игры"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~У~далить игру"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Удалить игру из списка. Не удаляет игру с носителя"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~Д~об. игру..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "Н~а~с. игры..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~У~далить игру"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Поиск в списке игр"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Поиск:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Загрузить игру:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Загрузить"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -704,63 +704,63 @@ msgstr ""
"Вы действительно хотите запустить детектор всех игр? Это потенциально может "
"добавить большое количество игр."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
"Эта директория пока не может быть использована. В неё сейчас загружаются "
"данные!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Вы действительно хотите удалить настройки для этой игры?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Вы хотите загрузить игру?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Эта игра не поддерживает загрузку сохранений через главное меню."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr "ScummVM не может найти движок для запуска выбранной игры!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM не может найти игру в указанной директории!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Выберите игру:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Много игр..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Запись..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... ищу ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Поиск закончен!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "Найдено %d новых игр, пропущено %d ранее добавленных игр."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Просмотрено %d директорий ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "Найдено %d новых игр, пропущено %d ранее добавленных игр ..."
@@ -1597,31 +1597,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Выберите тему"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Без графики"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Без графики"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Стандартный растеризатор"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Стандартный"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Растеризатор со сглаживанием"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Со сглаживанием"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Восстановить игру:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1644,7 +1672,7 @@ msgstr ""
msgid "Proceed"
msgstr "Продолжить"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Очистить значение"
@@ -1787,23 +1815,6 @@ msgstr "Ежемесячно"
msgid "<Bad value>"
msgstr "<Неправильное значение>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Похоже, что игра в '%s' является неизвестной игрой на движке %s.\n"
-"\n"
-"Пожалуйста, сообщите команде ScummVM на %s следующие данные вместе с "
-"названием игры, её версией, языком и др.:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Возможные ID игры:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "Продол~ж~ить"
@@ -1839,12 +1850,12 @@ msgstr "~В~ главное меню"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1859,12 +1870,12 @@ msgstr "Сохранить игру:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1980,22 +1991,48 @@ msgstr ""
msgid "Start anyway"
msgstr "Всё равно запустить"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Похоже, что игра в '%s' является неизвестной игрой на движке %s.\n"
+"\n"
+"Пожалуйста, сообщите команде ScummVM на %s следующие данные вместе с "
+"названием игры, её версией, языком и др.:"
+
+#: engines/game.cpp:162
+#, fuzzy, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Возможные ID игры:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Эмулятор AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Эмулятор MAME OPL"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Эмулятор DOSBox OPL"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Эмулятор Nuked OPL"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "Прямой FM ALSA"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2789,7 +2826,7 @@ msgstr "Проверить обновления..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2797,7 +2834,7 @@ msgstr "Не удалось найти файл движка %s."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2841,6 +2878,7 @@ msgstr "Использовать оригинальные экраны записи/чтения игры"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"Использовать оригинальные экраны чтения и сохранения игры вместо сделанных в "
@@ -2890,9 +2928,9 @@ msgstr ""
"вместо ввода в реальном времени."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2904,9 +2942,9 @@ msgid "Restore game:"
msgstr "Восстановить игру:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2917,7 +2955,7 @@ msgstr "Восстановить игру:"
msgid "Restore"
msgstr "Восстановить"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2939,7 +2977,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2955,11 +2993,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Файл заставки '%s' не найден!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Режим без цвета"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Включить режим для людей со слабым восприятием цвета"
@@ -3256,16 +3294,16 @@ msgstr "Анимированный интерфейс игры"
msgid "Naughty game mode"
msgstr "Откровенный режим игры"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Проигрывать ролик пролёта над Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "Ролик пролёта над Myst не проигрывался оригинальным движком."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Р~ежим быстрого перехода активирован"
@@ -3286,27 +3324,27 @@ msgstr "Показать ~к~арту"
msgid "Main Men~u~"
msgstr "Главное мен~ю~"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~Э~ффекты воды включены"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "Переходы:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Выключены"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Быстрые"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Обычные"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Лучшие"
@@ -3314,7 +3352,7 @@ msgstr "Лучшие"
msgid "The game is paused. Press any key to continue."
msgstr "Игра приостановлена. Для продолжения нажмите любую кнопку."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3322,7 +3360,7 @@ msgstr ""
"Не хватает исполняемого файла Riven. Windows-файл называется 'riven.exe' "
"либо 'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3330,7 +3368,7 @@ msgstr ""
"Вместо него подойдёт файл установщика 'arcriven.z'. Также можно использовать "
"исполняемый файл 'Riven' для Mac."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3338,7 +3376,7 @@ msgstr ""
"Не хватает файла 'extras.mhk'. Вместо него можно использовать файл 'arcriven."
"z'."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "Не хватает следующих файлов игры Riven:\n"
@@ -3687,7 +3725,7 @@ msgstr ""
"ошибки в ScummVM не возникают, поэтому рекомендуется удалить их из папки с "
"игрой, чтобы предотвратить непредвиденные проблемы в дальнейшем."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3700,7 +3738,7 @@ msgstr ""
"переводом), пожалуйста, сообщите команде ScummVM следующие\n"
"данные вместе с именем игры, её версией, языком и т. д.:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3709,11 +3747,11 @@ msgstr ""
"Во избежание пиратства Lite-версия игры Putt-Putt Saves the Zoo для iOS\n"
"не поддерживается. Полную версию игры можно купить в iTunes Store."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Показывать строку объектов"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Показывать названия объектов внизу экрана"
@@ -4391,7 +4429,7 @@ msgstr ""
"Режим \"родного\" MIDI требует обновление Roland Upgrade от\n"
"LucasArts, но не хватает %s. Переключаюсь на AdLib."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4473,13 +4511,13 @@ msgstr "Вступление с дискет"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Использовать вступление с гибких дисков (только для CD-версии игры)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, fuzzy, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr "Неверная версия файла движка %s. Ожидается %d.%d, а найдена %d.%d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, fuzzy, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr "Не удалось найти файл движка %s."
@@ -4603,27 +4641,39 @@ msgstr "Сохранённая игра №%d загружена"
msgid "Could not quick load the saved game #%d"
msgstr "Не удалось быстро загрузить сохранённую игру №%d"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Показать счётчик кадров в секунду"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "Показать в верхнем левом углу текущее количество кадров в секунду"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Билинейная фильтрация спрайтов (медленно)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Применить билинейную фильтрацию для индивидуальных спрайтов"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Использовать оригинальные экраны записи и сохранения игры вместо сделанных в "
-"ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4659,7 +4709,7 @@ msgstr ""
"Использовать MPEG-видео из DVD-версии вместо видео низкого разрешения в "
"формате AVI"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4669,6 +4719,11 @@ msgstr ""
"версии не выше %d. Для использования этого файла необходима свежая версия "
"движка."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Использовать оригинальные экраны записи и сохранения игры вместо "
+#~ "сделанных в ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr "(Вы всегда можете включить её в настройках на закладке \"Разное\")"
diff --git a/po/scummvm.pot b/po/scummvm.pot
index 40cc87d4bf..558b73e395 100644
--- a/po/scummvm.pot
+++ b/po/scummvm.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 2.1.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\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"
@@ -54,7 +54,7 @@ msgstr ""
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -78,7 +78,7 @@ msgstr ""
msgid "Select directory where to download game data"
msgstr ""
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr ""
@@ -111,7 +111,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -124,7 +124,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -135,7 +135,7 @@ msgstr ""
msgid "No"
msgstr ""
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr ""
@@ -146,8 +146,8 @@ msgid ""
msgstr ""
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -162,7 +162,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr ""
@@ -523,10 +523,10 @@ msgid ""
"Do you really want to reset all FluidSynth settings to their default values?"
msgstr ""
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 ""
@@ -575,171 +575,171 @@ msgstr ""
msgid "Choose an action to map"
msgstr ""
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr ""
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr ""
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr ""
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr ""
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr ""
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr ""
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr ""
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr ""
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr ""
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr ""
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr ""
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr ""
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr ""
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr ""
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr ""
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr ""
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr ""
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr ""
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr ""
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr ""
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr ""
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr ""
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr ""
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
msgstr ""
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr ""
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr ""
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr ""
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr ""
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr ""
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr ""
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr ""
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr ""
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr ""
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr ""
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr ""
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr ""
@@ -1558,31 +1558,58 @@ msgstr ""
msgid "Select a Theme"
msgstr ""
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr ""
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr ""
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr ""
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr ""
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr ""
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr ""
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+msgid "Report game"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1600,7 +1627,7 @@ msgstr ""
msgid "Proceed"
msgstr ""
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr ""
@@ -1743,19 +1770,6 @@ msgstr ""
msgid "<Bad value>"
msgstr ""
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr ""
@@ -1791,12 +1805,12 @@ msgstr ""
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1811,12 +1825,12 @@ msgstr ""
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1911,22 +1925,44 @@ msgstr ""
msgid "Start anyway"
msgstr ""
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr ""
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr ""
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr ""
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr ""
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr ""
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr ""
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2703,7 +2739,7 @@ msgstr ""
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2711,7 +2747,7 @@ msgstr ""
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2755,6 +2791,7 @@ msgstr ""
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
@@ -2796,9 +2833,9 @@ msgid ""
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2810,9 +2847,9 @@ msgid "Restore game:"
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2823,7 +2860,7 @@ msgstr ""
msgid "Restore"
msgstr ""
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2839,7 +2876,7 @@ msgid ""
"%s"
msgstr ""
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2852,11 +2889,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr ""
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr ""
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr ""
@@ -3126,16 +3163,16 @@ msgstr ""
msgid "Naughty game mode"
msgstr ""
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr ""
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr ""
@@ -3156,27 +3193,27 @@ msgstr ""
msgid "Main Men~u~"
msgstr ""
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr ""
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr ""
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr ""
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr ""
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr ""
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3184,25 +3221,25 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr ""
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
msgstr ""
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
msgstr ""
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3489,7 +3526,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3498,18 +3535,18 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
"The full version is available for purchase from the iTunes Store."
msgstr ""
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr ""
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr ""
@@ -4185,7 +4222,7 @@ msgid ""
"but %s is missing. Using AdLib instead."
msgstr ""
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4258,13 +4295,13 @@ msgstr ""
msgid "Use the floppy version's intro (CD version only)"
msgstr ""
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4371,24 +4408,38 @@ msgstr ""
msgid "Could not quick load the saved game #%d"
msgstr ""
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr ""
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr ""
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr ""
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr ""
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
#: engines/zvision/detection_tables.h:61
@@ -4423,7 +4474,7 @@ msgstr ""
msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr ""
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
diff --git a/po/sv_SE.po b/po/sv_SE.po
index aba205bd83..9cefb4899a 100644
--- a/po/sv_SE.po
+++ b/po/sv_SE.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.5.0svn\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-12-01 10:54+0000\n"
-"Last-Translator: hampusf <hampus.flink@gmail.com>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-14 20:40+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Swedish <https://translations.scummvm.org/projects/scummvm/"
"scummvm/sv/>\n"
"Language: sv_SE\n"
@@ -58,7 +58,7 @@ msgstr "Uppхt"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -82,7 +82,7 @@ msgstr "Vфlj"
msgid "Select directory where to download game data"
msgstr "Vфlj katalogen dфr du vill ladda ner speldata"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Vфlj katalog med speldata"
@@ -117,7 +117,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -130,7 +130,7 @@ msgstr "Ja"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -141,7 +141,7 @@ msgstr "Ja"
msgid "No"
msgstr "Nej"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM kunde inte іppna den valda katalogen!"
@@ -154,8 +154,8 @@ msgstr ""
"fil med samma namn."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -170,7 +170,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -186,7 +186,7 @@ msgstr ""
#: gui/downloaddialog.cpp:252
#, c-format
msgid "Downloaded %s %s / %s %s"
-msgstr "Laddar ner %s %s / %s %s"
+msgstr "Laddade ner %s %s / %s %s"
#: gui/downloaddialog.cpp:259
#, c-format
@@ -239,7 +239,7 @@ msgid ""
"English"
msgstr ""
"Spelets sprхk. Den hфr instфllningen omvandlar inte din spanska spelversion "
-"till en engelsk"
+"till en svensk"
#: gui/editgamedialog.cpp:152 gui/editgamedialog.cpp:166 gui/options.cpp:995
#: gui/options.cpp:1008 gui/options.cpp:1573 audio/null.cpp:41
@@ -464,7 +464,7 @@ msgstr "Rum:"
#: gui/fluidsynth-dialog.cpp:80
msgid "Damp:"
-msgstr "Dфmpa:"
+msgstr "Dфmpning:"
#: gui/fluidsynth-dialog.cpp:87
msgid "Width:"
@@ -542,10 +542,10 @@ msgstr ""
"Vill du verkligen хterstфlla alla FluidSynth-instфllningar till deras "
"ursprungliga vфrden?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Stфng"
@@ -594,111 +594,111 @@ msgstr "Tryck pх en tangent fіr att stфlla in"
msgid "Choose an action to map"
msgstr "Vфlj en handling att stфlla in"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~A~vsluta"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Avsluta ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "O~m~..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Om ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~I~nstфllningar..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Redigera globala ScummVM-instфllningar"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~S~tarta"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Starta det valda spelet"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~L~adda..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Ladda spardata fіr det valda spelet"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "Lф~g~g till spel..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Hхll ned Skift fіr masstillфgg"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "R~e~digera spel..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Redigera spelinstфllningarna"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~R~adera spel"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Radera spelet frхn listan. Spelets datafiler pхverkas inte"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "Lф~g~g till spel..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "R~e~digera spel..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~R~adera spel"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Sіk i spellistan"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Sіk:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Ladda spel:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Ladda"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -706,63 +706,63 @@ msgstr ""
"Vill du verkligen anvфnda mass-speldetektorn? Processen kan potentiellt "
"lфgga till ett enormt antal spel."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
"Den hфr katalogen kan inte anvфndas фn, eftersom nхgot laddas ner i den!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Vill du verkligen radera den hфr spelkonfigurationen?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Vill du ladda sparat spel?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Det hфr spelet stіder inte laddning av spardata frхn launchern."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr ""
"ScummVM kunde inte hitta en motor kapabel till att kіra det valda spelet!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM kunde inte hitta nхgra spel i den valda katalogen!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Vфlj spel:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Masstillфgg..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Spela in..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... progression ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Scanning fфrdig!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "Upptфckte %d nya spel. Ignorerade %d tidigare tillagda spel."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Kataloger scannade: %d ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "Upptфckte %d nya spel, ignorerade %d tidigare tillagda spel ..."
@@ -915,7 +915,7 @@ msgstr "Korrektion av bildfіrhхllande"
#: gui/options.cpp:1024
msgid "Correct aspect ratio for 320x200 games"
-msgstr "Korrigera bildfіrhхllandet fіr 320 x 200-spel"
+msgstr "Korrigera bildfіrhхllandet fіr 320x200-spel"
#: gui/options.cpp:1032
msgid "Preferred Device:"
@@ -1557,7 +1557,7 @@ msgstr "Du kommer att fіras till ScummVM:s sida"
#: gui/storagewizarddialog.cpp:79
msgid "you should allow it to access your storage."
-msgstr "dфr du borde kunna komma хt ditt lager."
+msgstr "dфr du borde tillхta хtkomst till ditt lager."
#: gui/storagewizarddialog.cpp:112
msgid "Another Storage is active. Do you want to interrupt it?"
@@ -1597,31 +1597,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Vфlj ett tema"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Inaktiverad GFX"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Inaktiverad GFX"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Standard rendering"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Standard"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Antialiserad rendering"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Antialiserad"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Ladda sparfil:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1644,7 +1672,7 @@ msgstr ""
msgid "Proceed"
msgstr "Fortsфtt"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Tіm sіkfфltet"
@@ -1787,23 +1815,6 @@ msgstr "Varje mхnad"
msgid "<Bad value>"
msgstr "<Dхligt vфrde>"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Spelet i '%s' verkar vara en okфnd variant av %s-motorn.\n"
-"\n"
-"Rapportera informationen nedan till ScummVM-teamet pх %s tillsammans med "
-"namnet pх spelet du fіrsіkte lфgga till och spelets version, sprхk, etc.:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr "Matchade spel-ID:"
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~F~ortsфtt"
@@ -1839,12 +1850,12 @@ msgstr "Хte~r~vфnd till launcher"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1859,12 +1870,12 @@ msgstr "Spara spelet:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1979,22 +1990,48 @@ msgstr ""
msgid "Start anyway"
msgstr "Starta фndх"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Spelet i '%s' verkar vara en okфnd variant av %s-motorn.\n"
+"\n"
+"Rapportera informationen nedan till ScummVM-teamet pх %s tillsammans med "
+"namnet pх spelet du fіrsіkte lфgga till och spelets version, sprхk, etc.:"
+
+#: engines/game.cpp:162
+#, fuzzy, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr "Matchade spel-ID:"
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "AdLib-emulator"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL-emulator"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "DOSBox OPL-emulator"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL-emulator"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2101,7 +2138,9 @@ msgstr ""
msgid ""
"Download complete.\n"
"Failed to download %u files."
-msgstr "Nedladdningen фr fфrdig. Kunde inte ladda ner %u filer."
+msgstr ""
+"Nedladdningen фr fфrdig.\n"
+"Kunde inte ladda ner %u filer."
#: backends/cloud/storage.cpp:330
msgid "Download complete."
@@ -2239,12 +2278,12 @@ msgstr "Korrektion av bildfіrhхllande av"
#: backends/graphics/openglsdl/openglsdl-graphics.cpp:747
#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2477
msgid "Filtering enabled"
-msgstr "Filtrering aktiverat"
+msgstr "Filtrering aktiverad"
#: backends/graphics/openglsdl/openglsdl-graphics.cpp:749
#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:2479
msgid "Filtering disabled"
-msgstr "Filtrering фr inaktiverat"
+msgstr "Filtrering inaktiverad"
#: backends/graphics/surfacesdl/surfacesdl-graphics.cpp:55
#: backends/graphics/wincesdl/wincesdl-graphics.cpp:88
@@ -2364,7 +2403,7 @@ msgstr "Hіg ljudkvalitet (lхngsammare) (omstart)"
#: backends/platform/ds/arm9/source/dsoptions.cpp:122
msgid "Disable power off"
-msgstr "Inaktivera strіmsparning"
+msgstr "Inaktivera strіmsparlфge"
#: backends/platform/ios7/ios7_osys_events.cpp:309
#: backends/platform/ios7/ios7_osys_events.cpp:519
@@ -2559,7 +2598,7 @@ msgstr "Lodrфt underskanning:"
#: backends/platform/wii/options.cpp:71
msgid "Input"
-msgstr "Ingхng"
+msgstr "Inmatning"
#: backends/platform/wii/options.cpp:74
msgid "GC Pad sensitivity:"
@@ -2599,7 +2638,7 @@ msgstr "Server:"
#: backends/platform/wii/options.cpp:110
msgid "Share:"
-msgstr "Delad:"
+msgstr "Utdelning:"
#: backends/platform/wii/options.cpp:118
msgid "Password:"
@@ -2786,7 +2825,7 @@ msgstr "Sіk efter uppdateringar..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2794,7 +2833,7 @@ msgstr "Kunde inte hitta spelmotorns datafil '%s'."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2840,6 +2879,7 @@ msgstr "Anvфnd originalskфrmar fіr spara/ladda"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"Anvфnd originalskфrmarna fіr ladda och spara istфllet fіr ScummVM:s egna"
@@ -2854,7 +2894,7 @@ msgid ""
"behavior"
msgstr ""
"Anvфnd en alternativ fфrgkarta typisk fіr alla Amiga-spel. Det hфr фr det "
-"mala beteendet"
+"gamla beteendet"
#: engines/agi/detection.cpp:167
msgid "Mouse support"
@@ -2888,9 +2928,9 @@ msgstr ""
"istфllet fіr inmatning i realtid."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2902,9 +2942,9 @@ msgid "Restore game:"
msgstr "Ladda sparfil:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2915,7 +2955,7 @@ msgstr "Ladda sparfil:"
msgid "Restore"
msgstr "Ladda"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2937,7 +2977,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2953,11 +2993,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Filmfilen '%s' hittades ej!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Fфrgblint lфge"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Aktivera fфrgblint lфge som standard"
@@ -3038,7 +3078,7 @@ msgstr "Skipp-stіd"
#: engines/kyra/detection.cpp:74
msgid "Allow text and cutscenes to be skipped"
-msgstr "Tillхter skippning av text och filmscener"
+msgstr "Tillхt skippning av text och filmscener"
#. I18N: Helium mode makes people sound like they've inhaled Helium.
#: engines/kyra/detection.cpp:84
@@ -3053,7 +3093,7 @@ msgstr "Aktivera heliumlфge"
#. changing from one screen to another.
#: engines/kyra/detection.cpp:99
msgid "Smooth scrolling"
-msgstr "Mjuk rullning"
+msgstr "Mjuk skфrmrullning"
#: engines/kyra/detection.cpp:100
msgid "Enable smooth scrolling when walking"
@@ -3253,16 +3293,16 @@ msgstr "Animerat spelgrфnssnitt"
msgid "Naughty game mode"
msgstr "\"Busigt\" spellфge"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Spela flygvideon i Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "Flygvideon i Myst visades inte i originalspelet."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~iplфge aktiverat"
@@ -3283,27 +3323,27 @@ msgstr "~V~isa karta"
msgid "Main Men~u~"
msgstr "Huvud~m~eny"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~V~atteneffekt aktiverad"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
msgid "Transitions:"
msgstr "жvergхngar:"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
msgid "Disabled"
msgstr "Inaktiverad"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
msgid "Fastest"
msgstr "Snabbast"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr "Normal"
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr "Bфsta"
@@ -3311,7 +3351,7 @@ msgstr "Bфsta"
msgid "The game is paused. Press any key to continue."
msgstr "Spelet pausat. Tryck pх valfri tangent fіr att fortsфtta."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3319,7 +3359,7 @@ msgstr ""
"Rivens huvudprogram saknas. Windowsprogrammet heter 'riven.exe' eller "
"'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3327,7 +3367,7 @@ msgstr ""
"Det gхr фven bra med installationsfilen 'arcriven.z', eller "
"Macintoshprogrammet 'Riven'."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3335,7 +3375,7 @@ msgstr ""
"Filen 'extras.mhk' saknas. Det gхr фven bra att anvфnda installationsfilen "
"'arcriven.z' i stфllet."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr "Du saknar fіljande obligatoriska datafiler fіr Riven:\n"
@@ -3526,7 +3566,7 @@ msgid ""
"Use an IBM Music Feature card or a Yamaha FB-01 FM synth module for MIDI "
"output"
msgstr ""
-"Anvфnd ett IMB Music Feature-kort eller en Yamaha FB-01 FM synthmodul fіr "
+"Anvфnd ett IBM Music Feature-kort eller en Yamaha FB-01 FM synthmodul fіr "
"MIDI-uppspelning"
#: engines/sci/detection.cpp:473
@@ -3677,7 +3717,7 @@ msgstr ""
"rekommenderas att du tar bort den hфr patchen frхn spelmappen fіr att "
"undvika ovфntade fel eller problem senare."
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3690,7 +3730,7 @@ msgstr ""
"data till ScummVM-teamet tillsammans med namnet pх spelet du\n"
"fіrsіkte lфgga till och vilken version och sprхk det har, osv.\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3700,11 +3740,11 @@ msgstr ""
"skфl.\n"
"Den fullstфndiga versionen gхr att kіpa pх iTunes Store."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Visa objektrad"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Visa namnen pх objekt pх botten av skфrmen"
@@ -3753,7 +3793,7 @@ msgstr "Du mхste ange ett namn"
#: engines/scumm/dialogs.cpp:192
msgid "The game was NOT saved (disk full?)"
-msgstr "Spelet sprades EJ (skivan full?)"
+msgstr "Spelet sparades EJ (skivan full?)"
#: engines/scumm/dialogs.cpp:193
msgid "The game was NOT loaded"
@@ -3928,7 +3968,7 @@ msgstr "Musrestriktion av/pх"
#: engines/scumm/help.cpp:101
msgid "Switch between graphics filters"
-msgstr "Vфxla grafikfilter"
+msgstr "Vфxla mellan grafikfilter"
#: engines/scumm/help.cpp:102
msgid "Increase / Decrease scale factor"
@@ -4190,7 +4230,7 @@ msgstr "Comm"
#: engines/scumm/help.cpp:247
msgid "Save / Load / Options"
-msgstr "Spara / Ladda / Inst"
+msgstr "Spara / Ladda / Instфllningar"
#: engines/scumm/help.cpp:256
msgid "Other game controls:"
@@ -4382,7 +4422,7 @@ msgstr ""
"Stіd fіr Native MIDI krфver Roland-uppdateringen frхn LucasArts,\n"
"men %s saknas. Anvфnder AdLib istфllet."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4466,18 +4506,17 @@ msgstr "Diskettintro"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Anvфnd diskettversionens intro (endast CD-version)"
-#: engines/supernova/supernova.cpp:308
-#, fuzzy, c-format
+#: engines/supernova/supernova.cpp:193
+#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-"Felaktig version av datafilen '%s' hittades. Version %d.%d krфvs, hittade %d."
-"%d."
+"Felaktig version av datafilen '%s' hittades. Version %d krфvs, hittade %d."
-#: engines/supernova/supernova.cpp:335
-#, fuzzy, c-format
+#: engines/supernova/supernova.cpp:220
+#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
-msgstr "Kunde inte hitta spelmotorns datafil '%s'."
+msgstr "Kunde inte hitta sprхk %s i spelmotorns datafil '%s'."
#: engines/sword1/animation.cpp:524
#, c-format
@@ -4592,30 +4631,46 @@ msgstr "Sparade speldata #%d snabbladdades"
msgid "Could not quick load the saved game #%d"
msgstr "Det gick inte att snabbladda sparat spel #%d"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Visa FPS-rфknare"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
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/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Bilinjфr filtrering av rіrliga figurer (LХNGSAM)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Tillфmpa bilinjфr filtrering pх enskilda rіrliga figurer"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
-msgstr "Anvфnd originalskфrmarna fіr spara/ladda istфllet fіr ScummVM:s"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr "Visa kostnader fіr fіremхl i standardlфge fіr inventariet"
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+"Visar kostnader fіr fіremхl i standardlфge fіr inventariet i syfte att "
+"mіjliggіra jфmfіrbarhet mellan olika fіremхl"
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
+msgstr ""
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
-msgstr "Dubbel FPS"
+msgstr "Dubbla FPS"
#: engines/zvision/detection_tables.h:62
msgid "Increase framerate from 30 to 60 FPS"
@@ -4645,7 +4700,7 @@ msgstr "Anvфnd hіgupplіst MPEG-video"
msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr "Anvфnd MPEG-video frхn DVD-versionen istфllet fіr lхgupplіst AVI"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4655,6 +4710,9 @@ msgstr ""
"till version %d. Det krфvs en uppdaterad version av spelmotorn fіr att "
"anvфnda den hфr sparfilen."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr "Anvфnd originalskфrmarna fіr spara/ladda istфllet fіr ScummVM:s"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr ""
#~ "(Du kan alltid aktivera den under \"Diverse\"-fliken i instфllningarna)"
diff --git a/po/uk_UA.po b/po/uk_UA.po
index 65ebd3e399..741c5bf6d3 100644
--- a/po/uk_UA.po
+++ b/po/uk_UA.po
@@ -8,9 +8,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.9.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2017-06-14 14:55+0000\n"
-"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:18+0000\n"
+"Last-Translator: Adrian Fruehwirth <bonki@scummvm.org>\n"
"Language-Team: Ukrainian <https://translations.scummvm.org/projects/scummvm/"
"scummvm/uk/>\n"
"Language: uk_UA\n"
@@ -59,7 +59,7 @@ msgstr "Вгору"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -83,7 +83,7 @@ msgstr "Вибрати"
msgid "Select directory where to download game data"
msgstr "Виберіть папку куди завантажувати файли гри"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Виберіть папку з файлами гри"
@@ -118,7 +118,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -131,7 +131,7 @@ msgstr "Так"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -142,7 +142,7 @@ msgstr "Так"
msgid "No"
msgstr "Ні"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM не може відкрити вказану папку!"
@@ -155,8 +155,8 @@ msgstr ""
"назвою."
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -171,7 +171,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "OK"
@@ -543,10 +543,10 @@ msgstr ""
"Ви дійсно хочете скинути всі налаштування FluidSynth до їх значень за "
"замовченням?"
-#: 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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 "Закрити"
@@ -595,111 +595,111 @@ msgstr "Натисніть клавішу для призначення"
msgid "Choose an action to map"
msgstr "Виберіть дію для призначення"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~В~ихід"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Вихід зі ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "Про п~р~ограму..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Про ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~Н~алаштування..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Змінити глобальні налаштування ScummVM"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "З~а~пуск"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Запустити вибрану гру"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~З~авантажити..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Завантажити збережений стан для вибраної гри"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~Д~одати гру..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Утримуйте клавішу Shift для того, щоб додати декілька ігор"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "Реда~г~увати гру..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Змінити налаштування гри"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~В~идалити гру"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
msgid "Remove game from the list. The game data files stay intact"
msgstr "Видалити гру зі списку. Не видаляє гру з жорсткого диску"
-#: gui/launcher.cpp:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~Д~одати гру..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "Реда~г~. гру..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~В~идалити гру"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Пошук у списку ігор"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Пошук:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Завантажити гру:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Завантажити"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -707,61 +707,61 @@ msgstr ""
"Чи ви дійсно хочете запустити пошук усіх ігор? Це потенційно може додати "
"велику кількість ігор."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr "Цю папку ще не можна використовувати, в неї іде завантаження!"
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Ви дійсно хочете видалити налаштування для цієї гри?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Ви хочете завантажити збережений стан гри?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Ця гра не підтримує завантаження збережених ігор через головне меню."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
msgid "ScummVM could not find any engine capable of running the selected game!"
msgstr "ScummVM не може знайти движок для запуску вибраної гри!"
-#: gui/launcher.cpp:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM не може знайти гру у вказаній папці!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Виберіть гру:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "Дод. багато..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Запис..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... пошук ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Пошук закінчено!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, c-format
msgid "Discovered %d new games, ignored %d previously added games."
msgstr "Знайдено %d нових ігор, пропущено %d попередньо доданих ігор."
-#: gui/massadd.cpp:266
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "Проглянуто %d папок ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "Знайдено %d нових ігор, пропущено %d попередньо доданих ігор ..."
@@ -1600,31 +1600,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Виберіть тему"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Без графіки"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Без графіки"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Стандартний растеризатор"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Стандартний"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Растеризатор зі згладжуванням"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Зі згладжуванням"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Відновити гру:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
#, fuzzy
msgid ""
@@ -1647,7 +1675,7 @@ msgstr ""
msgid "Proceed"
msgstr "Продовжити"
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Очистити значення"
@@ -1790,22 +1818,6 @@ msgstr "Щомісяця"
msgid "<Bad value>"
msgstr "<Невірне значення>"
-#: engines/advancedDetector.cpp:330
-#, fuzzy, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-"Гра у '%s' невідома.\n"
-"Будь ласка, передайте нижченаведену інформацію команді ScummVM разом з\n"
-"назвою гри, яку ви намагаєтесь додати, а також її версію/мову/та інше:"
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "Продов~ж~ити"
@@ -1841,12 +1853,12 @@ msgstr "~П~овер.в головне меню"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1861,12 +1873,12 @@ msgstr "Зберегти гру:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1981,22 +1993,47 @@ msgstr ""
msgid "Start anyway"
msgstr "Все одно запустити"
+#: engines/game.cpp:158
+#, fuzzy, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+"Гра у '%s' невідома.\n"
+"Будь ласка, передайте нижченаведену інформацію команді ScummVM разом з\n"
+"назвою гри, яку ви намагаєтесь додати, а також її версію/мову/та інше:"
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "Емулятор AdLib"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "Емулятор MAME OPL"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
msgstr "Емулятор DOSBox OPL"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Емулятор Nuked OPL"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "Безпосередній ALSA FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2789,7 +2826,7 @@ msgstr "Перевірити оновлення..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2797,7 +2834,7 @@ msgstr "Не вдалося знайти файл даних движка %s."
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2842,6 +2879,7 @@ msgstr "Використовувати ориг. екрани збереження/завантаження"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr ""
"Використовувати оригінальні екрани збереження/завантаження замість ScummVM"
@@ -2892,9 +2930,9 @@ msgstr ""
"замість безпосереднього вводу."
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2906,9 +2944,9 @@ msgid "Restore game:"
msgstr "Відновити гру:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2919,7 +2957,7 @@ msgstr "Відновити гру:"
msgid "Restore"
msgstr "Відновити"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2941,7 +2979,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2957,11 +2995,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Файл ролику '%s' не знайдено!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Режим без кольору"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Включає режим для людей з погіршенним сприяттям кольору"
@@ -3256,16 +3294,16 @@ msgstr "Анімований інтерфейс гри"
msgid "Naughty game mode"
msgstr "Відвертий режим гри"
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr "Показувати ролік польоту над Myst"
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr "Ролік польоту над Myst не показувався оригінальним движком."
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "Режим швидкого переходу активовано"
@@ -3286,30 +3324,30 @@ msgstr "Показати мапу"
msgid "Main Men~u~"
msgstr "Головне меню"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "Ефекти води увімкнено"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
#, fuzzy
msgid "Transitions:"
msgstr "Переходи активовано"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
#, fuzzy
msgid "Disabled"
msgstr "Без графіки"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
#, fuzzy
msgid "Fastest"
msgstr "Вставити"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr ""
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3317,7 +3355,7 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr "Ігру призупинено. Натисніть будь-яку клавішу для продовження."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
@@ -3325,7 +3363,7 @@ msgstr ""
"У вам немає файлу для виконання Riven. Файл виконання для Windows має назву "
"'riven.exe' або 'rivendmo.exe'. "
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
@@ -3333,7 +3371,7 @@ msgstr ""
"Використання файлу 'arcriven.z' також є припустимим. Також ви можете "
"використовувати файл 'Riven' для Mac."
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
@@ -3341,7 +3379,7 @@ msgstr ""
"У вас немає файлу 'extras.mhk'. Використання файлу 'arcriven.z' також "
"достатньо."
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3664,7 +3702,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3677,7 +3715,7 @@ msgstr ""
"ніжченаведені дані команді ScummVM разом з назвою гри, яку ви намагаєтесь\n"
"додати, а також її версію, мову та інше:\n"
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
@@ -3686,11 +3724,11 @@ msgstr ""
"Задля запобігання піратства, Lite-версія гри Putt-Putt Save the Zoo для iOS\n"
"не підтримується. Повну версію можна придбати у iTunes Store."
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
msgid "Show Object Line"
msgstr "Показувати лінії об'єктів"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr "Показувати назви об'єктів внизу екрану"
@@ -4368,7 +4406,7 @@ msgstr ""
"Режим \"рідного\" MIDI потребує поновлення Roland Upgrade від\n"
"LucasArts, проте %s відсутній. Перемикаюсь на AdLib."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4450,14 +4488,14 @@ msgstr "Вступ з флоппі-версії"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Використовувати введення з флоппі-версії (тільки для CD версії гри)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, fuzzy, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
"Знайдено невірну версію даних движка %s. Очікувана %d.%d, але знайдено %d.%d."
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, fuzzy, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr "Не вдалося знайти файл даних движка %s."
@@ -4578,27 +4616,39 @@ msgstr "Збережену гру №%d завантажено"
msgid "Could not quick load the saved game #%d"
msgstr "Не вдалося завантажити збережену гру №%d"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Показати лічильник кадрів"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "Показує у верньому лівому куті поточну кількість кадрів на секунду"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr "Білінійна фільтрація спрайтів (повільно)"
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr "Застосувати білінійну фільтрацію до окремих спрайтів"
-#: engines/zvision/detection_tables.h:52
-msgid "Use the original save/load screens instead of the ScummVM interface"
+#: engines/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
msgstr ""
-"Використовувати оригінальні екрани збереження/завантаження замість екранів "
-"зі ScummVM"
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4634,7 +4684,7 @@ msgstr ""
"Використовувати відео MPEG з DVD-версії замість файлів AVI з ніжчою "
"роздільною здатністю"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
@@ -4644,6 +4694,11 @@ msgstr ""
"версію до %d. Вам потрібна поновлена версія ScummVM для завантаження цього "
"файлу."
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr ""
+#~ "Використовувати оригінальні екрани збереження/завантаження замість "
+#~ "екранів зі ScummVM"
+
#~ msgid "(You can always enable it in the options dialog on the Misc tab)"
#~ msgstr "(Ви завжди можете включити її у Налаштуваннях на закладці Інше)"
diff --git a/po/zh-Latn_CN.po b/po/zh-Latn_CN.po
index 7a28fbaecf..5a707f8277 100644
--- a/po/zh-Latn_CN.po
+++ b/po/zh-Latn_CN.po
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: ScummVM 1.9.0git\n"
"Report-Msgid-Bugs-To: scummvm-devel@lists.scummvm.org\n"
-"POT-Creation-Date: 2018-03-12 11:46+0100\n"
-"PO-Revision-Date: 2016-12-26 19:38+0000\n"
-"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
+"POT-Creation-Date: 2018-06-03 13:49+0200\n"
+"PO-Revision-Date: 2018-04-18 10:18+0000\n"
+"Last-Translator: Adrian Frќhwirth <bonki@scummvm.org>\n"
"Language-Team: Chinese <https://translations.scummvm.org/projects/scummvm/"
"scummvm/zh_LATN@cn/>\n"
"Language: zh-Latn_CN\n"
@@ -57,7 +57,7 @@ msgstr "ShangYiJi"
#: gui/browser.cpp:76 gui/chooser.cpp:46 gui/editgamedialog.cpp:293
#: gui/editrecorddialog.cpp:67 gui/filebrowser-dialog.cpp:65
-#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:95
+#: gui/fluidsynth-dialog.cpp:153 gui/KeysDialog.cpp:43 gui/massadd.cpp:92
#: gui/options.cpp:1678 gui/predictivedialog.cpp:73 gui/recorderdialog.cpp:69
#: gui/recorderdialog.cpp:155 gui/remotebrowser.cpp:60
#: gui/saveload-dialog.cpp:383 gui/saveload-dialog.cpp:445
@@ -82,7 +82,7 @@ msgstr "Xuanze"
msgid "Select directory where to download game data"
msgstr "Xuanze Youxi Shuju Mulu"
-#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:197
+#: gui/downloaddialog.cpp:50 gui/editgamedialog.cpp:471 gui/launcher.cpp:198
msgid "Select directory with game data"
msgstr "Xuanze Youxi Shuju Mulu"
@@ -115,7 +115,7 @@ msgstr ""
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:153
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -128,7 +128,7 @@ msgstr "Shi"
#: gui/downloaddialog.cpp:119 gui/downloaddialog.cpp:154
#: gui/filebrowser-dialog.cpp:133 gui/fluidsynth-dialog.cpp:218
-#: gui/launcher.cpp:310 gui/launcher.cpp:418 gui/launcher.cpp:477
+#: gui/launcher.cpp:311 gui/launcher.cpp:380 gui/launcher.cpp:440
#: gui/storagewizarddialog.cpp:112
#: backends/events/symbiansdl/symbiansdl-events.cpp:192
#: backends/platform/wince/CEActionsPocket.cpp:326
@@ -139,7 +139,7 @@ msgstr "Shi"
msgid "No"
msgstr "Fou"
-#: gui/downloaddialog.cpp:137 gui/launcher.cpp:569
+#: gui/downloaddialog.cpp:137 gui/launcher.cpp:532
msgid "ScummVM couldn't open the specified directory!"
msgstr "ScummVM Wufa Dakai Zhiding Mulu!"
@@ -150,8 +150,8 @@ msgid ""
msgstr ""
#: gui/downloaddialog.cpp:147 gui/editgamedialog.cpp:294
-#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:526
-#: gui/launcher.cpp:530 gui/massadd.cpp:92 gui/options.cpp:1680
+#: gui/fluidsynth-dialog.cpp:154 gui/KeysDialog.cpp:42 gui/launcher.cpp:489
+#: gui/launcher.cpp:493 gui/massadd.cpp:89 gui/options.cpp:1680
#: gui/saveload-dialog.cpp:1122 engines/engine.cpp:443 engines/engine.cpp:454
#: backends/platform/wii/options.cpp:47
#: backends/platform/wince/CELauncherDialog.cpp:54
@@ -166,7 +166,7 @@ msgstr ""
#: engines/sword1/control.cpp:887 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
-#: engines/zvision/file/save_manager.cpp:224
+#: engines/zvision/file/save_manager.cpp:230
msgid "OK"
msgstr "Queding"
@@ -530,10 +530,10 @@ 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
+#: gui/gui-manager.cpp:119 gui/unknown-game-dialog.cpp:48
+#: 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"
@@ -582,111 +582,111 @@ msgstr "Anxia Anjian lai Guanlian"
msgid "Choose an action to map"
msgstr "Xuanze yao Yingshe de Xingwei"
-#: gui/launcher.cpp:141 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
+#: gui/launcher.cpp:142 engines/dialogs.cpp:111 engines/mohawk/dialogs.cpp:100
msgid "~Q~uit"
msgstr "~Q~Tuichu"
-#: gui/launcher.cpp:141 backends/platform/sdl/macosx/appmenu_osx.mm:112
+#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:112
msgid "Quit ScummVM"
msgstr "Tuichu ScummVM"
-#: gui/launcher.cpp:142
+#: gui/launcher.cpp:143
msgid "A~b~out..."
msgstr "~b~Guanyu..."
-#: gui/launcher.cpp:142 backends/platform/sdl/macosx/appmenu_osx.mm:86
+#: gui/launcher.cpp:143 backends/platform/sdl/macosx/appmenu_osx.mm:86
msgid "About ScummVM"
msgstr "Guanyu ScummVM"
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "~O~ptions..."
msgstr "~O~Xuanxiang..."
-#: gui/launcher.cpp:143
+#: gui/launcher.cpp:144
msgid "Change global ScummVM options"
msgstr "Genggai ScummVM Quanju Shezhi"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "~S~tart"
msgstr "~S~Kaishi"
-#: gui/launcher.cpp:145
+#: gui/launcher.cpp:146
msgid "Start selected game"
msgstr "Kaishi Xuanze de Youxi"
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "~L~oad..."
msgstr "~L~Jiazai..."
-#: gui/launcher.cpp:148
+#: gui/launcher.cpp:149
msgid "Load saved game for selected game"
msgstr "Jiazai Xuanze Baocun de Youxi"
-#: gui/launcher.cpp:153
+#: gui/launcher.cpp:154
msgid "~A~dd Game..."
msgstr "~A~Tianjia Youxi ..."
-#: gui/launcher.cpp:153 gui/launcher.cpp:160
+#: gui/launcher.cpp:154 gui/launcher.cpp:161
msgid "Hold Shift for Mass Add"
msgstr "Anzhu Shift Lai Piliang Tianjia"
-#: gui/launcher.cpp:155
+#: gui/launcher.cpp:156
msgid "~E~dit Game..."
msgstr "~E~Bianji Youxi ..."
-#: gui/launcher.cpp:155 gui/launcher.cpp:162
+#: gui/launcher.cpp:156 gui/launcher.cpp:163
msgid "Change game options"
msgstr "Genggai Youxi Xuanxiang"
-#: gui/launcher.cpp:157
+#: gui/launcher.cpp:158
msgid "~R~emove Game"
msgstr "~R~Yichu Youxi"
-#: gui/launcher.cpp:157 gui/launcher.cpp:164
+#: gui/launcher.cpp:158 gui/launcher.cpp:165
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:160
+#: gui/launcher.cpp:161
msgctxt "lowres"
msgid "~A~dd Game..."
msgstr "~A~Tianjia Youxi ..."
-#: gui/launcher.cpp:162
+#: gui/launcher.cpp:163
msgctxt "lowres"
msgid "~E~dit Game..."
msgstr "~E~Bianji Youxi ..."
-#: gui/launcher.cpp:164
+#: gui/launcher.cpp:165
msgctxt "lowres"
msgid "~R~emove Game"
msgstr "~R~Yichu Youxi"
-#: gui/launcher.cpp:172
+#: gui/launcher.cpp:173
msgid "Search in game list"
msgstr "Zai Youxi Liebiao zhong Sousuo"
-#: gui/launcher.cpp:176 gui/launcher.cpp:775
+#: gui/launcher.cpp:177 gui/launcher.cpp:745
msgid "Search:"
msgstr "Sousuo:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
-#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:533
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115 engines/cruise/menu.cpp:214
+#: engines/mohawk/dialogs.cpp:105 engines/mohawk/riven.cpp:549
#: engines/pegasus/pegasus.cpp:355 engines/tsage/scenes.cpp:601
#: engines/wage/saveload.cpp:748
msgid "Load game:"
msgstr "Jiazai Youxi:"
-#: gui/launcher.cpp:200 engines/dialogs.cpp:115
+#: gui/launcher.cpp:201 engines/dialogs.cpp:115
#: backends/platform/wince/CEActionsPocket.cpp:267
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/cruise/menu.cpp:214 engines/mohawk/dialogs.cpp:105
-#: engines/mohawk/riven.cpp:533 engines/parallaction/saveload.cpp:194
+#: engines/mohawk/riven.cpp:549 engines/parallaction/saveload.cpp:194
#: engines/pegasus/pegasus.cpp:355 engines/scumm/dialogs.cpp:185
#: engines/tsage/scenes.cpp:601 engines/wage/saveload.cpp:748
msgid "Load"
msgstr "Jiazai"
-#: gui/launcher.cpp:309
+#: gui/launcher.cpp:310
msgid ""
"Do you really want to run the mass game detector? This could potentially add "
"a huge number of games."
@@ -694,61 +694,61 @@ msgstr ""
"Nin Queding yao Yunxing Youxi Piliang Jiance Ma? Zhe You Keneng Hui Zengjia "
"Daliang Youxi."
-#: gui/launcher.cpp:368
+#: gui/launcher.cpp:369
msgid "This directory cannot be used yet, it is being downloaded into!"
msgstr ""
-#: gui/launcher.cpp:418
+#: gui/launcher.cpp:380
msgid "Do you really want to remove this game configuration?"
msgstr "Nin Zhende Xiangyao Yichu Zhege Youxi Peizhi?"
-#: gui/launcher.cpp:476
+#: gui/launcher.cpp:439
msgid "Do you want to load saved game?"
msgstr "Nin Yao Zairu Baocun de Youxi ma?"
-#: gui/launcher.cpp:526
+#: gui/launcher.cpp:489
msgid "This game does not support loading games from the launcher."
msgstr "Ci Youxi Bu Zhichi cong Jiazaiqi Zhong Jiazai Youxi."
-#: gui/launcher.cpp:530
+#: gui/launcher.cpp:493
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:581
+#: gui/launcher.cpp:554
msgid "ScummVM could not find any game in the specified directory!"
msgstr "ScummVM zai Zhiding Mulu Zhong Wufa Zhaodao Renhe Youxi!"
-#: gui/launcher.cpp:594
+#: gui/launcher.cpp:567
msgid "Pick the game:"
msgstr "Xuanze Youxi:"
-#: gui/launcher.cpp:712
+#: gui/launcher.cpp:682
msgid "Mass Add..."
msgstr "PiLiang Zengjia ..."
-#: gui/launcher.cpp:714
+#: gui/launcher.cpp:684
msgid "Record..."
msgstr "Luxiang ..."
-#: gui/massadd.cpp:79 gui/massadd.cpp:82
+#: gui/massadd.cpp:76 gui/massadd.cpp:79
msgid "... progress ..."
msgstr "... Jindu ..."
-#: gui/massadd.cpp:259
+#: gui/massadd.cpp:265
msgid "Scan complete!"
msgstr "Saomiao Wancheng!"
-#: gui/massadd.cpp:262
+#: gui/massadd.cpp:268
#, 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
+#: gui/massadd.cpp:272
#, c-format
msgid "Scanned %d directories ..."
msgstr "YiSaomiao %d ge Mulu ..."
-#: gui/massadd.cpp:269
+#: gui/massadd.cpp:275
#, c-format
msgid "Discovered %d new games, ignored %d previously added games ..."
msgstr "Faxian le %d ge Xinyouxi, Hulue %d ge YiTianjia de Youxi ..."
@@ -1594,31 +1594,59 @@ msgstr ""
msgid "Select a Theme"
msgstr "Xuanze Zhuti"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgid "Disabled GFX"
msgstr "Jinyong GFX"
-#: gui/ThemeEngine.cpp:258
+#: gui/ThemeEngine.cpp:256
msgctxt "lowres"
msgid "Disabled GFX"
msgstr "Jinyong GFX"
-#: gui/ThemeEngine.cpp:259
+#: gui/ThemeEngine.cpp:257
msgid "Standard Renderer"
msgstr "Biaozhun Xuanranqi"
-#: gui/ThemeEngine.cpp:259 engines/scumm/dialogs.cpp:660
+#: gui/ThemeEngine.cpp:257 engines/scumm/dialogs.cpp:660
msgid "Standard"
msgstr "Biaozhun"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased Renderer"
msgstr "Fanjuchi Xuanranqi"
-#: gui/ThemeEngine.cpp:261
+#: gui/ThemeEngine.cpp:259
msgid "Antialiased"
msgstr "Fanjuchi"
+#: gui/unknown-game-dialog.cpp:52
+msgid "Copy to clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:67
+#, fuzzy
+msgid "Report game"
+msgstr "Huifu Youxi:"
+
+#: gui/unknown-game-dialog.cpp:110
+msgid ""
+"Use the button below to copy the required game information into your "
+"clipboard."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:117
+msgid "You can also directly report your game to the Bug Tracker."
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:199
+msgid ""
+"All necessary information about your game has been copied into the clipboard"
+msgstr ""
+
+#: gui/unknown-game-dialog.cpp:201
+msgid "Copying the game information to the clipboard has failed!"
+msgstr ""
+
#: gui/updates-dialog.cpp:49
msgid ""
"ScummVM now supports automatic check for updates\n"
@@ -1636,7 +1664,7 @@ msgstr ""
msgid "Proceed"
msgstr ""
-#: gui/widget.cpp:379 gui/widget.cpp:381 gui/widget.cpp:387 gui/widget.cpp:389
+#: gui/widget.cpp:356 gui/widget.cpp:358 gui/widget.cpp:364 gui/widget.cpp:366
msgid "Clear value"
msgstr "Qingchu Zhi"
@@ -1781,19 +1809,6 @@ msgstr ""
msgid "<Bad value>"
msgstr "Qingchu Zhi"
-#: engines/advancedDetector.cpp:330
-#, c-format
-msgid ""
-"The game in '%s' seems to be an unknown %s engine game variant.\n"
-"\n"
-"Please report the following data to the ScummVM team at %s along with the "
-"name of the game you tried to add and its version, language, etc.:"
-msgstr ""
-
-#: engines/advancedDetector.cpp:338
-msgid "Matched game IDs:"
-msgstr ""
-
#: engines/dialogs.cpp:85
msgid "~R~esume"
msgstr "~R~Jixu"
@@ -1829,12 +1844,12 @@ msgstr "~R~Fanhui Qidongqi"
#: engines/dialogs.cpp:116 engines/agi/saveload.cpp:761
#: engines/avalanche/parser.cpp:1900 engines/cge/events.cpp:72
-#: engines/cge2/events.cpp:65 engines/cine/various.cpp:348
-#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:196
+#: engines/cge2/events.cpp:64 engines/cine/various.cpp:348
+#: engines/cruise/menu.cpp:212 engines/dm/loadsave.cpp:199
#: engines/drascula/saveload.cpp:383 engines/dreamweb/saveload.cpp:262
#: engines/gnap/menu.cpp:464 engines/hugo/file.cpp:298
#: engines/mads/nebular/dialogs_nebular.cpp:350 engines/mohawk/dialogs.cpp:106
-#: engines/mohawk/riven.cpp:545 engines/neverhood/menumodule.cpp:880
+#: engines/mohawk/riven.cpp:561 engines/neverhood/menumodule.cpp:880
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:658
#: engines/sci/engine/kfile.cpp:1054 engines/sherlock/scalpel/scalpel.cpp:1250
#: engines/sherlock/tattoo/widget_files.cpp:75 engines/toltecs/menu.cpp:291
@@ -1849,12 +1864,12 @@ msgstr "Baocun Youxi:"
#: backends/platform/wince/CEActionsSmartphone.cpp:45
#: backends/platform/wince/CEActionsSmartphone.cpp:231
#: engines/agi/saveload.cpp:761 engines/avalanche/parser.cpp:1900
-#: engines/cge/events.cpp:72 engines/cge2/events.cpp:65
+#: engines/cge/events.cpp:72 engines/cge2/events.cpp:64
#: engines/cine/various.cpp:348 engines/cruise/menu.cpp:212
-#: engines/dm/loadsave.cpp:196 engines/drascula/saveload.cpp:383
+#: engines/dm/loadsave.cpp:199 engines/drascula/saveload.cpp:383
#: engines/dreamweb/saveload.cpp:262 engines/gnap/menu.cpp:464
#: engines/hugo/file.cpp:298 engines/mads/nebular/dialogs_nebular.cpp:350
-#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:545
+#: engines/mohawk/dialogs.cpp:106 engines/mohawk/riven.cpp:561
#: engines/neverhood/menumodule.cpp:880 engines/parallaction/saveload.cpp:209
#: engines/pegasus/pegasus.cpp:379 engines/sci/engine/guest_additions.cpp:659
#: engines/sci/engine/kfile.cpp:1054 engines/scumm/dialogs.cpp:184
@@ -1969,22 +1984,44 @@ msgstr ""
msgid "Start anyway"
msgstr "Qiangzhi Qidong"
+#: engines/game.cpp:158
+#, c-format
+msgid ""
+"The game in '%s' seems to be an unknown game variant.\n"
+"\n"
+"Please report the following data to the ScummVM team at %s along with the "
+"name of the game you tried to add and its version, language, etc.:"
+msgstr ""
+
+#: engines/game.cpp:162
+#, c-format
+msgid "Matched game IDs for the %s engine:"
+msgstr ""
+
#: audio/adlib.cpp:2290
msgid "AdLib Emulator"
msgstr "AdLib Moniqi"
-#: audio/fmopl.cpp:62
+#: audio/fmopl.cpp:71
msgid "MAME OPL emulator"
msgstr "MAME OPL Moniqi"
-#: audio/fmopl.cpp:64
+#: audio/fmopl.cpp:73
msgid "DOSBox OPL emulator"
-msgstr "DosBox OPL Moniqi"
+msgstr "DOSBox OPL Moniqi"
-#: audio/fmopl.cpp:67
+#: audio/fmopl.cpp:76
+msgid "Nuked OPL emulator"
+msgstr "Nuked OPL Moniqi"
+
+#: audio/fmopl.cpp:79
msgid "ALSA Direct FM"
msgstr "ALSA Direct FM"
+#: audio/fmopl.cpp:82
+msgid "OPL2LPT"
+msgstr "OPL2LPT"
+
#: audio/mididrv.cpp:209
#, c-format
msgid ""
@@ -2776,7 +2813,7 @@ msgstr "Jiancha Gengxin..."
#: engines/access/resources.cpp:44 engines/drascula/drascula.cpp:966
#: engines/hugo/hugo.cpp:437 engines/lure/lure.cpp:64
#: engines/mortevielle/mortevielle.cpp:306 engines/sky/compact.cpp:131
-#: engines/supernova/supernova.cpp:290 engines/teenagent/resources.cpp:97
+#: engines/supernova/supernova.cpp:175 engines/teenagent/resources.cpp:97
#: engines/tony/tony.cpp:198 engines/toon/toon.cpp:4918
#, c-format
msgid "Unable to locate the '%s' engine data file."
@@ -2784,7 +2821,7 @@ msgstr ""
#: engines/access/resources.cpp:52 engines/drascula/drascula.cpp:980
#: engines/hugo/hugo.cpp:448 engines/lure/lure.cpp:73
-#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:300
+#: engines/mortevielle/mortevielle.cpp:315 engines/supernova/supernova.cpp:185
#: engines/tony/tony.cpp:210 engines/toon/toon.cpp:4930
#, c-format
msgid "The '%s' engine data file is corrupt."
@@ -2830,6 +2867,7 @@ msgstr "Shiyong Yuanshi Baocun/Zairu Pingmu"
#: engines/drascula/detection.cpp:332 engines/dreamweb/detection.cpp:49
#: engines/neverhood/detection.cpp:178 engines/sci/detection.cpp:453
#: engines/sherlock/detection.cpp:72 engines/toltecs/detection.cpp:201
+#: engines/zvision/detection_tables.h:52
#, fuzzy
msgid "Use the original save/load screens instead of the ScummVM ones"
msgstr "Shiyong Yuanshi Baocun/Zairu Pingmu, Bu Shiyong ScummVM de"
@@ -2875,9 +2913,9 @@ msgid ""
msgstr ""
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2889,9 +2927,9 @@ msgid "Restore game:"
msgstr "Huifu Youxi:"
#: engines/agi/saveload.cpp:774 engines/avalanche/parser.cpp:1888
-#: engines/cge/events.cpp:83 engines/cge2/events.cpp:76
+#: engines/cge/events.cpp:83 engines/cge2/events.cpp:75
#: engines/cine/various.cpp:359 engines/dm/dm.cpp:276
-#: engines/dm/loadsave.cpp:184 engines/drascula/saveload.cpp:396
+#: engines/dm/loadsave.cpp:187 engines/drascula/saveload.cpp:396
#: engines/dreamweb/saveload.cpp:170 engines/gnap/menu.cpp:473
#: engines/hugo/file.cpp:400 engines/mads/nebular/dialogs_nebular.cpp:377
#: engines/neverhood/menumodule.cpp:893
@@ -2902,7 +2940,7 @@ msgstr "Huifu Youxi:"
msgid "Restore"
msgstr "Huifu"
-#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2441
+#: engines/agos/saveload.cpp:159 engines/scumm/scumm.cpp:2444
#, fuzzy, c-format
msgid ""
"Failed to load saved game from file:\n"
@@ -2924,7 +2962,7 @@ msgstr ""
"\n"
"%s"
-#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2452
+#: engines/agos/saveload.cpp:202 engines/scumm/scumm.cpp:2455
#, fuzzy, c-format
msgid ""
"Successfully saved game in file:\n"
@@ -2940,11 +2978,11 @@ msgstr ""
msgid "Cutscene file '%s' not found!"
msgstr "Changjing Qiehuan Wenjian '%s' Wei Zhaodao!"
-#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:101
+#: engines/cge/detection.cpp:105 engines/cge2/detection.cpp:111
msgid "Color Blind Mode"
msgstr "Semang Moshi"
-#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:102
+#: engines/cge/detection.cpp:106 engines/cge2/detection.cpp:112
msgid "Enable Color Blind Mode by default"
msgstr "Moren Qiyong Semang Moshi"
@@ -3247,16 +3285,16 @@ msgstr ""
msgid "Naughty game mode"
msgstr ""
-#: engines/mohawk/detection.cpp:169
+#: engines/mohawk/detection.cpp:162
msgid "Play the Myst fly by movie"
msgstr ""
-#: engines/mohawk/detection.cpp:170
+#: engines/mohawk/detection.cpp:163
msgid "The Myst fly by movie was not played by the original engine."
msgstr ""
#. I18N: Option for fast scene switching
-#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:269
+#: engines/mohawk/dialogs.cpp:183 engines/mohawk/dialogs.cpp:272
msgid "~Z~ip Mode Activated"
msgstr "~Z~Yasuo Moshi Qidong"
@@ -3279,30 +3317,30 @@ msgstr "~S~Xianshi Ditu"
msgid "Main Men~u~"
msgstr "~M~Zhucaidan"
-#: engines/mohawk/dialogs.cpp:270
+#: engines/mohawk/dialogs.cpp:273
msgid "~W~ater Effect Enabled"
msgstr "~W~Qiyong Shuimian Xiaoguo"
-#: engines/mohawk/dialogs.cpp:272
+#: engines/mohawk/dialogs.cpp:275
#, fuzzy
msgid "Transitions:"
msgstr "~T~Qiyong Zhuanyi"
-#: engines/mohawk/dialogs.cpp:274
+#: engines/mohawk/dialogs.cpp:277
#, fuzzy
msgid "Disabled"
msgstr "Jinyong GFX"
-#: engines/mohawk/dialogs.cpp:275
+#: engines/mohawk/dialogs.cpp:278
#, fuzzy
msgid "Fastest"
msgstr "Kuaisu Moshi"
-#: engines/mohawk/dialogs.cpp:276
+#: engines/mohawk/dialogs.cpp:279
msgid "Normal"
msgstr ""
-#: engines/mohawk/dialogs.cpp:277
+#: engines/mohawk/dialogs.cpp:280
msgid "Best"
msgstr ""
@@ -3311,25 +3349,25 @@ msgstr ""
msgid "The game is paused. Press any key to continue."
msgstr "Youxi Zanting. An Kongge Yi jixu."
-#: engines/mohawk/riven.cpp:149
+#: engines/mohawk/riven.cpp:150
msgid ""
"You're missing a Riven executable. The Windows executable is 'riven.exe' or "
"'rivendmo.exe'. "
msgstr ""
-#: engines/mohawk/riven.cpp:150
+#: engines/mohawk/riven.cpp:151
msgid ""
"Using the 'arcriven.z' installer file also works. In addition, you can use "
"the Mac 'Riven' executable."
msgstr ""
-#: engines/mohawk/riven.cpp:161
+#: engines/mohawk/riven.cpp:162
msgid ""
"You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also "
"works."
msgstr ""
-#: engines/mohawk/riven.cpp:432
+#: engines/mohawk/riven.cpp:448
msgid "You are missing the following required Riven data files:\n"
msgstr ""
@@ -3635,7 +3673,7 @@ msgid ""
"errors and/or issues later on."
msgstr ""
-#: engines/scumm/detection.cpp:1126
+#: engines/scumm/detection.cpp:1123
msgid ""
"Your game version appears to be unknown. If this is *NOT* a fan-modified\n"
"version (in particular, not a fan-made translation), please, report the\n"
@@ -3644,19 +3682,19 @@ msgid ""
"to add and its version, language, etc.:\n"
msgstr ""
-#: engines/scumm/detection.cpp:1144
+#: engines/scumm/detection.cpp:1141
msgid ""
"The Lite version of Putt-Putt Saves the Zoo iOS is not supported to avoid "
"piracy.\n"
"The full version is available for purchase from the iTunes Store."
msgstr ""
-#: engines/scumm/detection.cpp:1347
+#: engines/scumm/detection.cpp:1352
#, fuzzy
msgid "Show Object Line"
msgstr "Xianshi Wuti Biaoqian"
-#: engines/scumm/detection.cpp:1348
+#: engines/scumm/detection.cpp:1353
msgid "Show the names of objects at the bottom of the screen"
msgstr ""
@@ -4336,7 +4374,7 @@ msgstr ""
"Bendi MIDI Zhichi Xuyao Cong LucasArts Shengji Zhi Roland,\n"
"Dnahsi %s meiyou zhaodao. Shiyong AdLib."
-#: engines/scumm/scumm.cpp:2738
+#: engines/scumm/scumm.cpp:2740
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 "
@@ -4416,13 +4454,13 @@ msgstr "Ruanpan Jieshao"
msgid "Use the floppy version's intro (CD version only)"
msgstr "Shiyong Ruanpan Banben JIeshao (jin CD banben)"
-#: engines/supernova/supernova.cpp:308
+#: engines/supernova/supernova.cpp:193
#, c-format
msgid ""
"Incorrect version of the '%s' engine data file found. Expected %d but got %d."
msgstr ""
-#: engines/supernova/supernova.cpp:335
+#: engines/supernova/supernova.cpp:220
#, c-format
msgid "Unable to locate the text for %s language in '%s' engine data file."
msgstr ""
@@ -4544,25 +4582,39 @@ msgstr ""
msgid "Could not quick load the saved game #%d"
msgstr "Nin Yao Zairu Baocun de Youxi ma?"
-#: engines/wintermute/detection.cpp:58
+#: engines/wintermute/detection.cpp:59
msgid "Show FPS-counter"
msgstr "Xianshi FPS Jishuqi"
-#: engines/wintermute/detection.cpp:59
+#: engines/wintermute/detection.cpp:60
msgid "Show the current number of frames per second in the upper left corner"
msgstr "Zai Zuoshangjiao Xianshi Xianzai Meimiaozhong Zhenshu"
-#: engines/wintermute/detection.cpp:68
+#: engines/wintermute/detection.cpp:69
msgid "Sprite bilinear filtering (SLOW)"
msgstr ""
-#: engines/wintermute/detection.cpp:69
+#: engines/wintermute/detection.cpp:70
msgid "Apply bilinear filtering to individual sprites"
msgstr ""
-#: 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/xeen/detection.cpp:89
+msgid "Show item costs in standard inventory mode"
+msgstr ""
+
+#: engines/xeen/detection.cpp:90
+msgid ""
+"Shows item costs in standard inventory mode, allowing the value of items to "
+"be compared"
+msgstr ""
+
+#: engines/xeen/detection.cpp:99
+msgid "More durable armor"
+msgstr ""
+
+#: engines/xeen/detection.cpp:100
+msgid "Armor won't break until character is at -80HP, rather than merely -10HP"
+msgstr ""
#: engines/zvision/detection_tables.h:61
msgid "Double FPS"
@@ -4597,13 +4649,16 @@ msgstr "Shiyong Gaofenbianlv MPEG shipin"
msgid "Use MPEG video from the DVD version instead of lower resolution AVI"
msgstr "Cong DVD Banben Zhong shiyong MPEG shipin, erfei Difenbianlv AVI"
-#: engines/zvision/file/save_manager.cpp:220
+#: engines/zvision/file/save_manager.cpp:226
#, c-format
msgid ""
"This saved game uses version %u, but this engine only supports up to version "
"%d. You will need an updated version of the engine to use this saved game."
msgstr ""
+#~ msgid "Use the original save/load screens instead of the ScummVM interface"
+#~ msgstr "Shiyong Yuanshi baocun/zairu Pingmu Erfei ScummVM jiemian"
+
#, fuzzy
#~ msgid "Check for updates automatically"
#~ msgstr "Jiancha Gengxin..."
diff --git a/video/bink_decoder.cpp b/video/bink_decoder.cpp
index fbf75b48ee..6fca2c11c8 100644
--- a/video/bink_decoder.cpp
+++ b/video/bink_decoder.cpp
@@ -559,7 +559,7 @@ void BinkDecoder::BinkVideoTrack::mergeHuffmanSymbols(VideoFrame &video, byte *d
}
void BinkDecoder::BinkVideoTrack::initBundles() {
- uint32 bw = (_surface.w + 7) >> 3;
+ uint32 bw = (_surface.w + 7) >> 3;
uint32 bh = (_surface.h + 7) >> 3;
uint32 blocks = bw * bh;
diff --git a/video/flic_decoder.cpp b/video/flic_decoder.cpp
index a1976e2729..57d8fb5585 100644
--- a/video/flic_decoder.cpp
+++ b/video/flic_decoder.cpp
@@ -265,9 +265,9 @@ void FlicDecoder::FlicVideoTrack::copyFrame(uint8 *data) {
void FlicDecoder::FlicVideoTrack::decodeByteRun(uint8 *data) {
byte *ptr = (byte *)_surface->getPixels();
- while ((int32)(ptr - (byte *)_surface->getPixels()) < (getWidth() * getHeight())) {
- int chunks = *data++;
- while (chunks--) {
+ for (int i = 0; i < getHeight(); ++i) {
+ data++;
+ for (int j = 0; j < getWidth();) {
int count = (int8)*data++;
if (count > 0) {
memset(ptr, *data++, count);
@@ -277,6 +277,7 @@ void FlicDecoder::FlicVideoTrack::decodeByteRun(uint8 *data) {
data += count;
}
ptr += count;
+ j += count;
}
}
diff --git a/video/flic_decoder.h b/video/flic_decoder.h
index 445e474b87..3697fb2cb1 100644
--- a/video/flic_decoder.h
+++ b/video/flic_decoder.h
@@ -43,6 +43,7 @@ namespace Video {
*
* Video decoder used in engines:
* - chewy
+ * - prince
* - tucker
*/
class FlicDecoder : public VideoDecoder {