aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--AUTHORS6
-rw-r--r--Makefile9
-rw-r--r--Makefile.common3
-rw-r--r--NEWS7
-rw-r--r--audio/mixer.cpp21
-rw-r--r--audio/softsynth/fluidsynth.cpp2
-rw-r--r--audio/softsynth/mt32.cpp3
-rw-r--r--audio/softsynth/mt32/Part.cpp6
-rw-r--r--audio/softsynth/mt32/Partial.cpp1
-rw-r--r--audio/softsynth/mt32/Synth.cpp17
-rw-r--r--audio/softsynth/mt32/Synth.h8
-rw-r--r--audio/softsynth/mt32/TVA.cpp6
-rw-r--r--backends/events/default/default-events.cpp3
-rw-r--r--backends/events/sdl/sdl-events.cpp4
-rw-r--r--backends/graphics/opengl/gltexture.h4
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp23
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h3
-rw-r--r--backends/mixer/nullmixer/nullsdl-mixer.cpp75
-rw-r--r--backends/mixer/nullmixer/nullsdl-mixer.h62
-rw-r--r--backends/modular-backend.cpp11
-rw-r--r--backends/module.mk12
-rw-r--r--backends/mutex/sdl/sdl-mutex.cpp6
-rw-r--r--backends/platform/android/android.cpp2
-rw-r--r--backends/platform/android/android.h2
-rw-r--r--backends/platform/bada/bada.mk5
-rw-r--r--backends/platform/bada/form.cpp464
-rw-r--r--backends/platform/bada/form.h108
-rw-r--r--backends/platform/dc/dc.h2
-rw-r--r--backends/platform/dc/time.cpp2
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp2
-rw-r--r--backends/platform/ds/arm9/source/dsmain.h2
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.cpp2
-rw-r--r--backends/platform/ds/arm9/source/osystem_ds.h2
-rw-r--r--backends/platform/iphone/osys_main.cpp2
-rw-r--r--backends/platform/iphone/osys_main.h2
-rw-r--r--backends/platform/n64/osys_n64.h2
-rw-r--r--backends/platform/n64/osys_n64_base.cpp2
-rw-r--r--backends/platform/null/null.cpp2
-rw-r--r--backends/platform/ps2/systemps2.cpp2
-rw-r--r--backends/platform/ps2/systemps2.h2
-rw-r--r--backends/platform/psp/osys_psp.cpp2
-rw-r--r--backends/platform/psp/osys_psp.h2
-rw-r--r--backends/platform/psp/rtc.cpp2
-rw-r--r--backends/platform/psp/rtc.h2
-rw-r--r--backends/platform/sdl/sdl-sys.h3
-rw-r--r--backends/platform/sdl/sdl.cpp51
-rw-r--r--backends/platform/sdl/sdl.h3
-rw-r--r--backends/platform/tizen/README.TXT (renamed from backends/platform/bada/README.TXT)116
-rw-r--r--backends/platform/tizen/application.cpp (renamed from backends/platform/bada/application.cpp)79
-rw-r--r--backends/platform/tizen/application.h69
-rw-r--r--backends/platform/tizen/audio.cpp (renamed from backends/platform/bada/audio.cpp)111
-rw-r--r--backends/platform/tizen/audio.h (renamed from backends/platform/bada/audio.h)37
-rw-r--r--backends/platform/tizen/form.cpp419
-rw-r--r--backends/platform/tizen/form.h113
-rw-r--r--backends/platform/tizen/fs.cpp (renamed from backends/platform/bada/fs.cpp)294
-rw-r--r--backends/platform/tizen/fs.h (renamed from backends/platform/bada/fs.h)38
-rw-r--r--backends/platform/tizen/graphics.cpp (renamed from backends/platform/bada/graphics.cpp)108
-rw-r--r--backends/platform/tizen/graphics.h (renamed from backends/platform/bada/graphics.h)19
-rw-r--r--backends/platform/tizen/main.cpp (renamed from backends/platform/bada/main.cpp)36
-rw-r--r--backends/platform/tizen/missing.cpp (renamed from backends/platform/bada/missing.cpp)37
-rw-r--r--backends/platform/tizen/portdefs.h (renamed from backends/platform/bada/portdefs.h)12
-rw-r--r--backends/platform/tizen/sscanf.cpp (renamed from backends/platform/bada/sscanf.cpp)0
-rw-r--r--backends/platform/tizen/system.cpp (renamed from backends/platform/bada/system.cpp)287
-rw-r--r--backends/platform/tizen/system.h (renamed from backends/platform/bada/system.h)46
-rw-r--r--backends/platform/tizen/tizen.mk7
-rw-r--r--backends/platform/wii/osystem.cpp2
-rw-r--r--backends/platform/wii/osystem.h2
-rw-r--r--backends/saves/recorder/recorder-saves.cpp35
-rw-r--r--backends/saves/recorder/recorder-saves.h36
-rw-r--r--backends/timer/default/default-timer.cpp2
-rw-r--r--backends/timer/tizen/timer.cpp (renamed from backends/timer/bada/timer.cpp)50
-rw-r--r--backends/timer/tizen/timer.h (renamed from backends/timer/bada/timer.h)23
-rw-r--r--base/commandLine.cpp33
-rw-r--r--base/main.cpp39
-rw-r--r--common/EventDispatcher.cpp14
-rw-r--r--common/EventRecorder.cpp428
-rw-r--r--common/EventRecorder.h110
-rw-r--r--common/debug.h4
-rw-r--r--common/events.h12
-rw-r--r--common/macresman.cpp98
-rw-r--r--common/macresman.h25
-rw-r--r--common/memstream.h37
-rw-r--r--common/module.mk6
-rw-r--r--common/random.cpp13
-rw-r--r--common/recorderfile.cpp714
-rw-r--r--common/recorderfile.h180
-rw-r--r--common/str.cpp19
-rw-r--r--common/str.h5
-rw-r--r--common/system.cpp17
-rw-r--r--common/system.h18
-rw-r--r--common/util.h8
-rw-r--r--common/winexe_ne.cpp2
-rwxr-xr-xconfigure255
-rw-r--r--devtools/README7
-rw-r--r--devtools/create_kyradat/create_kyradat.cpp7
-rw-r--r--devtools/create_kyradat/pak.cpp2
-rw-r--r--devtools/create_lure/process_actions.cpp1
-rw-r--r--devtools/create_mortdat/create_mortdat.cpp225
-rw-r--r--devtools/create_mortdat/create_mortdat.h63
-rw-r--r--devtools/create_mortdat/enginetext.h189
-rw-r--r--devtools/create_mortdat/gametext.h1794
-rw-r--r--devtools/create_mortdat/module.mk11
-rw-r--r--devtools/create_neverhood/create_neverhood.cpp74
-rw-r--r--devtools/create_neverhood/tables.h2
-rw-r--r--devtools/create_project/create_project.cpp243
-rw-r--r--devtools/create_project/create_project.h10
-rw-r--r--devtools/create_project/msbuild.cpp62
-rw-r--r--devtools/create_project/msvc.cpp10
-rw-r--r--devtools/create_project/msvc.h7
-rw-r--r--devtools/create_project/msvc12/create_project.sln20
-rw-r--r--devtools/create_project/msvc12/create_project.vcxproj132
-rw-r--r--devtools/create_project/msvc12/create_project.vcxproj.filters71
-rw-r--r--devtools/create_project/visualstudio.cpp26
-rw-r--r--devtools/create_teenagent/static_tables.h2
-rwxr-xr-xdevtools/credits.pl8
-rw-r--r--devtools/extract_mort/extract_mort.cpp428
-rw-r--r--devtools/extract_mort/module.mk11
-rw-r--r--devtools/scumm-md5.txt1
-rw-r--r--devtools/skycpt/cptcompiler.cpp3
-rw-r--r--dists/engine-data/README5
-rw-r--r--dists/engine-data/mort.datbin0 -> 75737 bytes
-rw-r--r--dists/msvc10/create_msvc10.bat10
-rw-r--r--dists/msvc11/create_msvc11.bat10
-rw-r--r--dists/msvc12/create_msvc12.bat105
-rw-r--r--dists/msvc12/readme.txt6
-rw-r--r--dists/msvc8/create_msvc8.bat10
-rw-r--r--dists/msvc9/create_msvc9.bat10
-rw-r--r--dists/scummvm.rc3
-rw-r--r--dists/scummvm.rc.in3
-rw-r--r--engines/advancedDetector.cpp11
-rw-r--r--engines/advancedDetector.h3
-rw-r--r--engines/agi/agi.cpp4
-rw-r--r--engines/agi/preagi_troll.cpp2
-rw-r--r--engines/agi/preagi_winnie.cpp1
-rw-r--r--engines/cge/cge.cpp1
-rw-r--r--engines/cge/detection.cpp2
-rw-r--r--engines/cge/snail.cpp2
-rw-r--r--engines/configure.engines1
-rw-r--r--engines/drascula/drascula.h2
-rw-r--r--engines/dreamweb/dreamweb.cpp1
-rw-r--r--engines/dreamweb/monitor.cpp10
-rw-r--r--engines/dreamweb/print.cpp2
-rw-r--r--engines/engines.mk5
-rw-r--r--engines/gob/surface.cpp16
-rw-r--r--engines/groovie/stuffit.cpp2
-rw-r--r--engines/hopkins/computer.cpp53
-rw-r--r--engines/hopkins/computer.h2
-rw-r--r--engines/hopkins/dialogs.cpp2
-rw-r--r--engines/hopkins/globals.cpp4
-rw-r--r--engines/hopkins/globals.h1
-rw-r--r--engines/hopkins/graphics.cpp6
-rw-r--r--engines/hopkins/graphics.h2
-rw-r--r--engines/hopkins/hopkins.cpp4
-rw-r--r--engines/hopkins/saveload.cpp12
-rw-r--r--engines/hopkins/saveload.h3
-rw-r--r--engines/hugo/hugo.cpp2
-rw-r--r--engines/kyra/kyra_rpg.cpp2
-rw-r--r--engines/kyra/screen.cpp4
-rw-r--r--engines/lure/hotspots.cpp1
-rw-r--r--engines/mortevielle/actions.cpp1640
-rw-r--r--engines/mortevielle/debugger.cpp59
-rw-r--r--engines/mortevielle/debugger.h (renamed from backends/platform/bada/application.h)45
-rw-r--r--engines/mortevielle/detection.cpp101
-rw-r--r--engines/mortevielle/detection_tables.h88
-rw-r--r--engines/mortevielle/dialogs.cpp494
-rw-r--r--engines/mortevielle/dialogs.h65
-rw-r--r--engines/mortevielle/graphics.cpp1187
-rw-r--r--engines/mortevielle/graphics.h117
-rw-r--r--engines/mortevielle/menu.cpp599
-rw-r--r--engines/mortevielle/menu.h112
-rw-r--r--engines/mortevielle/module.mk24
-rw-r--r--engines/mortevielle/mortevielle.cpp445
-rw-r--r--engines/mortevielle/mortevielle.h522
-rw-r--r--engines/mortevielle/mouse.cpp273
-rw-r--r--engines/mortevielle/mouse.h56
-rw-r--r--engines/mortevielle/outtext.cpp330
-rw-r--r--engines/mortevielle/outtext.h49
-rw-r--r--engines/mortevielle/saveload.cpp328
-rw-r--r--engines/mortevielle/saveload.h73
-rw-r--r--engines/mortevielle/sound.cpp205
-rw-r--r--engines/mortevielle/sound.h115
-rw-r--r--engines/mortevielle/speech.cpp611
-rw-r--r--engines/mortevielle/speech.h106
-rw-r--r--engines/mortevielle/utils.cpp3497
-rw-r--r--engines/neverhood/background.cpp4
-rw-r--r--engines/neverhood/blbarchive.cpp16
-rw-r--r--engines/neverhood/console.cpp21
-rw-r--r--engines/neverhood/console.h1
-rw-r--r--engines/neverhood/diskplayerscene.cpp32
-rw-r--r--engines/neverhood/diskplayerscene.h6
-rw-r--r--engines/neverhood/entity.cpp20
-rw-r--r--engines/neverhood/entity.h2
-rw-r--r--engines/neverhood/gamemodule.cpp20
-rw-r--r--engines/neverhood/gamemodule.h2
-rw-r--r--engines/neverhood/gamevars.cpp2
-rw-r--r--engines/neverhood/gamevars.h2
-rw-r--r--engines/neverhood/graphics.cpp20
-rw-r--r--engines/neverhood/graphics.h4
-rw-r--r--engines/neverhood/klaymen.cpp400
-rw-r--r--engines/neverhood/klaymen.h30
-rw-r--r--engines/neverhood/menumodule.cpp56
-rw-r--r--engines/neverhood/menumodule.h8
-rw-r--r--engines/neverhood/module.cpp4
-rw-r--r--engines/neverhood/modules/module1000.cpp104
-rw-r--r--engines/neverhood/modules/module1000.h2
-rw-r--r--engines/neverhood/modules/module1100.cpp34
-rw-r--r--engines/neverhood/modules/module1200.cpp64
-rw-r--r--engines/neverhood/modules/module1300.cpp88
-rw-r--r--engines/neverhood/modules/module1400.cpp54
-rw-r--r--engines/neverhood/modules/module1500.cpp6
-rw-r--r--engines/neverhood/modules/module1600.cpp48
-rw-r--r--engines/neverhood/modules/module1700.cpp12
-rw-r--r--engines/neverhood/modules/module1700.h2
-rw-r--r--engines/neverhood/modules/module1800.cpp4
-rw-r--r--engines/neverhood/modules/module1900.cpp40
-rw-r--r--engines/neverhood/modules/module2000.cpp8
-rw-r--r--engines/neverhood/modules/module2100.cpp22
-rw-r--r--engines/neverhood/modules/module2100.h2
-rw-r--r--engines/neverhood/modules/module2200.cpp114
-rw-r--r--engines/neverhood/modules/module2200.h4
-rw-r--r--engines/neverhood/modules/module2300.cpp10
-rw-r--r--engines/neverhood/modules/module2400.cpp36
-rw-r--r--engines/neverhood/modules/module2500.cpp22
-rw-r--r--engines/neverhood/modules/module2600.cpp10
-rw-r--r--engines/neverhood/modules/module2700.cpp102
-rw-r--r--engines/neverhood/modules/module2700.h2
-rw-r--r--engines/neverhood/modules/module2800.cpp168
-rw-r--r--engines/neverhood/modules/module2800.h6
-rw-r--r--engines/neverhood/modules/module2900.cpp20
-rw-r--r--engines/neverhood/modules/module2900.h4
-rw-r--r--engines/neverhood/modules/module3000.cpp44
-rw-r--r--engines/neverhood/modules/module3000.h2
-rw-r--r--engines/neverhood/mouse.cpp50
-rw-r--r--engines/neverhood/mouse.h2
-rw-r--r--engines/neverhood/navigationscene.cpp44
-rw-r--r--engines/neverhood/neverhood.cpp12
-rw-r--r--engines/neverhood/neverhood.h4
-rw-r--r--engines/neverhood/palette.cpp14
-rw-r--r--engines/neverhood/resource.cpp58
-rw-r--r--engines/neverhood/resource.h4
-rw-r--r--engines/neverhood/resourceman.cpp2
-rw-r--r--engines/neverhood/saveload.cpp10
-rw-r--r--engines/neverhood/scene.cpp48
-rw-r--r--engines/neverhood/scene.h42
-rw-r--r--engines/neverhood/screen.cpp52
-rw-r--r--engines/neverhood/smackerplayer.cpp18
-rw-r--r--engines/neverhood/smackerplayer.h2
-rw-r--r--engines/neverhood/smackerscene.cpp8
-rw-r--r--engines/neverhood/sound.cpp26
-rw-r--r--engines/neverhood/sound.h30
-rw-r--r--engines/neverhood/sprite.cpp24
-rw-r--r--engines/neverhood/staticdata.cpp10
-rw-r--r--engines/neverhood/todo.txt45
-rw-r--r--engines/pegasus/neighborhood/neighborhood.cpp2
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp2
-rw-r--r--engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp2
-rw-r--r--engines/pegasus/neighborhood/norad/norad.cpp4
-rw-r--r--engines/pegasus/timers.cpp4
-rw-r--r--engines/plugins_table.h3
-rw-r--r--engines/saga/animation.cpp2
-rw-r--r--engines/saga/music.cpp2
-rw-r--r--engines/saga/sndres.cpp6
-rw-r--r--engines/sci/engine/kpathing.cpp2
-rw-r--r--engines/sci/engine/kstring.cpp2
-rw-r--r--engines/sci/graphics/frameout.cpp10
-rw-r--r--engines/sci/sound/midiparser_sci.cpp29
-rw-r--r--engines/sci/sound/midiparser_sci.h1
-rw-r--r--engines/scumm/detection_tables.h1
-rw-r--r--engines/scumm/imuse/imuse.cpp6
-rw-r--r--engines/scumm/input.cpp2
-rw-r--r--engines/scumm/insane/insane_enemy.cpp3
-rw-r--r--engines/scumm/player_mac.cpp10
-rw-r--r--engines/scumm/player_v3m.cpp2
-rw-r--r--engines/scumm/scumm-md5.h3
-rw-r--r--engines/sword1/animation.cpp56
-rw-r--r--engines/sword1/animation.h3
-rw-r--r--engines/sword2/animation.cpp55
-rw-r--r--engines/sword2/animation.h3
-rw-r--r--engines/sword25/gfx/dynamicbitmap.cpp4
-rw-r--r--engines/sword25/gfx/image/image.h2
-rw-r--r--engines/sword25/gfx/image/renderedimage.cpp81
-rw-r--r--engines/sword25/gfx/image/renderedimage.h3
-rw-r--r--engines/sword25/gfx/panel.cpp2
-rw-r--r--engines/sword25/gfx/renderobject.cpp2
-rw-r--r--engines/sword25/gfx/renderobject.h16
-rw-r--r--engines/sword25/gfx/renderobjectmanager.cpp6
-rw-r--r--engines/sword25/gfx/staticbitmap.cpp2
-rw-r--r--engines/sword25/util/pluto/pluto.cpp540
-rw-r--r--engines/teenagent/callbacks.cpp6
-rw-r--r--engines/teenagent/dialog.cpp2
-rw-r--r--engines/teenagent/resources.cpp3
-rw-r--r--engines/tinsel/handle.cpp2
-rw-r--r--engines/tinsel/rince.cpp3
-rw-r--r--engines/tinsel/scene.cpp2
-rw-r--r--engines/tony/gfxcore.cpp2
-rw-r--r--engines/tony/gfxcore.h2
-rw-r--r--engines/toon/character.cpp9
-rw-r--r--engines/toon/character.h1
-rw-r--r--engines/tsage/converse.cpp161
-rw-r--r--engines/tsage/converse.h11
-rw-r--r--engines/tsage/core.cpp39
-rw-r--r--engines/tsage/core.h5
-rw-r--r--engines/tsage/dialogs.cpp78
-rw-r--r--engines/tsage/globals.cpp36
-rw-r--r--engines/tsage/globals.h18
-rw-r--r--engines/tsage/graphics.cpp87
-rw-r--r--engines/tsage/graphics.h2
-rw-r--r--engines/tsage/ringworld/ringworld_scenes1.cpp1
-rw-r--r--engines/tsage/ringworld2/ringworld2_dialogs.cpp14
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.cpp967
-rw-r--r--engines/tsage/ringworld2/ringworld2_logic.h154
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.cpp522
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes0.h59
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.cpp401
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes1.h29
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes2.cpp17
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes2.h1
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes3.cpp874
-rw-r--r--engines/tsage/ringworld2/ringworld2_scenes3.h20
-rw-r--r--engines/tsage/ringworld2/ringworld2_speakers.cpp281
-rw-r--r--engines/tsage/ringworld2/ringworld2_speakers.h10
-rw-r--r--engines/tsage/saveload.h10
-rw-r--r--engines/tsage/user_interface.cpp9
-rw-r--r--engines/tucker/tucker.cpp13
-rw-r--r--engines/wintermute/ad/ad_response.cpp2
-rw-r--r--engines/wintermute/base/base_engine.cpp12
-rw-r--r--engines/wintermute/base/base_engine.h10
-rw-r--r--engines/wintermute/base/base_file_manager.cpp2
-rw-r--r--engines/wintermute/base/base_game.cpp34
-rw-r--r--engines/wintermute/base/base_game.h14
-rw-r--r--engines/wintermute/base/base_game_music.cpp108
-rw-r--r--engines/wintermute/base/base_game_music.h6
-rw-r--r--engines/wintermute/base/base_game_settings.cpp50
-rw-r--r--engines/wintermute/base/base_game_settings.h4
-rw-r--r--engines/wintermute/base/base_keyboard_state.h2
-rw-r--r--engines/wintermute/base/base_persistence_manager.cpp4
-rw-r--r--engines/wintermute/base/gfx/base_renderer.cpp14
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.cpp2
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp2
-rw-r--r--engines/wintermute/base/gfx/osystem/render_ticket.cpp4
-rw-r--r--engines/wintermute/base/gfx/osystem/render_ticket.h4
-rw-r--r--engines/wintermute/base/save_thumb_helper.cpp12
-rw-r--r--engines/wintermute/base/scriptables/script.cpp1
-rw-r--r--engines/wintermute/base/timer.cpp4
-rw-r--r--engines/wintermute/base/timer.h6
-rw-r--r--engines/wintermute/debugger.cpp4
-rw-r--r--engines/wintermute/debugger.h6
-rw-r--r--engines/wintermute/detection_tables.h61
-rw-r--r--engines/wintermute/platform_osystem.cpp9
-rw-r--r--engines/wintermute/video/video_theora_player.cpp4
-rw-r--r--engines/wintermute/video/video_theora_player.h2
-rw-r--r--engines/wintermute/wintermute.cpp8
-rw-r--r--graphics/cursorman.cpp7
-rw-r--r--graphics/cursorman.h6
-rw-r--r--graphics/scaler.h6
-rw-r--r--graphics/scaler/thumbnail_intern.cpp32
-rw-r--r--graphics/thumbnail.cpp118
-rw-r--r--graphics/thumbnail.h18
-rw-r--r--graphics/yuv_to_rgb.h15
-rw-r--r--gui/EventRecorder.cpp678
-rw-r--r--gui/EventRecorder.h238
-rw-r--r--gui/ThemeEngine.cpp35
-rw-r--r--gui/ThemeEngine.h13
-rw-r--r--gui/about.cpp4
-rw-r--r--gui/chooser.cpp1
-rw-r--r--gui/credits.h6
-rw-r--r--gui/dialog.h3
-rw-r--r--gui/editrecorddialog.cpp87
-rw-r--r--gui/editrecorddialog.h56
-rw-r--r--gui/gui-manager.cpp142
-rw-r--r--gui/gui-manager.h6
-rw-r--r--gui/launcher.cpp83
-rw-r--r--gui/launcher.h15
-rw-r--r--gui/module.mk8
-rw-r--r--gui/onscreendialog.cpp233
-rw-r--r--gui/onscreendialog.h66
-rw-r--r--gui/recorderdialog.cpp298
-rw-r--r--gui/recorderdialog.h81
-rw-r--r--gui/saveload-dialog.cpp2
-rw-r--r--gui/themes/default.inc1052
-rw-r--r--gui/themes/scummclassic.zipbin104059 -> 110000 bytes
-rw-r--r--gui/themes/scummclassic/classic_layout.stx128
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx104
-rw-r--r--gui/themes/scummmodern.zipbin1462338 -> 1485763 bytes
-rw-r--r--gui/themes/scummmodern/editbtn.bmpbin0 -> 3126 bytes
-rw-r--r--gui/themes/scummmodern/editbtn_small.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/fastreplay.bmpbin0 -> 3126 bytes
-rw-r--r--gui/themes/scummmodern/fastreplay_small.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/scummmodern_gfx.stx8
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx130
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx125
-rw-r--r--gui/themes/scummmodern/stopbtn.bmpbin0 -> 3126 bytes
-rw-r--r--gui/themes/scummmodern/stopbtn_small.bmpbin0 -> 822 bytes
-rw-r--r--gui/themes/scummmodern/switchbtn.bmpbin0 -> 3126 bytes
-rw-r--r--gui/themes/scummmodern/switchbtn_small.bmpbin0 -> 822 bytes
-rw-r--r--gui/widgets/edittext.cpp8
-rw-r--r--ports.mk4
-rw-r--r--test/common/hash-str.h164
-rw-r--r--test/common/huffman.h144
-rw-r--r--test/common/rendermode.h84
-rw-r--r--test/common/str.h8
-rw-r--r--test/common/util.h237
-rw-r--r--video/avi_decoder.cpp68
-rw-r--r--video/avi_decoder.h7
-rw-r--r--video/codecs/codec.h2
-rw-r--r--video/codecs/indeo3.cpp119
-rw-r--r--video/codecs/mpeg.cpp107
-rw-r--r--video/codecs/mpeg.h98
-rw-r--r--video/coktel_decoder.cpp8
-rw-r--r--video/module.mk5
411 files changed, 26211 insertions, 5815 deletions
diff --git a/.gitignore b/.gitignore
index a046909bbf..a74f45bec0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -93,6 +93,7 @@ project.xcworkspace
/dists/msvc*/*.SAV
/dists/msvc*/*.dat
/dists/msvc*/*.dll
+/dists/msvc*/test_runner.cpp
/doc/*.aux
/doc/*.dvi
diff --git a/AUTHORS b/AUTHORS
index e6a25b5b76..0a2d2c5fe1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -238,9 +238,6 @@ ScummVM Team
Andre Heider
Angus Lees
- BADA:
- Chris Warren-Smith
-
Dreamcast:
Marcus Comstedt
@@ -288,6 +285,9 @@ ScummVM Team
Jurgen Braam
Lars Persson
+ Tizen / BADA:
+ Chris Warren-Smith
+
WebOS:
Klaus Reimer
diff --git a/Makefile b/Makefile
index 28eaead4b4..09c38b2598 100644
--- a/Makefile
+++ b/Makefile
@@ -32,8 +32,10 @@ ifeq "$(HAVE_GCC)" "1"
# being helpful.
#CXXFLAGS+= -Wmissing-format-attribute
- # Disable RTTI and exceptions
+ifneq "$(BACKEND)" "tizen"
+ # Disable RTTI and exceptions. These settings cause tizen apps to crash
CXXFLAGS+= -fno-rtti -fno-exceptions
+endif
ifneq "$(HAVE_CLANG)" "1"
# enable checking of pointers returned by "new", but only when we do not
@@ -44,6 +46,11 @@ endif
ifeq "$(HAVE_CLANG)" "1"
CXXFLAGS+= -Wno-conversion -Wno-shorten-64-to-32 -Wno-sign-compare -Wno-four-char-constants
+ # We use a anonymous nested type declaration in an anonymous union in
+ # common/str.h. This is no standard construct and clang warns about it.
+ # It works for all our target systems though, thus we simply disable that
+ # warning.
+ CXXFLAGS+= -Wno-nested-anon-types
endif
ifeq "$(HAVE_ICC)" "1"
diff --git a/Makefile.common b/Makefile.common
index aec033f0c7..02c3408684 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -253,6 +253,9 @@ endif
ifdef ENABLE_LURE
DIST_FILES_ENGINEDATA+=lure.dat
endif
+ifdef ENABLE_MORTEVIELLE
+DIST_FILES_ENGINEDATA+=mort.dat
+endif
ifdef ENABLE_NEVERHOOD
DIST_FILES_ENGINEDATA+=neverhood.dat
endif
diff --git a/NEWS b/NEWS
index cf9a07e8cb..98757ad9ae 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,14 @@ For a more comprehensive changelog of the latest experimental code, see:
https://github.com/scummvm/scummvm/commits/
1.7.0 (????-??-??)
+ Gob:
+ - Improved video quality in Urban Runner
+
+ Broken Sword 1:
+ - Added back support for MPEG-2 videos
+ Broken Sword 2:
+ - Added back support for MPEG-2 videos
1.6.0 (2013-05-31)
New Games:
diff --git a/audio/mixer.cpp b/audio/mixer.cpp
index 8ff364b98d..9e6e4596e2 100644
--- a/audio/mixer.cpp
+++ b/audio/mixer.cpp
@@ -20,6 +20,8 @@
*
*/
+#include "gui/EventRecorder.h"
+
#include "common/util.h"
#include "common/system.h"
#include "common/textconsole.h"
@@ -427,6 +429,11 @@ void MixerImpl::pauseHandle(SoundHandle handle, bool paused) {
bool MixerImpl::isSoundIDActive(int id) {
Common::StackLock lock(_mutex);
+
+#ifdef ENABLE_EVENTRECORDER
+ g_eventRec.updateSubsystems();
+#endif
+
for (int i = 0; i != NUM_CHANNELS; i++)
if (_channels[i] && _channels[i]->getId() == id)
return true;
@@ -443,6 +450,11 @@ int MixerImpl::getSoundID(SoundHandle handle) {
bool MixerImpl::isSoundHandleActive(SoundHandle handle) {
Common::StackLock lock(_mutex);
+
+#ifdef ENABLE_EVENTRECORDER
+ g_eventRec.updateSubsystems();
+#endif
+
const int index = handle._val % NUM_CHANNELS;
return _channels[index] && _channels[index]->getHandle()._val == handle._val;
}
@@ -556,12 +568,12 @@ void Channel::pause(bool paused) {
_pauseLevel++;
if (_pauseLevel == 1)
- _pauseStartTime = g_system->getMillis();
+ _pauseStartTime = g_system->getMillis(true);
} else if (_pauseLevel > 0) {
_pauseLevel--;
if (!_pauseLevel) {
- _pauseTime = (g_system->getMillis() - _pauseStartTime);
+ _pauseTime = (g_system->getMillis(true) - _pauseStartTime);
_pauseStartTime = 0;
}
}
@@ -579,7 +591,7 @@ Timestamp Channel::getElapsedTime() {
if (isPaused())
delta = _pauseStartTime - _mixerTimeStamp;
else
- delta = g_system->getMillis() - _mixerTimeStamp - _pauseTime;
+ delta = g_system->getMillis(true) - _mixerTimeStamp - _pauseTime;
// Convert the number of samples into a time duration.
@@ -599,13 +611,12 @@ int Channel::mix(int16 *data, uint len) {
assert(_stream);
int res = 0;
-
if (_stream->endOfData()) {
// TODO: call drain method
} else {
assert(_converter);
_samplesConsumed = _samplesDecoded;
- _mixerTimeStamp = g_system->getMillis();
+ _mixerTimeStamp = g_system->getMillis(true);
_pauseTime = 0;
res = _converter->flow(*_stream, data, len, _volL, _volR);
_samplesDecoded += res;
diff --git a/audio/softsynth/fluidsynth.cpp b/audio/softsynth/fluidsynth.cpp
index 518e260175..efcf1be615 100644
--- a/audio/softsynth/fluidsynth.cpp
+++ b/audio/softsynth/fluidsynth.cpp
@@ -163,7 +163,7 @@ int MidiDriver_FluidSynth::open() {
Common::String interpolation = ConfMan.get("fluidsynth_misc_interpolation");
int interpMethod = FLUID_INTERP_4THORDER;
-
+
if (interpolation == "none") {
interpMethod = FLUID_INTERP_NONE;
} else if (interpolation == "linear") {
diff --git a/audio/softsynth/mt32.cpp b/audio/softsynth/mt32.cpp
index 00d0469356..29f5e3577c 100644
--- a/audio/softsynth/mt32.cpp
+++ b/audio/softsynth/mt32.cpp
@@ -62,7 +62,8 @@ protected:
// Callback for debug messages, in vprintf() format
void printDebug(const char *fmt, va_list list) {
- debug(4, fmt, list);
+ Common::String out = Common::String::vformat(fmt, list);
+ debug(4, "%s", out.c_str());
}
// Callbacks for reporting various errors and information
diff --git a/audio/softsynth/mt32/Part.cpp b/audio/softsynth/mt32/Part.cpp
index 62ba346c35..88404316eb 100644
--- a/audio/softsynth/mt32/Part.cpp
+++ b/audio/softsynth/mt32/Part.cpp
@@ -175,6 +175,7 @@ void Part::refresh() {
patchCache[t].reverb = patchTemp->patch.reverbSwitch > 0;
}
memcpy(currentInstr, timbreTemp->common.name, 10);
+ synth->newTimbreSet(partNum, patchTemp->patch.timbreGroup, currentInstr);
updatePitchBenderRange();
}
@@ -207,7 +208,6 @@ void RhythmPart::setTimbre(TimbreParam * /*timbre*/) {
void Part::setTimbre(TimbreParam *timbre) {
*timbreTemp = *timbre;
- synth->newTimbreSet(partNum, timbre->common.name);
}
unsigned int RhythmPart::getAbsTimbreNum() const {
@@ -533,7 +533,6 @@ void Part::playPoly(const PatchCache cache[4], const MemParams::RhythmTemp *rhyt
#if MT32EMU_MONITOR_PARTIALS > 1
synth->printPartialUsage();
#endif
- synth->partStateChanged(partNum, true);
synth->polyStateChanged(partNum);
}
@@ -614,9 +613,6 @@ void Part::partialDeactivated(Poly *poly) {
freePolys.prepend(poly);
synth->polyStateChanged(partNum);
}
- if (activePartialCount == 0) {
- synth->partStateChanged(partNum, false);
- }
}
//#define POLY_LIST_DEBUG
diff --git a/audio/softsynth/mt32/Partial.cpp b/audio/softsynth/mt32/Partial.cpp
index a0aec90ec4..b80a028515 100644
--- a/audio/softsynth/mt32/Partial.cpp
+++ b/audio/softsynth/mt32/Partial.cpp
@@ -87,7 +87,6 @@ void Partial::deactivate() {
if (poly != NULL) {
poly->partialDeactivated(this);
}
- synth->partialStateChanged(this, tva->getPhase(), TVA_PHASE_DEAD);
#if MT32EMU_MONITOR_PARTIALS > 2
synth->printDebug("[+%lu] [Partial %d] Deactivated", sampleNum, debugPartialNum);
synth->printPartialUsage(sampleNum);
diff --git a/audio/softsynth/mt32/Synth.cpp b/audio/softsynth/mt32/Synth.cpp
index b7af992b99..1e1be06bc9 100644
--- a/audio/softsynth/mt32/Synth.cpp
+++ b/audio/softsynth/mt32/Synth.cpp
@@ -201,25 +201,12 @@ void ReportHandler::printDebug(const char *fmt, va_list list) {
printf("\n");
}
-void Synth::partStateChanged(int partNum, bool isPartActive) {
- reportHandler->onPartStateChanged(partNum, isPartActive);
-}
-
void Synth::polyStateChanged(int partNum) {
reportHandler->onPolyStateChanged(partNum);
}
-void Synth::partialStateChanged(const Partial * const partial, int oldPartialPhase, int newPartialPhase) {
- for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
- if (getPartial(i) == partial) {
- reportHandler->onPartialStateChanged(i, oldPartialPhase, newPartialPhase);
- break;
- }
- }
-}
-
-void Synth::newTimbreSet(int partNum, char patchName[]) {
- reportHandler->onProgramChanged(partNum, patchName);
+void Synth::newTimbreSet(int partNum, Bit8u timbreGroup, const char patchName[]) {
+ reportHandler->onProgramChanged(partNum, timbreGroup, patchName);
}
void Synth::printDebug(const char *fmt, ...) {
diff --git a/audio/softsynth/mt32/Synth.h b/audio/softsynth/mt32/Synth.h
index 56e88e6156..b85e7ae507 100644
--- a/audio/softsynth/mt32/Synth.h
+++ b/audio/softsynth/mt32/Synth.h
@@ -249,10 +249,10 @@ protected:
virtual void onNewReverbMode(Bit8u /* mode */) {}
virtual void onNewReverbTime(Bit8u /* time */) {}
virtual void onNewReverbLevel(Bit8u /* level */) {}
- virtual void onPartStateChanged(int /* partNum */, bool /* isActive */) {}
+ virtual void onPartStateChanged(int /* partNum */, bool /* hasActiveNonReleasingPolys */) {}
virtual void onPolyStateChanged(int /* partNum */) {}
virtual void onPartialStateChanged(int /* partialNum */, int /* oldPartialPhase */, int /* newPartialPhase */) {}
- virtual void onProgramChanged(int /* partNum */, char * /* patchName */) {}
+ virtual void onProgramChanged(int /* partNum */, int /* bankNum */, const char * /* patchName */) {}
};
class Synth {
@@ -370,10 +370,8 @@ private:
void printPartialUsage(unsigned long sampleOffset = 0);
- void partStateChanged(int partNum, bool isPartActive);
void polyStateChanged(int partNum);
- void partialStateChanged(const Partial * const partial, int oldPartialPhase, int newPartialPhase);
- void newTimbreSet(int partNum, char patchName[]);
+ void newTimbreSet(int partNum, Bit8u timbreGroup, const char patchName[]);
void printDebug(const char *fmt, ...);
public:
diff --git a/audio/softsynth/mt32/TVA.cpp b/audio/softsynth/mt32/TVA.cpp
index 65e5256048..5438471fa4 100644
--- a/audio/softsynth/mt32/TVA.cpp
+++ b/audio/softsynth/mt32/TVA.cpp
@@ -34,9 +34,6 @@ TVA::TVA(const Partial *usePartial, LA32Ramp *useAmpRamp) :
}
void TVA::startRamp(Bit8u newTarget, Bit8u newIncrement, int newPhase) {
- if (newPhase != phase) {
- partial->getSynth()->partialStateChanged(partial, phase, newPhase);
- }
target = newTarget;
phase = newPhase;
ampRamp->startRamp(newTarget, newIncrement);
@@ -46,9 +43,6 @@ void TVA::startRamp(Bit8u newTarget, Bit8u newIncrement, int newPhase) {
}
void TVA::end(int newPhase) {
- if (newPhase != phase) {
- partial->getSynth()->partialStateChanged(partial, phase, newPhase);
- }
phase = newPhase;
playing = false;
#if MT32EMU_MONITOR_TVA >= 1
diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 38a0c8d46f..bf76bbc1cb 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -84,7 +84,8 @@ void DefaultEventManager::init() {
}
bool DefaultEventManager::pollEvent(Common::Event &event) {
- uint32 time = g_system->getMillis();
+ // Skip recording of these events
+ uint32 time = g_system->getMillis(true);
bool result = false;
_dispatcher.dispatch();
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index 0ca5bbb059..e2ef7f6bf6 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -106,7 +106,9 @@ void SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) {
}
void SdlEventSource::handleKbdMouse() {
- uint32 curTime = g_system->getMillis();
+ // Skip recording of these events
+ uint32 curTime = g_system->getMillis(true);
+
if (curTime >= _km.last_time + _km.delay_time) {
_km.last_time = curTime;
if (_km.x_down_count == 1) {
diff --git a/backends/graphics/opengl/gltexture.h b/backends/graphics/opengl/gltexture.h
index 8ff9838ff7..6ef80923ae 100644
--- a/backends/graphics/opengl/gltexture.h
+++ b/backends/graphics/opengl/gltexture.h
@@ -44,9 +44,9 @@
#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
#endif
-#if defined(BADA)
+#if defined(TIZEN)
#include <FGraphicsOpengl.h>
-using namespace Osp::Graphics::Opengl;
+using namespace Tizen::Graphics::Opengl;
#elif defined(USE_GLES)
#include <GLES/gl.h>
#elif defined(SDL_BACKEND)
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 02e58ab319..a2e1981e79 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -40,6 +40,7 @@
#include "graphics/scaler.h"
#include "graphics/scaler/aspect.h"
#include "graphics/surface.h"
+#include "gui/EventRecorder.h"
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
{"1x", _s("Normal (no scaling)"), GFX_NORMAL},
@@ -135,6 +136,7 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
_paletteDirtyStart(0), _paletteDirtyEnd(0),
_screenIsLocked(false),
_graphicsMutex(0),
+ _displayDisabled(false),
#ifdef USE_SDL_DEBUG_FOCUSRECT
_enableFocusRectDebugCode(false), _enableFocusRect(false), _focusRect(),
#endif
@@ -765,9 +767,20 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
fixupResolutionForAspectRatio(_videoMode.desiredAspectRatio, _videoMode.hardwareWidth, _videoMode.hardwareHeight);
}
- _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
- _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
- );
+
+#ifdef ENABLE_EVENTRECORDER
+ _displayDisabled = ConfMan.getBool("disable_display");
+
+ if (_displayDisabled) {
+ _hwscreen = g_eventRec.getSurface(_videoMode.hardwareWidth, _videoMode.hardwareHeight);
+ } else
+#endif
+ {
+ _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
+ _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
+ );
+ }
+
#ifdef USE_RGB_COLOR
detectSupportedFormats();
#endif
@@ -1188,7 +1201,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
#endif
// Finally, blit all our changes to the screen
- SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+ if (!_displayDisabled) {
+ SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+ }
}
_numDirtyRects = 0;
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index 21444cc25d..97de0f9c97 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -232,6 +232,9 @@ protected:
int _scalerType;
int _transactionMode;
+ // Indicates whether it is needed to free _hwsurface in destructor
+ bool _displayDisabled;
+
bool _screenIsLocked;
Graphics::Surface _framebuffer;
diff --git a/backends/mixer/nullmixer/nullsdl-mixer.cpp b/backends/mixer/nullmixer/nullsdl-mixer.cpp
new file mode 100644
index 0000000000..2fd652e19f
--- /dev/null
+++ b/backends/mixer/nullmixer/nullsdl-mixer.cpp
@@ -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.
+ *
+ */
+
+#include "backends/mixer/nullmixer/nullsdl-mixer.h"
+#include "common/savefile.h"
+
+NullSdlMixerManager::NullSdlMixerManager() : SdlMixerManager() {
+ _outputRate = 22050;
+ _callsCounter = 0;
+ _callbackPeriod = 10;
+ _samples = 8192;
+ while (_samples * 16 > _outputRate * 2)
+ _samples >>= 1;
+ _samplesBuf = new uint8[_samples * 4];
+}
+
+NullSdlMixerManager::~NullSdlMixerManager() {
+ delete _samplesBuf;
+}
+
+void NullSdlMixerManager::init() {
+ _mixer = new Audio::MixerImpl(g_system, _outputRate);
+ assert(_mixer);
+ _mixer->setReady(true);
+}
+
+void NullSdlMixerManager::suspendAudio() {
+ _audioSuspended = true;
+}
+
+int NullSdlMixerManager::resumeAudio() {
+ if (!_audioSuspended) {
+ return -2;
+ }
+ _audioSuspended = false;
+ return 0;
+}
+
+
+void NullSdlMixerManager::startAudio() {
+}
+
+void NullSdlMixerManager::callbackHandler(byte *samples, int len) {
+ assert(_mixer);
+ _mixer->mixCallback(samples, len);
+}
+
+void NullSdlMixerManager::update() {
+ if (_audioSuspended) {
+ return;
+ }
+ _callsCounter++;
+ if ((_callsCounter % _callbackPeriod) == 0) {
+ callbackHandler(_samplesBuf, _samples);
+ }
+}
diff --git a/backends/mixer/nullmixer/nullsdl-mixer.h b/backends/mixer/nullmixer/nullsdl-mixer.h
new file mode 100644
index 0000000000..94248ced66
--- /dev/null
+++ b/backends/mixer/nullmixer/nullsdl-mixer.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_MIXER_NULLSDL_H
+#define BACKENDS_MIXER_NULLSDL_H
+
+#include "backends/mixer/sdl/sdl-mixer.h"
+#include "common/str.h"
+
+/** Audio mixer which in fact does not output audio.
+ *
+ * It is used by events recorder since the recorder is intentionally
+ * turning sound off to avoid stuttering.
+ *
+ * It returns correct output and shoots callbacks, so all OSystem
+ * users could work without modifications.
+ */
+
+class NullSdlMixerManager : public SdlMixerManager {
+public:
+ NullSdlMixerManager();
+ virtual ~NullSdlMixerManager();
+
+ virtual void init();
+ void update();
+
+ virtual void suspendAudio();
+ virtual int resumeAudio();
+
+protected:
+
+ virtual void startAudio();
+ virtual void callbackHandler(byte *samples, int len);
+
+private:
+ uint32 _outputRate;
+ uint32 _callsCounter;
+ uint8 _callbackPeriod;
+ uint32 _samples;
+ uint8 *_samplesBuf;
+};
+
+#endif
diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp
index b46f33a2bc..6afe06aeca 100644
--- a/backends/modular-backend.cpp
+++ b/backends/modular-backend.cpp
@@ -26,6 +26,7 @@
#include "backends/graphics/graphics.h"
#include "backends/mutex/mutex.h"
+#include "gui/EventRecorder.h"
#include "audio/mixer.h"
#include "graphics/pixelformat.h"
@@ -52,7 +53,7 @@ bool ModularBackend::hasFeature(Feature f) {
}
void ModularBackend::setFeatureState(Feature f, bool enable) {
- return _graphicsManager->setFeatureState(f, enable);
+ _graphicsManager->setFeatureState(f, enable);
}
bool ModularBackend::getFeatureState(Feature f) {
@@ -141,7 +142,15 @@ void ModularBackend::fillScreen(uint32 col) {
}
void ModularBackend::updateScreen() {
+#ifdef ENABLE_EVENTRECORDER
+ g_eventRec.preDrawOverlayGui();
+#endif
+
_graphicsManager->updateScreen();
+
+#ifdef ENABLE_EVENTRECORDER
+ g_eventRec.postDrawOverlayGui();
+#endif
}
void ModularBackend::setShakePos(int shakeOffset) {
diff --git a/backends/module.mk b/backends/module.mk
index a4f525d21d..31ac444750 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -70,7 +70,7 @@ MODULE_OBJS += \
mutex/sdl/sdl-mutex.o \
plugins/sdl/sdl-provider.o \
timer/sdl/sdl-timer.o
-
+
# SDL 1.3 removed audio CD support
ifndef USE_SDL13
MODULE_OBJS += \
@@ -120,9 +120,9 @@ MODULE_OBJS += \
mixer/sdl13/sdl13-mixer.o
endif
-ifeq ($(BACKEND),bada)
+ifeq ($(BACKEND),tizen)
MODULE_OBJS += \
- timer/bada/timer.o
+ timer/tizen/timer.o
endif
ifeq ($(BACKEND),ds)
@@ -214,5 +214,11 @@ MODULE_OBJS += \
plugins/wii/wii-provider.o
endif
+ifdef ENABLE_EVENTRECORDER
+MODULE_OBJS += \
+ mixer/nullmixer/nullsdl-mixer.o \
+ saves/recorder/recorder-saves.o
+endif
+
# Include common rules
include $(srcdir)/rules.mk
diff --git a/backends/mutex/sdl/sdl-mutex.cpp b/backends/mutex/sdl/sdl-mutex.cpp
index 8491ae468c..a51e6f0e38 100644
--- a/backends/mutex/sdl/sdl-mutex.cpp
+++ b/backends/mutex/sdl/sdl-mutex.cpp
@@ -33,15 +33,15 @@ OSystem::MutexRef SdlMutexManager::createMutex() {
}
void SdlMutexManager::lockMutex(OSystem::MutexRef mutex) {
- SDL_mutexP((SDL_mutex *) mutex);
+ SDL_mutexP((SDL_mutex *)mutex);
}
void SdlMutexManager::unlockMutex(OSystem::MutexRef mutex) {
- SDL_mutexV((SDL_mutex *) mutex);
+ SDL_mutexV((SDL_mutex *)mutex);
}
void SdlMutexManager::deleteMutex(OSystem::MutexRef mutex) {
- SDL_DestroyMutex((SDL_mutex *) mutex);
+ SDL_DestroyMutex((SDL_mutex *)mutex);
}
#endif
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index f06e4be19e..ad80ea7f8c 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -450,7 +450,7 @@ bool OSystem_Android::getFeatureState(Feature f) {
}
}
-uint32 OSystem_Android::getMillis() {
+uint32 OSystem_Android::getMillis(bool skipRecord) {
timeval curTime;
gettimeofday(&curTime, 0);
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 5f2f40b726..b4813b3bdf 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -274,7 +274,7 @@ public:
virtual void setCursorPalette(const byte *colors, uint start, uint num);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual MutexRef createMutex(void);
diff --git a/backends/platform/bada/bada.mk b/backends/platform/bada/bada.mk
deleted file mode 100644
index 7c72d7752b..0000000000
--- a/backends/platform/bada/bada.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bada specific modules are built under eclipse
-
-$(EXECUTABLE): $(OBJS)
- rm -f $@
- ar Tru $@ $(OBJS)
diff --git a/backends/platform/bada/form.cpp b/backends/platform/bada/form.cpp
deleted file mode 100644
index dfa72bce08..0000000000
--- a/backends/platform/bada/form.cpp
+++ /dev/null
@@ -1,464 +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 <FAppApplication.h>
-
-#include "common/translation.h"
-#include "base/main.h"
-
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-
-using namespace Osp::Base::Runtime;
-using namespace Osp::Ui;
-using namespace Osp::Ui::Controls;
-
-// number of volume levels
-#define LEVEL_RANGE 5
-
-// round down small Y touch values to 1 to allow the
-// cursor to be positioned at the top of the screen
-#define MIN_TOUCH_Y 10
-
-// block for up to 2.5 seconds during shutdown to
-// allow the game thread to exit gracefully.
-#define EXIT_SLEEP_STEP 10
-#define EXIT_SLEEP 250
-
-//
-// BadaAppForm
-//
-BadaAppForm::BadaAppForm() :
- _gameThread(0),
- _state(kInitState),
- _buttonState(kLeftButton),
- _shortcut(kSetVolume) {
- _eventQueueLock = new Mutex();
- _eventQueueLock->Create();
-}
-
-result BadaAppForm::Construct() {
- result r = Form::Construct(Controls::FORM_STYLE_NORMAL);
- if (IsFailed(r)) {
- return r;
- }
-
- BadaSystem *badaSystem = NULL;
- _gameThread = NULL;
-
- badaSystem = new BadaSystem(this);
- r = badaSystem != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
-
- if (!IsFailed(r)) {
- r = badaSystem->Construct();
- }
-
- if (!IsFailed(r)) {
- _gameThread = new Thread();
- r = _gameThread != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
- }
-
- if (!IsFailed(r)) {
- r = _gameThread->Construct(*this);
- }
-
- if (IsFailed(r)) {
- if (badaSystem != NULL) {
- delete badaSystem;
- }
- if (_gameThread != NULL) {
- delete _gameThread;
- _gameThread = NULL;
- }
- } else {
- g_system = badaSystem;
- }
-
- return r;
-}
-
-BadaAppForm::~BadaAppForm() {
- logEntered();
-
- if (_gameThread && _state != kErrorState) {
- terminate();
-
- _gameThread->Stop();
- if (_state != kErrorState) {
- _gameThread->Join();
- }
-
- delete _gameThread;
- _gameThread = NULL;
- }
-
- if (_eventQueueLock) {
- delete _eventQueueLock;
- _eventQueueLock = NULL;
- }
-
- logLeaving();
-}
-
-//
-// abort the game thread
-//
-void BadaAppForm::terminate() {
- if (_state == kActiveState) {
- ((BadaSystem *)g_system)->setMute(true);
-
- _eventQueueLock->Acquire();
-
- Common::Event e;
- e.type = Common::EVENT_QUIT;
- _eventQueue.push(e);
- _state = kClosingState;
-
- _eventQueueLock->Release();
-
- // block while thread ends
- AppLog("waiting for shutdown");
- for (int i = 0; i < EXIT_SLEEP_STEP && _state == kClosingState; i++) {
- Thread::Sleep(EXIT_SLEEP);
- }
-
- if (_state == kClosingState) {
- // failed to terminate - Join() will freeze
- _state = kErrorState;
- }
- }
-}
-
-void BadaAppForm::exitSystem() {
- _state = kErrorState;
-
- if (_gameThread) {
- _gameThread->Stop();
- delete _gameThread;
- _gameThread = NULL;
- }
-}
-
-result BadaAppForm::OnInitializing(void) {
- logEntered();
-
- SetOrientation(ORIENTATION_LANDSCAPE);
- AddOrientationEventListener(*this);
- AddTouchEventListener(*this);
- AddKeyEventListener(*this);
-
- // set focus to enable receiving key events
- SetFocusable(true);
- SetFocus();
-
- return E_SUCCESS;
-}
-
-result BadaAppForm::OnDraw(void) {
- logEntered();
-
- if (g_system) {
- BadaSystem *system = (BadaSystem *)g_system;
- BadaGraphicsManager *graphics = system->getGraphics();
- if (graphics && graphics->isReady()) {
- g_system->updateScreen();
- }
- }
-
- return E_SUCCESS;
-}
-
-bool BadaAppForm::pollEvent(Common::Event &event) {
- bool result = false;
-
- _eventQueueLock->Acquire();
- if (!_eventQueue.empty()) {
- event = _eventQueue.pop();
- result = true;
- }
- _eventQueueLock->Release();
-
- return result;
-}
-
-void BadaAppForm::pushEvent(Common::EventType type, const Point &currentPosition) {
- BadaSystem *system = (BadaSystem *)g_system;
- BadaGraphicsManager *graphics = system->getGraphics();
- if (graphics) {
- // graphics could be NULL at startup or when
- // displaying the system error screen
- Common::Event e;
- e.type = type;
- e.mouse.x = currentPosition.x;
- e.mouse.y = currentPosition.y > MIN_TOUCH_Y ? currentPosition.y : 1;
-
- bool moved = graphics->moveMouse(e.mouse.x, e.mouse.y);
-
- _eventQueueLock->Acquire();
-
- if (moved && type != Common::EVENT_MOUSEMOVE) {
- Common::Event moveEvent;
- moveEvent.type = Common::EVENT_MOUSEMOVE;
- moveEvent.mouse = e.mouse;
- _eventQueue.push(moveEvent);
- }
-
- _eventQueue.push(e);
- _eventQueueLock->Release();
- }
-}
-
-void BadaAppForm::pushKey(Common::KeyCode keycode) {
- Common::Event e;
- e.synthetic = false;
- e.kbd.keycode = keycode;
- e.kbd.ascii = keycode;
- e.kbd.flags = 0;
-
- _eventQueueLock->Acquire();
-
- e.type = Common::EVENT_KEYDOWN;
- _eventQueue.push(e);
- e.type = Common::EVENT_KEYUP;
- _eventQueue.push(e);
-
- _eventQueueLock->Release();
-}
-
-void BadaAppForm::OnOrientationChanged(const Control &source,
- OrientationStatus orientationStatus) {
- logEntered();
- if (_state == kInitState) {
- _state = kActiveState;
- _gameThread->Start();
- }
-}
-
-Object *BadaAppForm::Run(void) {
- scummvm_main(0, 0);
-
- if (_state == kActiveState) {
- Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT, NULL);
- }
- _state = kDoneState;
- return NULL;
-}
-
-void BadaAppForm::setButtonShortcut() {
- switch (_buttonState) {
- case kLeftButton:
- g_system->displayMessageOnOSD(_("Right Click Once"));
- _buttonState = kRightButtonOnce;
- break;
- case kRightButtonOnce:
- g_system->displayMessageOnOSD(_("Right Click"));
- _buttonState = kRightButton;
- break;
- case kRightButton:
- g_system->displayMessageOnOSD(_("Move Only"));
- _buttonState = kMoveOnly;
- break;
- case kMoveOnly:
- g_system->displayMessageOnOSD(_("Left Click"));
- _buttonState = kLeftButton;
- break;
- }
-}
-
-void BadaAppForm::setShortcut() {
- // cycle to the next shortcut
- switch (_shortcut) {
- case kControlMouse:
- g_system->displayMessageOnOSD(_("Escape Key"));
- _shortcut = kEscapeKey;
- break;
-
- case kEscapeKey:
- g_system->displayMessageOnOSD(_("Game Menu"));
- _shortcut = kGameMenu;
- break;
-
- case kGameMenu:
- g_system->displayMessageOnOSD(_("Show Keypad"));
- _shortcut = kShowKeypad;
- break;
-
- case kSetVolume:
- // fallthru
-
- case kShowKeypad:
- g_system->displayMessageOnOSD(_("Control Mouse"));
- _shortcut = kControlMouse;
- break;
- }
-}
-
-void BadaAppForm::setVolume(bool up, bool minMax) {
- int level = ((BadaSystem *)g_system)->setVolume(up, minMax);
- if (level != -1) {
- char message[32];
- char ind[LEVEL_RANGE]; // 1..5 (0=off)
- int j = LEVEL_RANGE - 1; // 0..4
- for (int i = 1; i <= LEVEL_RANGE; i++) {
- ind[j--] = level >= i ? '|' : ' ';
- }
- snprintf(message, sizeof(message), "Volume: [ %c%c%c%c%c ]",
- ind[0], ind[1], ind[2], ind[3], ind[4]);
- g_system->displayMessageOnOSD(message);
- }
-}
-
-void BadaAppForm::showKeypad() {
- // display the soft keyboard
- _buttonState = kLeftButton;
- pushKey(Common::KEYCODE_F7);
-}
-
-void BadaAppForm::OnTouchDoublePressed(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- if (_buttonState != kMoveOnly) {
- pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
- currentPosition);
- pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
- currentPosition);
- }
-}
-
-void BadaAppForm::OnTouchFocusIn(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
-}
-
-void BadaAppForm::OnTouchFocusOut(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
-}
-
-void BadaAppForm::OnTouchLongPressed(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- if (_buttonState != kLeftButton) {
- pushKey(Common::KEYCODE_RETURN);
- }
-}
-
-void BadaAppForm::OnTouchMoved(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- pushEvent(Common::EVENT_MOUSEMOVE, currentPosition);
-}
-
-void BadaAppForm::OnTouchPressed(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- if (_buttonState != kMoveOnly) {
- pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
- currentPosition);
- }
-}
-
-void BadaAppForm::OnTouchReleased(const Control &source,
- const Point &currentPosition,
- const TouchEventInfo &touchInfo) {
- if (_buttonState != kMoveOnly) {
- pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONUP : Common::EVENT_RBUTTONUP,
- currentPosition);
- if (_buttonState == kRightButtonOnce) {
- _buttonState = kLeftButton;
- }
- // flick to skip dialog
- if (touchInfo.IsFlicked()) {
- pushKey(Common::KEYCODE_PERIOD);
- }
- }
-}
-
-void BadaAppForm::OnKeyLongPressed(const Control &source, KeyCode keyCode) {
- logEntered();
- switch (keyCode) {
- case KEY_SIDE_UP:
- _shortcut = kSetVolume;
- setVolume(true, true);
- return;
-
- case KEY_SIDE_DOWN:
- _shortcut = kSetVolume;
- setVolume(false, true);
- return;
-
- case KEY_CAMERA:
- _shortcut = kShowKeypad;
- showKeypad();
- return;
-
- default:
- break;
- }
-}
-
-void BadaAppForm::OnKeyPressed(const Control &source, KeyCode keyCode) {
- switch (keyCode) {
- case KEY_SIDE_UP:
- if (_shortcut != kSetVolume) {
- _shortcut = kSetVolume;
- } else {
- setVolume(true, false);
- }
- return;
-
- case KEY_SIDE_DOWN:
- switch (_shortcut) {
- case kControlMouse:
- setButtonShortcut();
- break;
-
- case kEscapeKey:
- pushKey(Common::KEYCODE_ESCAPE);
- break;
-
- case kGameMenu:
- _buttonState = kLeftButton;
- pushKey(Common::KEYCODE_F5);
- break;
-
- case kShowKeypad:
- showKeypad();
- break;
-
- default:
- setVolume(false, false);
- break;
- }
- break;
-
- case KEY_CAMERA:
- setShortcut();
- break;
-
- default:
- break;
- }
-}
-
-void BadaAppForm::OnKeyReleased(const Control &source, KeyCode keyCode) {
-}
diff --git a/backends/platform/bada/form.h b/backends/platform/bada/form.h
deleted file mode 100644
index 3340e2216b..0000000000
--- a/backends/platform/bada/form.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef BADA_FORM_H
-#define BADA_FORM_H
-
-#include <FApp.h>
-#include <FUi.h>
-#include <FSystem.h>
-#include <FBase.h>
-#include <FUiITouchEventListener.h>
-#include <FUiITextEventListener.h>
-
-#include "config.h"
-#include "common/scummsys.h"
-#include "common/events.h"
-#include "common/queue.h"
-#include "common/mutex.h"
-
-//
-// BadaAppForm
-//
-class BadaAppForm : public Osp::Ui::Controls::Form,
- public Osp::Ui::IOrientationEventListener,
- public Osp::Ui::ITouchEventListener,
- public Osp::Ui::IKeyEventListener,
- public Osp::Base::Runtime::IRunnable {
-public:
- BadaAppForm();
- ~BadaAppForm();
-
- result Construct();
- bool pollEvent(Common::Event &event);
- bool isClosing() { return _state == kClosingState; }
- void pushKey(Common::KeyCode keycode);
- void exitSystem();
-
-private:
- Object *Run();
- result OnInitializing(void);
- result OnDraw(void);
- void OnOrientationChanged(const Osp::Ui::Control &source,
- Osp::Ui::OrientationStatus orientationStatus);
- void OnTouchDoublePressed(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchFocusIn(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchFocusOut(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchLongPressed(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchMoved(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchPressed(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnTouchReleased(const Osp::Ui::Control &source,
- const Osp::Graphics::Point &currentPosition,
- const Osp::Ui::TouchEventInfo &touchInfo);
- void OnKeyLongPressed(const Osp::Ui::Control &source,
- Osp::Ui::KeyCode keyCode);
- void OnKeyPressed(const Osp::Ui::Control &source,
- Osp::Ui::KeyCode keyCode);
- void OnKeyReleased(const Osp::Ui::Control &source,
- Osp::Ui::KeyCode keyCode);
-
- void pushEvent(Common::EventType type,
- const Osp::Graphics::Point &currentPosition);
- void terminate();
- void setButtonShortcut();
- void setShortcut();
- void setVolume(bool up, bool minMax);
- void showKeypad();
-
- // event handling
- Osp::Base::Runtime::Thread *_gameThread;
- Osp::Base::Runtime::Mutex *_eventQueueLock;
- Common::Queue<Common::Event> _eventQueue;
- enum { kInitState, kActiveState, kClosingState, kDoneState, kErrorState } _state;
- enum { kLeftButton, kRightButtonOnce, kRightButton, kMoveOnly } _buttonState;
- enum { kControlMouse, kEscapeKey, kGameMenu, kShowKeypad, kSetVolume } _shortcut;
-};
-
-#endif
diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h
index d41839d961..d62ced02e1 100644
--- a/backends/platform/dc/dc.h
+++ b/backends/platform/dc/dc.h
@@ -151,7 +151,7 @@ public:
void setShakePos(int shake_pos);
// Get the number of milliseconds since the program was started.
- uint32 getMillis();
+ uint32 getMillis(bool skipRecord = false);
// Delay for a specified amount of milliseconds
void delayMillis(uint msecs);
diff --git a/backends/platform/dc/time.cpp b/backends/platform/dc/time.cpp
index 8cc3a71e8d..1e5f44ec85 100644
--- a/backends/platform/dc/time.cpp
+++ b/backends/platform/dc/time.cpp
@@ -26,7 +26,7 @@
#include "dc.h"
-uint32 OSystem_Dreamcast::getMillis()
+uint32 OSystem_Dreamcast::getMillis(bool skipRecord)
{
static uint32 msecs=0;
static unsigned int t0=0;
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index 830c782b90..9dc66e80d7 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -2280,7 +2280,7 @@ void VBlankHandler(void) {
//REG_IF = IRQ_VBLANK;
}
-int getMillis() {
+int getMillis(bool skipRecord) {
return currentTimeMillis;
// return frameCount * FRAME_TIME;
}
diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h
index ad49ae276d..5e91fae13a 100644
--- a/backends/platform/ds/arm9/source/dsmain.h
+++ b/backends/platform/ds/arm9/source/dsmain.h
@@ -88,7 +88,7 @@ void setGamma(int gamma);
// Timers
void setTimerCallback(OSystem_DS::TimerProc proc, int interval); // Setup a callback function at a regular interval
-int getMillis(); // Return the current runtime in milliseconds
+int getMillis(bool skipRecord = false); // Return the current runtime in milliseconds
void doTimerCallback(); // Call callback function if required
// Sound
diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp
index a4b9c842fc..2f6358d8ee 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.cpp
+++ b/backends/platform/ds/arm9/source/osystem_ds.cpp
@@ -656,7 +656,7 @@ bool OSystem_DS::pollEvent(Common::Event &event) {
return false;
}
-uint32 OSystem_DS::getMillis() {
+uint32 OSystem_DS::getMillis(bool skipRecord) {
return DS::getMillis();
}
diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h
index a6001da764..4550e22b2c 100644
--- a/backends/platform/ds/arm9/source/osystem_ds.h
+++ b/backends/platform/ds/arm9/source/osystem_ds.h
@@ -117,7 +117,7 @@ public:
virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, u32 keycolor, bool dontScale, const Graphics::PixelFormat *format);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual void getTimeAndDate(TimeDate &t) const;
diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp
index ed2c886213..460d3fd2ac 100644
--- a/backends/platform/iphone/osys_main.cpp
+++ b/backends/platform/iphone/osys_main.cpp
@@ -166,7 +166,7 @@ void OSystem_IPHONE::suspendLoop() {
_timeSuspended += getMillis() - startTime;
}
-uint32 OSystem_IPHONE::getMillis() {
+uint32 OSystem_IPHONE::getMillis(bool skipRecord) {
//printf("getMillis()\n");
struct timeval currentTime;
diff --git a/backends/platform/iphone/osys_main.h b/backends/platform/iphone/osys_main.h
index 037125490d..811a8ddb2e 100644
--- a/backends/platform/iphone/osys_main.h
+++ b/backends/platform/iphone/osys_main.h
@@ -165,7 +165,7 @@ public:
virtual void setCursorPalette(const byte *colors, uint start, uint num);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual MutexRef createMutex(void);
diff --git a/backends/platform/n64/osys_n64.h b/backends/platform/n64/osys_n64.h
index bc6b3cb1a5..10138b230a 100644
--- a/backends/platform/n64/osys_n64.h
+++ b/backends/platform/n64/osys_n64.h
@@ -184,7 +184,7 @@ public:
virtual void setCursorPalette(const byte *colors, uint start, uint num);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual MutexRef createMutex(void);
diff --git a/backends/platform/n64/osys_n64_base.cpp b/backends/platform/n64/osys_n64_base.cpp
index 1e2aca9e51..afd93f5e09 100644
--- a/backends/platform/n64/osys_n64_base.cpp
+++ b/backends/platform/n64/osys_n64_base.cpp
@@ -810,7 +810,7 @@ void OSystem_N64::setMouseCursor(const void *buf, uint w, uint h, int hotspotX,
return;
}
-uint32 OSystem_N64::getMillis() {
+uint32 OSystem_N64::getMillis(bool skipRecord) {
return getMilliTick();
}
diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp
index 4690a67c55..9e05539799 100644
--- a/backends/platform/null/null.cpp
+++ b/backends/platform/null/null.cpp
@@ -49,7 +49,7 @@ public:
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual void getTimeAndDate(TimeDate &t) const {}
diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp
index 5628658381..a7d782b07c 100644
--- a/backends/platform/ps2/systemps2.cpp
+++ b/backends/platform/ps2/systemps2.cpp
@@ -571,7 +571,7 @@ void OSystem_PS2::displayMessageOnOSD(const char *msg) {
printf("displayMessageOnOSD: %s\n", msg);
}
-uint32 OSystem_PS2::getMillis(void) {
+uint32 OSystem_PS2::getMillis(bool skipRecord) {
return msecCount;
}
diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h
index 99482d4da4..3ba40a70f9 100644
--- a/backends/platform/ps2/systemps2.h
+++ b/backends/platform/ps2/systemps2.h
@@ -82,7 +82,7 @@ public:
virtual void warpMouse(int x, int y);
virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = 0);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual bool pollEvent(Common::Event &event);
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index fb8c1c60bf..8559066e53 100644
--- a/backends/platform/psp/osys_psp.cpp
+++ b/backends/platform/psp/osys_psp.cpp
@@ -349,7 +349,7 @@ bool OSystem_PSP::pollEvent(Common::Event &event) {
return _inputHandler.getAllInputs(event);
}
-uint32 OSystem_PSP::getMillis() {
+uint32 OSystem_PSP::getMillis(bool skipRecord) {
return PspRtc::instance().getMillis();
}
diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h
index 2afdabd0fc..f4591e476d 100644
--- a/backends/platform/psp/osys_psp.h
+++ b/backends/platform/psp/osys_psp.h
@@ -125,7 +125,7 @@ public:
bool processInput(Common::Event &event);
// Time
- uint32 getMillis();
+ uint32 getMillis(bool skipRecord = false);
void delayMillis(uint msecs);
// Timer
diff --git a/backends/platform/psp/rtc.cpp b/backends/platform/psp/rtc.cpp
index cbbb7d3f80..4f15e45535 100644
--- a/backends/platform/psp/rtc.cpp
+++ b/backends/platform/psp/rtc.cpp
@@ -52,7 +52,7 @@ void PspRtc::init() { // init our starting ticks
// Note that after we fill up 32 bits ie 50 days we'll loop back to 0, which may cause
// unpredictable results
-uint32 PspRtc::getMillis() {
+uint32 PspRtc::getMillis(bool skipRecord) {
uint32 ticks[2];
sceRtcGetCurrentTick((u64 *)ticks); // can introduce weird thread delays
diff --git a/backends/platform/psp/rtc.h b/backends/platform/psp/rtc.h
index 45885c3e66..d2689681dd 100644
--- a/backends/platform/psp/rtc.h
+++ b/backends/platform/psp/rtc.h
@@ -40,7 +40,7 @@ public:
init();
}
void init();
- uint32 getMillis();
+ uint32 getMillis(bool skipRecord = false);
uint32 getMicros();
};
diff --git a/backends/platform/sdl/sdl-sys.h b/backends/platform/sdl/sdl-sys.h
index ca3c586e03..eccf73815d 100644
--- a/backends/platform/sdl/sdl-sys.h
+++ b/backends/platform/sdl/sdl-sys.h
@@ -35,8 +35,11 @@
// it with an alternate slightly less unfriendly override.
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_FILE)
#undef FILE
+// Solaris has typedef __FILE FILE in several places already
+#if !defined(__sun)
typedef struct { int FAKE; } FAKE_FILE;
#define FILE FAKE_FILE
+#endif // (__sun)
#endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcasecmp)
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index d54854352d..7ab367d4a4 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -30,7 +30,7 @@
#include "backends/platform/sdl/sdl.h"
#include "common/config-manager.h"
-#include "common/EventRecorder.h"
+#include "gui/EventRecorder.h"
#include "common/taskbar.h"
#include "common/textconsole.h"
@@ -97,7 +97,15 @@ OSystem_SDL::~OSystem_SDL() {
_audiocdManager = 0;
delete _mixerManager;
_mixerManager = 0;
+
+#ifdef ENABLE_EVENTRECORDER
+ // HACK HACK HACK
+ // This is nasty.
+ delete g_eventRec.getTimerManager();
+#else
delete _timerManager;
+#endif
+
_timerManager = 0;
delete _mutexManager;
_mutexManager = 0;
@@ -131,9 +139,6 @@ void OSystem_SDL::init() {
if (_mutexManager == 0)
_mutexManager = new SdlMutexManager();
- if (_timerManager == 0)
- _timerManager = new SdlTimerManager();
-
#if defined(USE_TASKBAR)
if (_taskbarManager == 0)
_taskbarManager = new Common::TaskbarManager();
@@ -191,11 +196,19 @@ void OSystem_SDL::initBackend() {
if (_mixerManager == 0) {
_mixerManager = new SdlMixerManager();
-
// Setup and start mixer
_mixerManager->init();
}
+#ifdef ENABLE_EVENTRECORDER
+ g_eventRec.registerMixerManager(_mixerManager);
+
+ g_eventRec.registerTimerManager(new SdlTimerManager());
+#else
+ if (_timerManager == 0)
+ _timerManager = new SdlTimerManager();
+#endif
+
if (_audiocdManager == 0) {
// Audio CD support was removed with SDL 1.3
#if SDL_VERSION_ATLEAST(1, 3, 0)
@@ -466,14 +479,21 @@ void OSystem_SDL::setupIcon() {
free(icon);
}
-uint32 OSystem_SDL::getMillis() {
+
+uint32 OSystem_SDL::getMillis(bool skipRecord) {
uint32 millis = SDL_GetTicks();
- g_eventRec.processMillis(millis);
+
+#ifdef ENABLE_EVENTRECORDER
+ g_eventRec.processMillis(millis, skipRecord);
+#endif
+
return millis;
}
void OSystem_SDL::delayMillis(uint msecs) {
- if (!g_eventRec.processDelayMillis(msecs))
+#ifdef ENABLE_EVENTRECORDER
+ if (!g_eventRec.processDelayMillis())
+#endif
SDL_Delay(msecs);
}
@@ -491,12 +511,25 @@ void OSystem_SDL::getTimeAndDate(TimeDate &td) const {
Audio::Mixer *OSystem_SDL::getMixer() {
assert(_mixerManager);
- return _mixerManager->getMixer();
+ return getMixerManager()->getMixer();
}
SdlMixerManager *OSystem_SDL::getMixerManager() {
assert(_mixerManager);
+
+#ifdef ENABLE_EVENTRECORDER
+ return g_eventRec.getMixerManager();
+#else
return _mixerManager;
+#endif
+}
+
+Common::TimerManager *OSystem_SDL::getTimerManager() {
+#ifdef ENABLE_EVENTRECORDER
+ return g_eventRec.getTimerManager();
+#else
+ return _timerManager;
+#endif
}
#ifdef USE_OPENGL
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index f05207b482..840e73ff09 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -68,10 +68,11 @@ public:
virtual void setWindowCaption(const char *caption);
virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual void getTimeAndDate(TimeDate &td) const;
virtual Audio::Mixer *getMixer();
+ virtual Common::TimerManager *getTimerManager();
protected:
bool _inited;
diff --git a/backends/platform/bada/README.TXT b/backends/platform/tizen/README.TXT
index c4a04d5450..def3da2cce 100644
--- a/backends/platform/bada/README.TXT
+++ b/backends/platform/tizen/README.TXT
@@ -1,77 +1,58 @@
-Build instructions:
+Build instructions (using linux)
-1. Install BADA SDK (requires free registration):
-
- http://developer.bada.com/apis/index.do
-
-2. Install Cygwin:
-
- http://www.cygwin.com/
+1. Install the Tizen SDK
- Add the following to your cygwin .bash_profile:
+http://www.tizen.org
- alias mmake=/cygdrive/c/MinGW/bin/mingw32-make.exe
- export BADA_SDK=/cygdrive/c/bada/1.2.1
- export ARM_BIN=c:/bada/1.2.1/Tools/Toolchains/ARM/bin
- export CPPFLAGS="-fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 \
- -mfloat-abi=hard -mlittle-endian -mthumb-interwork -Wno-psabi \
- -fno-strict-aliasing -fno-short-enums"
- export LDFLAGS="-nostdlib -lc-newlib -lm-newlib -LC:/bada/1.2.1/Model/Wave_LP1/Target"
- #export PATH=${BADA_SDK}/Tools/Toolchains/Win32/bin:${PATH}
- export PATH=${BADA_SDK}/Tools/Toolchains/ARM/bin:~/utils:${PATH}
- alias gcc=${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe
- alias ar=${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe
+To use an alternative Java SDK to run the Tizen IDE (eclipse), edit ~/.profile
- The following were added to ~/utils for zlib:
+export JAVA_HOME=/opt/jdk1.6.0_45
+export PATH=${PATH}:${JAVA_HOME}/bin
- ar:
- #!/bin/sh
- ${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe $*
+2. Add the following to your ~/.bashrc file
- gcc:
- #!/bin/sh
- ${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe $*
+export TIZEN_SDK=${HOME}/tizen-sdk
+export TIZEN_ROOTSTRAP=${TIZEN_SDK}/platforms/tizen2.1/rootstraps/tizen-device-2.1.native
+export TIZEN_BIN=${TIZEN_SDK}/tools/arm-linux-gnueabi-gcc-4.5/bin
+export TIZEN_LIBS=${HOME}/tizen-lib
+export PATH=${PATH}:${TIZEN_BIN}:~/bin
+export CHOST=arm-linux-gnueabi
+export LDFLAGS="--sysroot=${TIZEN_ROOTSTRAP} -L${TIZEN_LIBS}/lib"
+export CPPFLAGS="--sysroot=${TIZEN_ROOTSTRAP} -fmessage-length=0 -fPIC\
+ -I${TIZEN_ROOTSTRAP}/usr/include -I${TIZEN_LIBS}/include"
+export CFLAGS=${CPPFLAGS}
3. Build dependencies
- zlib, libogg, libvorbis, libmad, FLAC
-
- see: "Building the libraries" under:
+ See: "Building the libraries" under:
http://wiki.scummvm.org/index.php/Compiling_ScummVM/MinGW#Building_the_libraries
for instructions on how to obtain these modules
- 3.1 For Target-Release configure ogg and mad with:
-
- ./configure --host=arm-samsung-nucleuseabi --disable-shared
+ 3.1 zlib
- when building vorbis and flac:
+ $ ./configure --static --prefix=${TIZEN_LIBS}
+ $ make && make install
- ./configure --host=arm-samsung-nucleuseabi --disable-shared --with-ogg=c:/cygwin/usr/local
+ 3.2 freetype, libtheora, libogg, libvorbis, libmad, FLAC
- 3.2 for each module, after a successful configure, add the following
- to the generated config.h (gzguts.h for zlib)
+ $ ./configure --host=arm-linux-gnueabi --prefix=${TIZEN_LIBS} --disable-shared
+ $ make && make install
- #undef __MINGW32__
- #undef _WIN32
- #include "c:/src/scummvm/backends/platform/bada/portdefs.h"
-
- 3.3 Additional post configure edits:
+ Note: you can ignore the ranlib errors when doing make install.
- - removed -fforce-mem from the libMAD Makefile
- - in libvorbis/lib/Makefile comment lines with vorbis_selftests
- - edit libFLAC/Makefile ... CFLAGS = $(OGG_CFLAGS)
+ Modify the resulting ~/tizen-lib/bin/freetype-config file to include -lz when printing libs
- Note: you can ignore the ranlib errors when doing make install.
+ 3.3 Linker ordering: scummvm, freetype, theoradec, vorbis, vorbisfile, mad, FLAC, ogg, z
4. Build the ScummVM base library:
- ./configure --host=bada --enable-release
+ ./configure --host=tizen --enable-release --with-freetype2-prefix=${TIZEN_LIBS}/bin
- To target the Win32 simulator:
+ For development:
- ./configure --host=bada --enable-debug
+ ./configure --host=tizen --enable-verbose-build --enable-debug
-5. Build the front end application using BADA-Ide:
+5. Build the front end application using Tizen IDE
Copy the scummvm/dists/bada folder into a clean directory
outside of the scummvm package. Start the BADA IDE then
@@ -90,3 +71,38 @@ HelvB14 font files:
Then run the following command:
$ ./ucs2any.pl 100dpi/helvB14.bdf MAPPINGS/8859-1.TXT iso8859-1 \
MAPPINGS/8859-2.TXT iso8859-2 MAPPINGS/8859-3.TXT iso8859-3
+
+=====================================================================
+Archived build instruction for BADA/cygwin
+
+1. Install BADA SDK (requires free registration):
+
+ http://developer.bada.com/apis/index.do
+
+2. Install Cygwin:
+
+ http://www.cygwin.com/
+
+ Add the following to your cygwin .bash_profile:
+
+ alias mmake=/cygdrive/c/MinGW/bin/mingw32-make.exe
+ export BADA_SDK=/cygdrive/c/bada/1.2.1
+ export ARM_BIN=c:/bada/1.2.1/Tools/Toolchains/ARM/bin
+ export CPPFLAGS="-fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 \
+ -mfloat-abi=hard -mlittle-endian -mthumb-interwork -Wno-psabi \
+ -fno-strict-aliasing -fno-short-enums"
+ export LDFLAGS="-nostdlib -lc-newlib -lm-newlib -LC:/bada/1.2.1/Model/Wave_LP1/Target"
+ #export PATH=${BADA_SDK}/Tools/Toolchains/Win32/bin:${PATH}
+ export PATH=${BADA_SDK}/Tools/Toolchains/ARM/bin:~/utils:${PATH}
+ alias gcc=${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe
+ alias ar=${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe
+
+ The following were added to ~/utils for zlib:
+
+ ar:
+ #!/bin/sh
+ ${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe $*
+
+ gcc:
+ #!/bin/sh
+ ${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe $*
diff --git a/backends/platform/bada/application.cpp b/backends/platform/tizen/application.cpp
index e761649245..8236ebef67 100644
--- a/backends/platform/bada/application.cpp
+++ b/backends/platform/tizen/application.cpp
@@ -22,43 +22,55 @@
#include "engines/engine.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/application.h"
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/application.h"
-using namespace Osp::System;
-using namespace Osp::Ui::Controls;
-
-Application *BadaScummVM::createInstance() {
- return new BadaScummVM();
+Application *TizenScummVM::createInstance() {
+ logEntered();
+ return new TizenScummVM();
}
-BadaScummVM::BadaScummVM() : _appForm(0) {
+TizenScummVM::TizenScummVM() : _appForm(0) {
+ logEntered();
}
-BadaScummVM::~BadaScummVM() {
+TizenScummVM::~TizenScummVM() {
logEntered();
if (g_system) {
- BadaSystem *system = (BadaSystem *)g_system;
+ TizenSystem *system = (TizenSystem *)g_system;
system->destroyBackend();
delete system;
g_system = 0;
}
}
-bool BadaScummVM::OnAppInitializing(AppRegistry &appRegistry) {
+bool TizenScummVM::OnAppInitialized(void) {
+ logEntered();
+ _appForm->SetOrientation(Tizen::Ui::ORIENTATION_LANDSCAPE);
+ return true;
+}
+
+bool TizenScummVM::OnAppWillTerminate(void) {
+ logEntered();
+ return true;
+}
+
+bool TizenScummVM::OnAppInitializing(AppRegistry &appRegistry) {
+ logEntered();
_appForm = systemStart(this);
return (_appForm != NULL);
}
-bool BadaScummVM::OnAppTerminating(AppRegistry &appRegistry,
- bool forcedTermination) {
+bool TizenScummVM::OnAppTerminating(AppRegistry &appRegistry, bool forcedTermination) {
logEntered();
return true;
}
-void BadaScummVM::OnUserEventReceivedN(RequestId requestId,
- Osp::Base::Collection::IList *args) {
+void TizenScummVM::OnUserEventReceivedN(RequestId requestId, IList *args) {
+ MessageBox messageBox;
+ int modalResult;
+
logEntered();
if (requestId == USER_MESSAGE_EXIT) {
@@ -73,39 +85,56 @@ void BadaScummVM::OnUserEventReceivedN(RequestId requestId,
if (!message) {
message = new String("Unknown error");
}
-
- MessageBox messageBox;
messageBox.Construct(L"Oops...", *message, MSGBOX_STYLE_OK);
- int modalResult;
+ messageBox.ShowAndWait(modalResult);
+ Terminate();
+ } else if (requestId == USER_MESSAGE_EXIT_ERR_CONFIG) {
+ // the config file was corrupted
+ messageBox.Construct(L"Config file corrupted",
+ L"Settings have been reverted, please restart.", MSGBOX_STYLE_OK);
messageBox.ShowAndWait(modalResult);
Terminate();
}
}
-void BadaScummVM::OnForeground(void) {
+void TizenScummVM::OnForeground(void) {
logEntered();
pauseGame(false);
}
-void BadaScummVM::OnBackground(void) {
+void TizenScummVM::OnBackground(void) {
logEntered();
pauseGame(true);
}
-void BadaScummVM::OnBatteryLevelChanged(BatteryLevel batteryLevel) {
+void TizenScummVM::OnBatteryLevelChanged(BatteryLevel batteryLevel) {
+ logEntered();
}
-void BadaScummVM::OnLowMemory(void) {
+void TizenScummVM::OnLowMemory(void) {
+ logEntered();
+}
+
+void TizenScummVM::OnScreenOn(void) {
+ logEntered();
+}
+
+void TizenScummVM::OnScreenOff(void) {
+ logEntered();
+}
+
+void TizenScummVM::OnScreenBrightnessChanged(int brightness) {
+ logEntered();
}
-void BadaScummVM::pauseGame(bool pause) {
+void TizenScummVM::pauseGame(bool pause) {
if (_appForm) {
if (pause && g_engine && !g_engine->isPaused()) {
_appForm->pushKey(Common::KEYCODE_SPACE);
}
if (g_system) {
- ((BadaSystem *)g_system)->setMute(pause);
+ ((TizenSystem *)g_system)->setMute(pause);
}
}
}
diff --git a/backends/platform/tizen/application.h b/backends/platform/tizen/application.h
new file mode 100644
index 0000000000..f18ccb175b
--- /dev/null
+++ b/backends/platform/tizen/application.h
@@ -0,0 +1,69 @@
+/* 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 TIZEN_APPLICATION_H
+#define TIZEN_APPLICATION_H
+
+#include <FBase.h>
+#include <FApp.h>
+#include <FGraphics.h>
+#include <FUi.h>
+#include <FSystem.h>
+
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/form.h"
+
+using namespace Tizen::App;
+using namespace Tizen::System;
+using namespace Tizen::Ui;
+using namespace Tizen::Ui::Controls;
+using namespace Tizen::Base::Collection;
+
+class TizenScummVM :
+ public UiApp,
+ public IScreenEventListener {
+
+public:
+ TizenScummVM();
+ virtual ~TizenScummVM();
+
+ static UiApp *createInstance(void);
+
+ virtual bool OnAppInitializing(AppRegistry &appRegistry);
+ virtual bool OnAppInitialized(void);
+ virtual bool OnAppWillTerminate(void);
+ virtual bool OnAppTerminating(AppRegistry &appRegistry, bool forcedTermination = false);
+ virtual void OnLowMemory(void);
+ virtual void OnBatteryLevelChanged(BatteryLevel batteryLevel);
+ virtual void OnUserEventReceivedN(RequestId requestId, IList *pArgs);
+ virtual void OnForeground(void);
+ virtual void OnBackground(void);
+ virtual void OnScreenOn(void);
+ virtual void OnScreenOff(void);
+ virtual void OnScreenBrightnessChanged(int brightness);
+
+private:
+ void pauseGame(bool pause);
+ TizenAppForm *_appForm;
+};
+
+#endif
diff --git a/backends/platform/bada/audio.cpp b/backends/platform/tizen/audio.cpp
index 65a5a80fa5..313a10eaa8 100644
--- a/backends/platform/bada/audio.cpp
+++ b/backends/platform/tizen/audio.cpp
@@ -23,18 +23,11 @@
#include <FSysSettingInfo.h>
#include <FAppAppRegistry.h>
-#include "backends/platform/bada/audio.h"
-#include "backends/platform/bada/system.h"
+#include "backends/platform/tizen/audio.h"
+#include "backends/platform/tizen/system.h"
-#define TIMER_INCREMENT 10
-#define TIMER_INTERVAL 40
-#define MIN_TIMER_INTERVAL 10
-#define MAX_TIMER_INTERVAL 160
-#define INIT_LEVEL 3
-#define CONFIG_KEY L"audiovol"
-
-// sound level pre-sets
-const int levels[] = {0, 1, 10, 45, 70, 99};
+#define TIMER_INTERVAL 10
+#define VOLUME 99
AudioThread::AudioThread() :
_mixer(0),
@@ -51,9 +44,7 @@ AudioThread::AudioThread() :
Audio::MixerImpl *AudioThread::Construct(OSystem *system) {
logEntered();
- if (IsFailed(Thread::Construct(THREAD_TYPE_EVENT_DRIVEN,
- DEFAULT_STACK_SIZE,
- THREAD_PRIORITY_HIGH))) {
+ if (IsFailed(EventDrivenThread::Construct(DEFAULT_STACK_SIZE, THREAD_PRIORITY_HIGH))) {
AppLog("Failed to create AudioThread");
return NULL;
}
@@ -69,7 +60,7 @@ AudioThread::~AudioThread() {
bool AudioThread::isSilentMode() {
bool silentMode;
String key(L"SilentMode");
- Osp::System::SettingInfo::GetValue(key, silentMode);
+ Tizen::System::SettingInfo::GetValue(key, silentMode);
return silentMode;
}
@@ -79,59 +70,16 @@ void AudioThread::setMute(bool on) {
if (on) {
_timer->Cancel();
} else {
- _timer->Start(_interval);
- }
- }
-}
-
-int AudioThread::setVolume(bool up, bool minMax) {
- int level = -1;
- int numLevels = sizeof(levels) / sizeof(levels[0]);
-
- if (_audioOut) {
- int volume = _audioOut->GetVolume();
- if (minMax) {
- level = up ? numLevels - 1 : 0;
- volume = levels[level];
- } else {
- // adjust volume to be one of the preset values
- for (int i = 0; i < numLevels && level == -1; i++) {
- if (volume == levels[i]) {
- level = i;
- if (up) {
- if (i + 1 < numLevels) {
- level = i + 1;
- }
- } else if (i > 0) {
- level = i - 1;
- }
- }
- }
-
- // default to INIT_LEVEL when current not preset value
- if (level == -1) {
- level = INIT_LEVEL;
- }
- volume = levels[level];
- }
-
- _audioOut->SetVolume(volume);
-
- // remember the chosen setting
- AppRegistry *registry = Application::GetInstance()->GetAppRegistry();
- if (registry) {
- registry->Set(CONFIG_KEY, volume);
+ _timer->StartAsRepeatable(_interval);
}
}
- return level;
}
bool AudioThread::OnStart(void) {
logEntered();
- _audioOut = new Osp::Media::AudioOut();
- if (!_audioOut ||
- IsFailed(_audioOut->Construct(*this))) {
+ _audioOut = new Tizen::Media::AudioOut();
+ if (!_audioOut || IsFailed(_audioOut->Construct(*this))) {
AppLog("Failed to create AudioOut");
return false;
}
@@ -144,8 +92,7 @@ bool AudioThread::OnStart(void) {
}
if (IsFailed(_audioOut->Prepare(AUDIO_TYPE_PCM_S16_LE,
- AUDIO_CHANNEL_TYPE_STEREO,
- sampleRate))) {
+ AUDIO_CHANNEL_TYPE_STEREO, sampleRate))) {
AppLog("Failed to prepare AudioOut %d", sampleRate);
return false;
}
@@ -164,26 +111,14 @@ bool AudioThread::OnStart(void) {
return false;
}
- if (IsFailed(_timer->Start(_interval))) {
+ if (IsFailed(_timer->StartAsRepeatable(_interval))) {
AppLog("failed to start audio timer");
return false;
}
- // get the volume from the app-registry
- int volume = levels[INIT_LEVEL];
- AppRegistry *registry = Application::GetInstance()->GetAppRegistry();
- if (registry) {
- if (E_KEY_NOT_FOUND == registry->Get(CONFIG_KEY, volume)) {
- registry->Add(CONFIG_KEY, volume);
- volume = levels[INIT_LEVEL];
- } else {
- AppLog("Setting volume: %d", volume);
- }
- }
-
_muted = false;
_mixer->setReady(true);
- _audioOut->SetVolume(isSilentMode() ? 0 : volume);
+ _audioOut->SetVolume(isSilentMode() ? 0 : VOLUME);
_audioOut->Start();
return true;
}
@@ -206,20 +141,20 @@ void AudioThread::OnStop(void) {
}
}
-void AudioThread::OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r) {
+void AudioThread::OnAudioOutErrorOccurred(Tizen::Media::AudioOut &src, result r) {
logEntered();
}
-void AudioThread::OnAudioOutInterrupted(Osp::Media::AudioOut &src) {
+void AudioThread::OnAudioOutInterrupted(Tizen::Media::AudioOut &src) {
logEntered();
}
-void AudioThread::OnAudioOutReleased(Osp::Media::AudioOut &src) {
+void AudioThread::OnAudioOutReleased(Tizen::Media::AudioOut &src) {
logEntered();
_audioOut->Start();
}
-void AudioThread::OnAudioOutBufferEndReached(Osp::Media::AudioOut &src) {
+void AudioThread::OnAudioOutBufferEndReached(Tizen::Media::AudioOut &src) {
if (_ready > 0) {
_playing = _tail;
_audioOut->WriteBuffer(_audioBuffer[_tail]);
@@ -228,10 +163,6 @@ void AudioThread::OnAudioOutBufferEndReached(Osp::Media::AudioOut &src) {
} else {
// audio buffer empty: decrease timer inverval
_playing = -1;
- _interval -= TIMER_INCREMENT;
- if (_interval < MIN_TIMER_INTERVAL) {
- _interval = MIN_TIMER_INTERVAL;
- }
}
}
@@ -243,18 +174,8 @@ void AudioThread::OnTimerExpired(Timer &timer) {
_head = (_head + 1) % NUM_AUDIO_BUFFERS;
_ready++;
}
- } else {
- // audio buffer full: increase timer inverval
- _interval += TIMER_INCREMENT;
- if (_interval > MAX_TIMER_INTERVAL) {
- _interval = MAX_TIMER_INTERVAL;
- }
}
-
if (_ready && _playing == -1) {
OnAudioOutBufferEndReached(*_audioOut);
}
-
- _timer->Start(_interval);
}
-
diff --git a/backends/platform/bada/audio.h b/backends/platform/tizen/audio.h
index 72c537a942..8d7835042d 100644
--- a/backends/platform/bada/audio.h
+++ b/backends/platform/tizen/audio.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef BADA_AUDIO_H
-#define BADA_AUDIO_H
+#ifndef TIZEN_AUDIO_H
+#define TIZEN_AUDIO_H
#include <FBase.h>
#include <FMedia.h>
@@ -33,17 +33,19 @@
#include "common/system.h"
#include "audio/mixer_intern.h"
-using namespace Osp::Base;
-using namespace Osp::Base::Collection;
-using namespace Osp::Base::Runtime;
-using namespace Osp::Media;
-using namespace Osp::Io;
+using namespace Tizen::Base;
+using namespace Tizen::Base::Collection;
+using namespace Tizen::Base::Runtime;
+using namespace Tizen::Media;
+using namespace Tizen::Io;
#define NUM_AUDIO_BUFFERS 2
-class AudioThread: public Osp::Media::IAudioOutEventListener,
- public Osp::Base::Runtime::ITimerEventListener,
- public Osp::Base::Runtime::Thread {
+class AudioThread:
+ public Tizen::Media::IAudioOutEventListener,
+ public Tizen::Base::Runtime::ITimerEventListener,
+ public Tizen::Base::Runtime::EventDrivenThread {
+
public:
AudioThread(void);
~AudioThread(void);
@@ -51,21 +53,20 @@ public:
Audio::MixerImpl *Construct(OSystem *system);
bool isSilentMode();
void setMute(bool on);
- int setVolume(bool up, bool minMax);
bool OnStart(void);
void OnStop(void);
- void OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r);
- void OnAudioOutInterrupted(Osp::Media::AudioOut &src);
- void OnAudioOutReleased(Osp::Media::AudioOut &src);
- void OnAudioOutBufferEndReached(Osp::Media::AudioOut &src);
+ void OnAudioOutErrorOccurred(Tizen::Media::AudioOut &src, result r);
+ void OnAudioOutInterrupted(Tizen::Media::AudioOut &src);
+ void OnAudioOutReleased(Tizen::Media::AudioOut &src);
+ void OnAudioOutBufferEndReached(Tizen::Media::AudioOut &src);
void OnTimerExpired(Timer &timer);
private:
Audio::MixerImpl *_mixer;
- Osp::Base::Runtime::Timer *_timer;
- Osp::Media::AudioOut *_audioOut;
- Osp::Base::ByteBuffer _audioBuffer[NUM_AUDIO_BUFFERS];
+ Tizen::Base::Runtime::Timer *_timer;
+ Tizen::Media::AudioOut *_audioOut;
+ Tizen::Base::ByteBuffer _audioBuffer[NUM_AUDIO_BUFFERS];
int _head, _tail, _ready, _interval, _playing;
bool _muted;
};
diff --git a/backends/platform/tizen/form.cpp b/backends/platform/tizen/form.cpp
new file mode 100644
index 0000000000..5050699ca9
--- /dev/null
+++ b/backends/platform/tizen/form.cpp
@@ -0,0 +1,419 @@
+/* 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 <FApp.h>
+#include <FSysSystemTime.h>
+
+#include "common/translation.h"
+#include "base/main.h"
+
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/system.h"
+
+using namespace Tizen::Base::Collection;
+using namespace Tizen::Base::Runtime;
+using namespace Tizen::Ui::Controls;
+
+// round down small Y touch values to 1 to allow the
+// cursor to be positioned at the top of the screen
+#define MIN_TOUCH_Y 20
+
+// block for up to 2.5 seconds during shutdown to
+// allow the game thread to exit gracefully.
+#define EXIT_SLEEP_STEP 10
+#define EXIT_SLEEP 250
+
+//
+// TizenAppForm
+//
+TizenAppForm::TizenAppForm() :
+ _gestureMode(false),
+ _osdMessage(NULL),
+ _gameThread(NULL),
+ _eventQueueLock(NULL),
+ _state(kInitState),
+ _buttonState(kLeftButton),
+ _shortcut(kShowKeypad) {
+}
+
+result TizenAppForm::Construct() {
+ TizenSystem *tizenSystem = NULL;
+ result r = Form::Construct(FORM_STYLE_NORMAL);
+ if (!IsFailed(r)) {
+ tizenSystem = new TizenSystem(this);
+ r = tizenSystem != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
+ }
+ if (!IsFailed(r)) {
+ r = tizenSystem->Construct();
+ }
+ if (!IsFailed(r)) {
+ _gameThread = new Thread();
+ r = _gameThread != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
+ }
+ if (!IsFailed(r)) {
+ r = _gameThread->Construct(*this);
+ }
+ if (!IsFailed(r)) {
+ _eventQueueLock = new Mutex();
+ r = _eventQueueLock != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
+ }
+ if (!IsFailed(r)) {
+ r = _eventQueueLock->Create();
+ }
+
+ if (!IsFailed(r)) {
+ g_system = tizenSystem;
+ } else {
+ AppLog("Form startup failed");
+ delete tizenSystem;
+ delete _gameThread;
+ _gameThread = NULL;
+ }
+ return r;
+}
+
+TizenAppForm::~TizenAppForm() {
+ logEntered();
+
+ if (_gameThread && _state != kErrorState) {
+ terminate();
+
+ _gameThread->Stop();
+ if (_state != kErrorState) {
+ _gameThread->Join();
+ }
+
+ delete _gameThread;
+ _gameThread = NULL;
+ }
+
+ delete _eventQueueLock;
+ _eventQueueLock = NULL;
+
+ logLeaving();
+}
+
+//
+// abort the game thread
+//
+void TizenAppForm::terminate() {
+ if (_state == kActiveState) {
+ ((TizenSystem *)g_system)->setMute(true);
+
+ _eventQueueLock->Acquire();
+
+ Common::Event e;
+ e.type = Common::EVENT_QUIT;
+ _eventQueue.push(e);
+ _state = kClosingState;
+
+ _eventQueueLock->Release();
+
+ // block while thread ends
+ AppLog("waiting for shutdown");
+ for (int i = 0; i < EXIT_SLEEP_STEP && _state == kClosingState; i++) {
+ Thread::Sleep(EXIT_SLEEP);
+ }
+
+ if (_state == kClosingState) {
+ // failed to terminate - Join() will freeze
+ _state = kErrorState;
+ }
+ }
+}
+
+void TizenAppForm::exitSystem() {
+ _state = kErrorState;
+
+ if (_gameThread) {
+ _gameThread->Stop();
+ delete _gameThread;
+ _gameThread = NULL;
+ }
+}
+
+result TizenAppForm::OnInitializing(void) {
+ logEntered();
+
+ AddOrientationEventListener(*this);
+ AddTouchEventListener(*this);
+ SetMultipointTouchEnabled(true);
+
+ // set focus to enable receiving key events
+ SetEnabled(true);
+ SetFocusable(true);
+ SetFocus();
+
+ return E_SUCCESS;
+}
+
+result TizenAppForm::OnDraw(void) {
+ logEntered();
+ return E_SUCCESS;
+}
+
+void TizenAppForm::OnOrientationChanged(const Control &source, OrientationStatus orientationStatus) {
+ logEntered();
+ if (_state == kInitState) {
+ _state = kActiveState;
+ _gameThread->Start();
+ }
+}
+
+Tizen::Base::Object *TizenAppForm::Run() {
+ logEntered();
+
+ scummvm_main(0, 0);
+ if (_state == kActiveState) {
+ Tizen::App::Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT, NULL);
+ }
+ _state = kDoneState;
+ return NULL;
+}
+
+bool TizenAppForm::pollEvent(Common::Event &event) {
+ bool result = false;
+
+ _eventQueueLock->Acquire();
+ if (!_eventQueue.empty()) {
+ event = _eventQueue.pop();
+ result = true;
+ }
+ if (_osdMessage) {
+ TizenSystem *system = (TizenSystem *)g_system;
+ TizenGraphicsManager *graphics = system->getGraphics();
+ if (graphics) {
+ graphics->displayMessageOnOSD(_osdMessage);
+ _osdMessage = NULL;
+ }
+ }
+ _eventQueueLock->Release();
+
+ return result;
+}
+
+void TizenAppForm::pushEvent(Common::EventType type, const Point &currentPosition) {
+ TizenSystem *system = (TizenSystem *)g_system;
+ TizenGraphicsManager *graphics = system->getGraphics();
+ if (graphics) {
+ // graphics could be NULL at startup or when
+ // displaying the system error screen
+ Common::Event e;
+ e.type = type;
+ e.mouse.x = currentPosition.x;
+ e.mouse.y = currentPosition.y > MIN_TOUCH_Y ? currentPosition.y : 1;
+
+ bool moved = graphics->moveMouse(e.mouse.x, e.mouse.y);
+
+ _eventQueueLock->Acquire();
+
+ if (moved && type != Common::EVENT_MOUSEMOVE) {
+ Common::Event moveEvent;
+ moveEvent.type = Common::EVENT_MOUSEMOVE;
+ moveEvent.mouse = e.mouse;
+ _eventQueue.push(moveEvent);
+ }
+
+ _eventQueue.push(e);
+ _eventQueueLock->Release();
+ }
+}
+
+void TizenAppForm::pushKey(Common::KeyCode keycode) {
+ if (_eventQueueLock) {
+ Common::Event e;
+ e.synthetic = false;
+ e.kbd.keycode = keycode;
+ e.kbd.ascii = keycode;
+ e.kbd.flags = 0;
+
+ _eventQueueLock->Acquire();
+ e.type = Common::EVENT_KEYDOWN;
+ _eventQueue.push(e);
+ e.type = Common::EVENT_KEYUP;
+ _eventQueue.push(e);
+ _eventQueueLock->Release();
+ }
+}
+
+void TizenAppForm::setButtonShortcut() {
+ switch (_buttonState) {
+ case kLeftButton:
+ setMessage(_s("Right Click Once"));
+ _buttonState = kRightButtonOnce;
+ break;
+ case kRightButtonOnce:
+ setMessage(_s("Right Click"));
+ _buttonState = kRightButton;
+ break;
+ case kRightButton:
+ setMessage(_s("Move Only"));
+ _buttonState = kMoveOnly;
+ break;
+ case kMoveOnly:
+ setMessage(_s("Left Click"));
+ _buttonState = kLeftButton;
+ break;
+ }
+}
+
+void TizenAppForm::setMessage(const char *message) {
+ if (_eventQueueLock) {
+ _eventQueueLock->Acquire();
+ _osdMessage = message;
+ _eventQueueLock->Release();
+ }
+}
+
+void TizenAppForm::setShortcut() {
+ logEntered();
+ // cycle to the next shortcut
+ switch (_shortcut) {
+ case kControlMouse:
+ setMessage(_s("Escape Key"));
+ _shortcut = kEscapeKey;
+ break;
+
+ case kEscapeKey:
+ setMessage(_s("Game Menu"));
+ _shortcut = kGameMenu;
+ break;
+
+ case kGameMenu:
+ setMessage(_s("Show Keypad"));
+ _shortcut = kShowKeypad;
+ break;
+
+ case kShowKeypad:
+ setMessage(_s("Control Mouse"));
+ _shortcut = kControlMouse;
+ break;
+ }
+}
+
+void TizenAppForm::invokeShortcut() {
+ logEntered();
+ switch (_shortcut) {
+ case kControlMouse:
+ setButtonShortcut();
+ break;
+
+ case kEscapeKey:
+ pushKey(Common::KEYCODE_ESCAPE);
+ break;
+
+ case kGameMenu:
+ _buttonState = kLeftButton;
+ pushKey(Common::KEYCODE_F5);
+ break;
+
+ case kShowKeypad:
+ showKeypad();
+ break;
+ }
+}
+
+void TizenAppForm::showKeypad() {
+ // display the soft keyboard
+ if (_state == kActiveState) {
+ _buttonState = kLeftButton;
+ pushKey(Common::KEYCODE_F7);
+ }
+}
+
+int TizenAppForm::getTouchCount() {
+ Tizen::Ui::TouchEventManager *touch = Tizen::Ui::TouchEventManager::GetInstance();
+ IListT<TouchEventInfo *> *touchList = touch->GetTouchInfoListN();
+ int touchCount = touchList->GetCount();
+ touchList->RemoveAll();
+ delete touchList;
+ return touchCount;
+}
+
+void TizenAppForm::OnTouchDoublePressed(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ if (_buttonState != kMoveOnly) {
+ pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
+ currentPosition);
+ pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
+ currentPosition);
+ }
+}
+
+void TizenAppForm::OnTouchFocusIn(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+}
+
+void TizenAppForm::OnTouchFocusOut(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+}
+
+void TizenAppForm::OnTouchLongPressed(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ logEntered();
+ if (_buttonState != kLeftButton) {
+ pushKey(Common::KEYCODE_RETURN);
+ }
+}
+
+void TizenAppForm::OnTouchMoved(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ if (!_gestureMode) {
+ pushEvent(Common::EVENT_MOUSEMOVE, currentPosition);
+ }
+}
+
+void TizenAppForm::OnTouchPressed(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ if (getTouchCount() > 1) {
+ _gestureMode = true;
+ } else if (_buttonState != kMoveOnly) {
+ pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
+ currentPosition);
+ }
+}
+
+void TizenAppForm::OnTouchReleased(const Control &source,
+ const Point &currentPosition, const TouchEventInfo &touchInfo) {
+ if (_gestureMode) {
+ int touchCount = getTouchCount();
+ if (touchCount == 1) {
+ setShortcut();
+ } else {
+ if (touchCount == 2) {
+ invokeShortcut();
+ }
+ _gestureMode = false;
+ }
+ } else if (_buttonState != kMoveOnly) {
+ pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONUP : Common::EVENT_RBUTTONUP,
+ currentPosition);
+ if (_buttonState == kRightButtonOnce) {
+ _buttonState = kLeftButton;
+ }
+ // flick to skip dialog
+ if (touchInfo.IsFlicked()) {
+ pushKey(Common::KEYCODE_PERIOD);
+ }
+ }
+}
+
diff --git a/backends/platform/tizen/form.h b/backends/platform/tizen/form.h
new file mode 100644
index 0000000000..64c447d409
--- /dev/null
+++ b/backends/platform/tizen/form.h
@@ -0,0 +1,113 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TIZEN_FORM_H
+#define TIZEN_FORM_H
+
+#include <FApp.h>
+#include <FUi.h>
+#include <FSystem.h>
+#include <FBase.h>
+#include <FUiITouchEventListener.h>
+#include <FUiITextEventListener.h>
+
+#include "config.h"
+#include "common/scummsys.h"
+#include "common/events.h"
+#include "common/queue.h"
+#include "common/mutex.h"
+#include "engines/engine.h"
+
+using namespace Tizen::Ui;
+using namespace Tizen::Graphics;
+using namespace Tizen::Base::Runtime;
+
+//
+// TizenAppForm
+//
+class TizenAppForm :
+ public Controls::Form,
+ public IRunnable,
+ public IOrientationEventListener,
+ public ITouchEventListener {
+
+public:
+ TizenAppForm();
+ virtual ~TizenAppForm();
+
+ result Construct();
+ bool pollEvent(Common::Event &event);
+ bool isClosing() { return _state == kClosingState; }
+ bool isStarting() { return _state == kInitState; }
+ void pushKey(Common::KeyCode keycode);
+ void exitSystem();
+ void showKeypad();
+
+private:
+ Tizen::Base::Object *Run();
+ result OnInitializing(void);
+ result OnDraw(void);
+ void OnOrientationChanged(const Control &source,
+ OrientationStatus orientationStatus);
+ void OnTouchDoublePressed(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchFocusIn(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchFocusOut(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchLongPressed(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchMoved(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchPressed(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+ void OnTouchReleased(const Control &source,
+ const Point &currentPosition,
+ const TouchEventInfo &touchInfo);
+
+ void pushEvent(Common::EventType type, const Point &currentPosition);
+ void terminate();
+ void setButtonShortcut();
+ void setMessage(const char *message);
+ void setShortcut();
+ void invokeShortcut();
+ int getTouchCount();
+ bool gameActive() { return _state == kActiveState && g_engine != NULL && !g_engine->isPaused(); }
+
+ // event handling
+ bool _gestureMode;
+ const char *_osdMessage;
+ Tizen::Base::Runtime::Thread *_gameThread;
+ Tizen::Base::Runtime::Mutex *_eventQueueLock;
+ Common::Queue<Common::Event> _eventQueue;
+ enum { kInitState, kActiveState, kClosingState, kDoneState, kErrorState } _state;
+ enum { kLeftButton, kRightButtonOnce, kRightButton, kMoveOnly } _buttonState;
+ enum { kControlMouse, kEscapeKey, kGameMenu, kShowKeypad } _shortcut;
+};
+
+#endif
diff --git a/backends/platform/bada/fs.cpp b/backends/platform/tizen/fs.cpp
index 37ca496d18..f8b32f4239 100644
--- a/backends/platform/bada/fs.cpp
+++ b/backends/platform/tizen/fs.cpp
@@ -20,33 +20,38 @@
*/
#include "config.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/fs.h"
+#include "common/translation.h"
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/fs.h"
+
+#include <FAppApp.h>
#define BUFFER_SIZE 1024
-// internal BADA paths
-#define PATH_ROOT "/"
-#define PATH_HOME "/Home"
-#define PATH_HOME_SHARE "/Home/Share"
-#define PATH_HOME_SHARE2 "/Home/Share2"
-#define PATH_HOME_X "/Home/"
-#define PATH_HOME_EXT "/HomeExt"
-#define PATH_MEDIA "/Media"
-#define PATH_CARD "/Storagecard"
-#define PATH_CARD_MEDIA "/Storagecard/Media"
+using namespace Tizen::App;
+
+//
+// converts a Tizen (wchar) String into a scummVM (char) string
+//
+Common::String fromString(const Tizen::Base::String &in) {
+ ByteBuffer *buf = StringUtil::StringToUtf8N(in);
+ Common::String result((const char*)buf->GetPointer());
+ delete buf;
+ return result;
+}
//
-// BadaFileStream
+// TizenFileStream
//
-class BadaFileStream : public Common::SeekableReadStream,
- public Common::WriteStream,
- public Common::NonCopyable {
+class TizenFileStream :
+ public Common::SeekableReadStream,
+ public Common::WriteStream,
+ public Common::NonCopyable {
public:
- static BadaFileStream *makeFromPath(const String &path, bool writeMode);
+ static TizenFileStream *makeFromPath(const String &path, bool writeMode);
- BadaFileStream(File *file, bool writeMode);
- ~BadaFileStream();
+ TizenFileStream(File *file, bool writeMode);
+ ~TizenFileStream();
bool err() const;
void clearErr();
@@ -61,81 +66,81 @@ public:
uint32 read(void *dataPtr, uint32 dataSize);
private:
- byte buffer[BUFFER_SIZE];
- uint32 bufferIndex;
- uint32 bufferLength;
- bool writeMode;
- File *file;
+ byte _buffer[BUFFER_SIZE];
+ uint32 _bufferIndex;
+ uint32 _bufferLength;
+ bool _writeMode;
+ File *_file;
};
-BadaFileStream::BadaFileStream(File *ioFile, bool writeMode) :
- bufferIndex(0),
- bufferLength(0),
- writeMode(writeMode),
- file(ioFile) {
+TizenFileStream::TizenFileStream(File *ioFile, bool writeMode) :
+ _bufferIndex(0),
+ _bufferLength(0),
+ _writeMode(writeMode),
+ _file(ioFile) {
AppAssert(ioFile != 0);
}
-BadaFileStream::~BadaFileStream() {
- if (file) {
- if (writeMode) {
+TizenFileStream::~TizenFileStream() {
+ if (_file) {
+ if (_writeMode) {
flush();
}
- delete file;
+ delete _file;
}
}
-bool BadaFileStream::err() const {
+bool TizenFileStream::err() const {
result r = GetLastResult();
return (r != E_SUCCESS && r != E_END_OF_FILE);
}
-void BadaFileStream::clearErr() {
+void TizenFileStream::clearErr() {
SetLastResult(E_SUCCESS);
}
-bool BadaFileStream::eos() const {
- return (bufferLength - bufferIndex == 0) && (GetLastResult() == E_END_OF_FILE);
+bool TizenFileStream::eos() const {
+ return (_bufferLength - _bufferIndex == 0) && (GetLastResult() == E_END_OF_FILE);
}
-int32 BadaFileStream::pos() const {
- return file->Tell() - (bufferLength - bufferIndex);
+int32 TizenFileStream::pos() const {
+ return _file->Tell() - (_bufferLength - _bufferIndex);
}
-int32 BadaFileStream::size() const {
- int32 oldPos = file->Tell();
- file->Seek(FILESEEKPOSITION_END, 0);
+int32 TizenFileStream::size() const {
+ int32 oldPos = _file->Tell();
+ _file->Seek(FILESEEKPOSITION_END, 0);
- int32 length = file->Tell();
- SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, oldPos));
+ int32 length = _file->Tell();
+ SetLastResult(_file->Seek(FILESEEKPOSITION_BEGIN, oldPos));
return length;
}
-bool BadaFileStream::seek(int32 offs, int whence) {
+bool TizenFileStream::seek(int32 offs, int whence) {
bool result = false;
switch (whence) {
case SEEK_SET:
// set from start of file
- SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, offs));
+ SetLastResult(_file->Seek(FILESEEKPOSITION_BEGIN, offs));
result = (E_SUCCESS == GetLastResult());
break;
case SEEK_CUR:
// set relative to offs
- if (bufferIndex < bufferLength && bufferIndex > (uint32)-offs) {
+ if (_bufferIndex < _bufferLength && _bufferIndex > (uint32)-offs) {
// re-position within the buffer
SetLastResult(E_SUCCESS);
- bufferIndex += offs;
+ _bufferIndex += offs;
return true;
} else {
- offs -= (bufferLength - bufferIndex);
- if (offs < 0 && file->Tell() + offs < 0) {
+ offs -= (_bufferLength - _bufferIndex);
+ if (offs < 0 && _file->Tell() + offs < 0) {
// avoid negative positioning
offs = 0;
}
if (offs != 0) {
- SetLastResult(file->Seek(FILESEEKPOSITION_CURRENT, offs));
+ SetLastResult(_file->Seek(FILESEEKPOSITION_CURRENT, offs));
result = (E_SUCCESS == GetLastResult());
} else {
result = true;
@@ -145,7 +150,7 @@ bool BadaFileStream::seek(int32 offs, int whence) {
case SEEK_END:
// set relative to end - positive will increase the file size
- SetLastResult(file->Seek(FILESEEKPOSITION_END, offs));
+ SetLastResult(_file->Seek(FILESEEKPOSITION_END, offs));
result = (E_SUCCESS == GetLastResult());
break;
@@ -158,46 +163,46 @@ bool BadaFileStream::seek(int32 offs, int whence) {
AppLog("seek failed");
}
- bufferIndex = bufferLength = 0;
+ _bufferIndex = _bufferLength = 0;
return result;
}
-uint32 BadaFileStream::read(void *ptr, uint32 len) {
+uint32 TizenFileStream::read(void *ptr, uint32 len) {
uint32 result = 0;
if (!eos()) {
- if (bufferIndex < bufferLength) {
+ if (_bufferIndex < _bufferLength) {
// use existing buffer
- uint32 available = bufferLength - bufferIndex;
+ uint32 available = _bufferLength - _bufferIndex;
if (len <= available) {
// use allocation
- memcpy((byte *)ptr, &buffer[bufferIndex], len);
- bufferIndex += len;
+ memcpy((byte *)ptr, &_buffer[_bufferIndex], len);
+ _bufferIndex += len;
result = len;
} else {
// use remaining allocation
- memcpy((byte *)ptr, &buffer[bufferIndex], available);
+ memcpy((byte *)ptr, &_buffer[_bufferIndex], available);
uint32 remaining = len - available;
result = available;
if (remaining) {
- result += file->Read(((byte *)ptr) + available, remaining);
+ result += _file->Read(((byte *)ptr) + available, remaining);
}
- bufferIndex = bufferLength = 0;
+ _bufferIndex = _bufferLength = 0;
}
} else if (len < BUFFER_SIZE) {
// allocate and use buffer
- bufferIndex = 0;
- bufferLength = file->Read(buffer, BUFFER_SIZE);
- if (bufferLength) {
- if (bufferLength < len) {
- len = bufferLength;
+ _bufferIndex = 0;
+ _bufferLength = _file->Read(_buffer, BUFFER_SIZE);
+ if (_bufferLength) {
+ if (_bufferLength < len) {
+ len = _bufferLength;
}
- memcpy((byte *)ptr, buffer, len);
- result = bufferIndex = len;
+ memcpy((byte *)ptr, _buffer, len);
+ result = _bufferIndex = len;
}
} else {
- result = file->Read((byte *)ptr, len);
- bufferIndex = bufferLength = 0;
+ result = _file->Read((byte *)ptr, len);
+ _bufferIndex = _bufferLength = 0;
}
} else {
AppLog("Attempted to read past EOS");
@@ -205,59 +210,77 @@ uint32 BadaFileStream::read(void *ptr, uint32 len) {
return result;
}
-uint32 BadaFileStream::write(const void *ptr, uint32 len) {
- result r = file->Write(ptr, len);
+uint32 TizenFileStream::write(const void *ptr, uint32 len) {
+ result r = _file->Write(ptr, len);
SetLastResult(r);
return (r == E_SUCCESS ? len : 0);
}
-bool BadaFileStream::flush() {
+bool TizenFileStream::flush() {
logEntered();
- SetLastResult(file->Flush());
+ SetLastResult(_file->Flush());
return (E_SUCCESS == GetLastResult());
}
-BadaFileStream *BadaFileStream::makeFromPath(const String &path, bool writeMode) {
+TizenFileStream *TizenFileStream::makeFromPath(const String &path, bool writeMode) {
File *ioFile = new File();
String filePath = path;
if (writeMode && (path[0] != '.' && path[0] != '/')) {
- filePath.Insert(PATH_HOME_X, 0);
+ filePath.Insert(App::GetInstance()->GetAppDataPath() + L"/", 0);
}
AppLog("Open file %S", filePath.GetPointer());
-
+ TizenFileStream *stream;
result r = ioFile->Construct(filePath, writeMode ? L"w" : L"r", writeMode);
if (r == E_SUCCESS) {
- return new BadaFileStream(ioFile, writeMode);
+ stream = new TizenFileStream(ioFile, writeMode);
+ } else {
+ AppLog("Failed to open file");
+ delete ioFile;
+ stream = NULL;
}
-
- AppLog("Failed to open file");
- delete ioFile;
- return 0;
-}
-
-//
-// converts a bada (wchar) String into a scummVM (char) string
-//
-Common::String fromString(const Osp::Base::String &in) {
- ByteBuffer *buf = StringUtil::StringToUtf8N(in);
- Common::String result((const char*)buf->GetPointer());
- delete buf;
-
- return result;
+ return stream;
}
//
-// BadaFilesystemNode
+// TizenFilesystemNode
//
-BadaFilesystemNode::BadaFilesystemNode(const Common::String &nodePath) {
+TizenFilesystemNode::TizenFilesystemNode(const Common::String &nodePath) {
AppAssert(nodePath.size() > 0);
init(nodePath);
}
-BadaFilesystemNode::BadaFilesystemNode(const Common::String &root,
- const Common::String &nodePath) {
+TizenFilesystemNode::TizenFilesystemNode(SystemPath systemPath) {
+ switch (systemPath) {
+ case kData:
+ _unicodePath = App::GetInstance()->GetAppDataPath();
+ _displayName = _s("[ Data ]");
+ break;
+ case kResource:
+ _unicodePath = App::GetInstance()->GetAppResourcePath();
+ _displayName = _s("[ Resources ]");
+ break;
+ case kSdCard:
+ _unicodePath = Tizen::System::Environment::GetExternalStoragePath();
+ _displayName = _s("[ SDCard ]");
+ break;
+ case kMedia:
+ _unicodePath = Tizen::System::Environment::GetMediaPath();
+ _displayName = _s("[ Media ]");
+ break;
+ case kShared:
+ _unicodePath = App::GetInstance()->GetAppSharedPath();
+ _displayName = _s("[ Shared ]");
+ break;
+ }
+ _path = ::fromString(_unicodePath);
+ _isValid = _isVirtualDir = !IsFailed(File::GetAttributes(_unicodePath, _attr));
+}
+
+TizenFilesystemNode::TizenFilesystemNode(const Common::String &root, const Common::String &nodePath) {
+ AppLog("TizenFilesystemNode '%s' '%s'", root.c_str(), nodePath.c_str());
+
// Make sure the string contains no slashes
AppAssert(!nodePath.contains('/'));
@@ -272,71 +295,54 @@ BadaFilesystemNode::BadaFilesystemNode(const Common::String &root,
init(newPath);
}
-void BadaFilesystemNode::init(const Common::String &nodePath) {
+void TizenFilesystemNode::init(const Common::String &nodePath) {
// Normalize the path (that is, remove unneeded slashes etc.)
_path = Common::normalizePath(nodePath, '/');
_displayName = Common::lastPathComponent(_path, '/');
StringUtil::Utf8ToString(_path.c_str(), _unicodePath);
- _isVirtualDir = (_path == PATH_ROOT ||
- _path == PATH_HOME ||
- _path == PATH_HOME_SHARE ||
- _path == PATH_HOME_SHARE2 ||
- _path == PATH_CARD);
+ _isVirtualDir = (_path == "/");
_isValid = _isVirtualDir || !IsFailed(File::GetAttributes(_unicodePath, _attr));
}
-bool BadaFilesystemNode::exists() const {
+bool TizenFilesystemNode::exists() const {
return _isValid;
}
-bool BadaFilesystemNode::isReadable() const {
+bool TizenFilesystemNode::isReadable() const {
return _isVirtualDir || _isValid;
}
-bool BadaFilesystemNode::isDirectory() const {
+bool TizenFilesystemNode::isDirectory() const {
return _isVirtualDir || (_isValid && _attr.IsDirectory());
}
-bool BadaFilesystemNode::isWritable() const {
- bool result = (_isValid && !_isVirtualDir && !_attr.IsDirectory() && !_attr.IsReadOnly());
- if (_path == PATH_HOME ||
- _path == PATH_HOME_EXT ||
- _path == PATH_HOME_SHARE ||
- _path == PATH_HOME_SHARE2) {
- result = true;
+bool TizenFilesystemNode::isWritable() const {
+ bool result = (_isValid && !_attr.IsReadOnly());
+ if (_unicodePath == App::GetInstance()->GetAppResourcePath()) {
+ result = false;
}
return result;
}
-AbstractFSNode *BadaFilesystemNode::getChild(const Common::String &n) const {
+AbstractFSNode *TizenFilesystemNode::getChild(const Common::String &n) const {
AppAssert(!_path.empty());
AppAssert(isDirectory());
- return new BadaFilesystemNode(_path, n);
+ return new TizenFilesystemNode(_path, n);
}
-bool BadaFilesystemNode::getChildren(AbstractFSList &myList,
- ListMode mode, bool hidden) const {
+bool TizenFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
AppAssert(isDirectory());
bool result = false;
- if (_isVirtualDir && mode != Common::FSNode::kListFilesOnly) {
- // present well known BADA file system areas
- if (_path == PATH_ROOT) {
- myList.push_back(new BadaFilesystemNode(PATH_HOME));
- myList.push_back(new BadaFilesystemNode(PATH_HOME_EXT));
- myList.push_back(new BadaFilesystemNode(PATH_MEDIA));
- myList.push_back(new BadaFilesystemNode(PATH_CARD));
- result = true; // no more entries
- } else if (_path == PATH_CARD) {
- myList.push_back(new BadaFilesystemNode(PATH_CARD_MEDIA));
- result = true; // no more entries
- } else if (_path == PATH_HOME) {
- // ensure share path is always included
- myList.push_back(new BadaFilesystemNode(PATH_HOME_SHARE));
- myList.push_back(new BadaFilesystemNode(PATH_HOME_SHARE2));
- }
+ if (_isVirtualDir && mode != Common::FSNode::kListFilesOnly && _path == "/") {
+ // present well known TIZEN file system areas
+ myList.push_back(new TizenFilesystemNode(kData));
+ myList.push_back(new TizenFilesystemNode(kResource));
+ myList.push_back(new TizenFilesystemNode(kSdCard));
+ myList.push_back(new TizenFilesystemNode(kMedia));
+ myList.push_back(new TizenFilesystemNode(kShared));
}
if (!result) {
@@ -358,7 +364,7 @@ bool BadaFilesystemNode::getChildren(AbstractFSList &myList,
DirEntry dirEntry = pDirEnum->GetCurrentDirEntry();
// skip 'invisible' files if necessary
- Osp::Base::String fileName = dirEntry.GetName();
+ Tizen::Base::String fileName = dirEntry.GetName();
if (fileName[0] == '.' && !hidden) {
continue;
@@ -374,7 +380,7 @@ bool BadaFilesystemNode::getChildren(AbstractFSList &myList,
(mode == Common::FSNode::kListDirectoriesOnly && !dirEntry.IsDirectory())) {
continue;
}
- myList.push_back(new BadaFilesystemNode(_path, fromString(fileName)));
+ myList.push_back(new TizenFilesystemNode(_path, ::fromString(fileName)));
}
}
@@ -392,9 +398,9 @@ bool BadaFilesystemNode::getChildren(AbstractFSList &myList,
return result;
}
-AbstractFSNode *BadaFilesystemNode::getParent() const {
- logEntered();
- if (_path == PATH_ROOT) {
+AbstractFSNode *TizenFilesystemNode::getParent() const {
+ logEntered();
+ if (_path == "/") {
return 0; // The filesystem root has no parent
}
@@ -412,22 +418,22 @@ AbstractFSNode *BadaFilesystemNode::getParent() const {
// there simply is no parent.
// TODO: We could also resolve this by assuming that the parent is the
// current working directory, and returning a node referring to that.
- return 0;
+ return NULL;
}
- return new BadaFilesystemNode(Common::String(start, end));
+ return new TizenFilesystemNode(Common::String(start, end));
}
-Common::SeekableReadStream *BadaFilesystemNode::createReadStream() {
- Common::SeekableReadStream *result = BadaFileStream::makeFromPath(_unicodePath, false);
+Common::SeekableReadStream *TizenFilesystemNode::createReadStream() {
+ Common::SeekableReadStream *result = TizenFileStream::makeFromPath(_unicodePath, false);
if (result != NULL) {
_isValid = !IsFailed(File::GetAttributes(_unicodePath, _attr));
}
return result;
}
-Common::WriteStream *BadaFilesystemNode::createWriteStream() {
- Common::WriteStream *result = BadaFileStream::makeFromPath(_unicodePath, true);
+Common::WriteStream *TizenFilesystemNode::createWriteStream() {
+ Common::WriteStream *result = TizenFileStream::makeFromPath(_unicodePath, true);
if (result != NULL) {
_isValid = !IsFailed(File::GetAttributes(_unicodePath, _attr));
}
diff --git a/backends/platform/bada/fs.h b/backends/platform/tizen/fs.h
index d7d368ac20..0356aaad33 100644
--- a/backends/platform/bada/fs.h
+++ b/backends/platform/tizen/fs.h
@@ -19,8 +19,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef BADA_FILESYSTEM_H
-#define BADA_FILESYSTEM_H
+#ifndef TIZEN_FILESYSTEM_H
+#define TIZEN_FILESYSTEM_H
#include <FBaseString.h>
#include <FBaseUtilStringUtil.h>
@@ -32,23 +32,40 @@
#include "common/stream.h"
#include "backends/fs/abstract-fs.h"
-using namespace Osp::Io;
-using namespace Osp::Base;
-using namespace Osp::Base::Utility;
+using namespace Tizen::Io;
+using namespace Tizen::Base;
+using namespace Tizen::Base::Utility;
+
+//
+// converts a Tizen (wchar) String into a scummVM (char) string
+//
+Common::String fromString(const Tizen::Base::String &in);
+
+//
+// Enumerates the possible system paths
+//
+enum SystemPath { kData, kResource, kSdCard, kMedia, kShared };
/**
- * Implementation of the ScummVM file system API based on BADA.
+ * Implementation of the ScummVM file system API based on TIZEN.
*
* Parts of this class are documented in the base interface class, AbstractFSNode.
*/
-class BadaFilesystemNode : public AbstractFSNode {
+class TizenFilesystemNode : public AbstractFSNode {
public:
/**
- * Creates a BadaFilesystemNode for a given path.
+ * Creates a TizenFilesystemNode for a given path.
+ *
+ * @param path the path the new node should point to.
+ */
+ TizenFilesystemNode(const Common::String &path);
+
+ /**
+ * Creates a TizenFilesystemNode from the given Tizen internal path
*
* @param path the path the new node should point to.
*/
- BadaFilesystemNode(const Common::String &path);
+ TizenFilesystemNode(SystemPath systemPath);
Common::String getDisplayName() const { return _displayName; }
Common::String getName() const { return _displayName; }
@@ -67,8 +84,7 @@ public:
Common::WriteStream *createWriteStream();
protected:
- BadaFilesystemNode(const Common::String &root,
- const Common::String &p);
+ TizenFilesystemNode(const Common::String &root, const Common::String &p);
void init(const Common::String &nodePath);
Common::String _displayName;
diff --git a/backends/platform/bada/graphics.cpp b/backends/platform/tizen/graphics.cpp
index bd65c597c6..bf255cd264 100644
--- a/backends/platform/bada/graphics.cpp
+++ b/backends/platform/tizen/graphics.cpp
@@ -22,29 +22,40 @@
#include "graphics/fontman.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/graphics.h"
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/graphics.h"
//
-// BadaGraphicsManager
+// TizenGraphicsManager
//
-BadaGraphicsManager::BadaGraphicsManager(BadaAppForm *appForm) :
+TizenGraphicsManager::TizenGraphicsManager(TizenAppForm *appForm) :
_appForm(appForm),
_eglDisplay(EGL_DEFAULT_DISPLAY),
_eglSurface(EGL_NO_SURFACE),
- _eglConfig(0),
+ _eglConfig(NULL),
_eglContext(EGL_NO_CONTEXT),
_initState(true) {
assert(appForm != NULL);
_videoMode.fullscreen = true;
}
-const Graphics::Font *BadaGraphicsManager::getFontOSD() {
+TizenGraphicsManager::~TizenGraphicsManager() {
+ logEntered();
+
+ if (_eglDisplay != EGL_NO_DISPLAY) {
+ eglMakeCurrent(_eglDisplay, NULL, NULL, NULL);
+ if (_eglContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(_eglDisplay, _eglContext);
+ }
+ }
+}
+
+const Graphics::Font *TizenGraphicsManager::getFontOSD() {
return FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
}
-bool BadaGraphicsManager::moveMouse(int16 &x, int16 &y) {
+bool TizenGraphicsManager::moveMouse(int16 &x, int16 &y) {
int16 currentX = _cursorState.x;
int16 currentY = _cursorState.y;
@@ -62,7 +73,7 @@ bool BadaGraphicsManager::moveMouse(int16 &x, int16 &y) {
return (currentX != x || currentY != y);
}
-Common::List<Graphics::PixelFormat> BadaGraphicsManager::getSupportedFormats() const {
+Common::List<Graphics::PixelFormat> TizenGraphicsManager::getSupportedFormats() const {
logEntered();
Common::List<Graphics::PixelFormat> res;
@@ -73,33 +84,37 @@ Common::List<Graphics::PixelFormat> BadaGraphicsManager::getSupportedFormats() c
return res;
}
-bool BadaGraphicsManager::hasFeature(OSystem::Feature f) {
+bool TizenGraphicsManager::hasFeature(OSystem::Feature f) {
bool result = (f == OSystem::kFeatureFullscreenMode ||
- f == OSystem::kFeatureVirtualKeyboard ||
- OpenGLGraphicsManager::hasFeature(f));
+ f == OSystem::kFeatureVirtualKeyboard ||
+ OpenGLGraphicsManager::hasFeature(f));
return result;
}
-void BadaGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
- OpenGLGraphicsManager::setFeatureState(f, enable);
+void TizenGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
+ if (f == OSystem::kFeatureVirtualKeyboard && enable) {
+ _appForm->showKeypad();
+ } else {
+ OpenGLGraphicsManager::setFeatureState(f, enable);
+ }
}
-void BadaGraphicsManager::setReady() {
+void TizenGraphicsManager::setReady() {
_initState = false;
}
-void BadaGraphicsManager::updateScreen() {
+void TizenGraphicsManager::updateScreen() {
if (_transactionMode == kTransactionNone) {
internUpdateScreen();
}
}
-bool BadaGraphicsManager::loadEgl() {
+bool TizenGraphicsManager::loadEgl() {
logEntered();
EGLint numConfigs = 1;
EGLint eglConfigList[] = {
- EGL_RED_SIZE, 5,
+ EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_ALPHA_SIZE, 0,
@@ -132,8 +147,7 @@ bool BadaGraphicsManager::loadEgl() {
return false;
}
- if (EGL_FALSE == eglChooseConfig(_eglDisplay, eglConfigList,
- &_eglConfig, 1, &numConfigs) ||
+ if (EGL_FALSE == eglChooseConfig(_eglDisplay, eglConfigList, &_eglConfig, 1, &numConfigs) ||
EGL_SUCCESS != eglGetError()) {
systemError("eglChooseConfig() failed");
return false;
@@ -144,15 +158,13 @@ bool BadaGraphicsManager::loadEgl() {
return false;
}
- _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig,
- (EGLNativeWindowType)_appForm, NULL);
+ _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig, (EGLNativeWindowType)_appForm, NULL);
if (EGL_NO_SURFACE == _eglSurface || EGL_SUCCESS != eglGetError()) {
systemError("eglCreateWindowSurface() failed. EGL_NO_SURFACE");
return false;
}
- _eglContext = eglCreateContext(_eglDisplay, _eglConfig,
- EGL_NO_CONTEXT, eglContextList);
+ _eglContext = eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT, eglContextList);
if (EGL_NO_CONTEXT == _eglContext ||
EGL_SUCCESS != eglGetError()) {
systemError("eglCreateContext() failed");
@@ -169,7 +181,7 @@ bool BadaGraphicsManager::loadEgl() {
return true;
}
-bool BadaGraphicsManager::loadGFXMode() {
+bool TizenGraphicsManager::loadGFXMode() {
logEntered();
if (!loadEgl()) {
@@ -181,35 +193,28 @@ bool BadaGraphicsManager::loadGFXMode() {
_appForm->GetBounds(x, y, width, height);
_videoMode.overlayWidth = _videoMode.hardwareWidth = width;
_videoMode.overlayHeight = _videoMode.hardwareHeight = height;
- _videoMode.scaleFactor = 3; // for proportional sized cursor in the launcher
+ _videoMode.scaleFactor = 4; // for proportional sized cursor in the launcher
AppLog("screen size: %dx%d", _videoMode.hardwareWidth, _videoMode.hardwareHeight);
return OpenGLGraphicsManager::loadGFXMode();
}
-void BadaGraphicsManager::loadTextures() {
+void TizenGraphicsManager::loadTextures() {
logEntered();
-
OpenGLGraphicsManager::loadTextures();
-
- // prevent image skew in some games, see:
- // http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
-void BadaGraphicsManager::internUpdateScreen() {
+void TizenGraphicsManager::internUpdateScreen() {
if (!_initState) {
OpenGLGraphicsManager::internUpdateScreen();
eglSwapBuffers(_eglDisplay, _eglSurface);
- } else {
- showSplash();
}
}
-void BadaGraphicsManager::unloadGFXMode() {
+void TizenGraphicsManager::unloadGFXMode() {
logEntered();
- if (EGL_NO_DISPLAY != _eglDisplay) {
+ if (_eglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(_eglDisplay, NULL, NULL, NULL);
if (_eglContext != EGL_NO_CONTEXT) {
@@ -227,35 +232,6 @@ void BadaGraphicsManager::unloadGFXMode() {
}
_eglConfig = NULL;
-
OpenGLGraphicsManager::unloadGFXMode();
logLeaving();
}
-
-// display a simple splash screen until launcher is ready
-void BadaGraphicsManager::showSplash() {
- Canvas canvas;
- canvas.Construct();
- canvas.SetBackgroundColor(Color::COLOR_BLACK);
- canvas.Clear();
-
- int x = _videoMode.hardwareWidth / 3;
- int y = _videoMode.hardwareHeight / 3;
-
- Font *pFont = new Font();
- pFont->Construct(FONT_STYLE_ITALIC | FONT_STYLE_BOLD, 55);
- canvas.SetFont(*pFont);
- canvas.SetForegroundColor(Color::COLOR_GREEN);
- canvas.DrawText(Point(x, y), L"ScummVM");
- delete pFont;
-
- pFont = new Font();
- pFont->Construct(FONT_STYLE_ITALIC | FONT_STYLE_BOLD, 35);
- canvas.SetFont(*pFont);
- canvas.SetForegroundColor(Color::COLOR_WHITE);
- canvas.DrawText(Point(x + 70, y + 50), L"Loading ...");
- delete pFont;
-
- canvas.Show();
-
-}
diff --git a/backends/platform/bada/graphics.h b/backends/platform/tizen/graphics.h
index b2aaca43bc..27e5a6aaeb 100644
--- a/backends/platform/bada/graphics.h
+++ b/backends/platform/tizen/graphics.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef BADA_GRAPHICS_H
-#define BADA_GRAPHICS_H
+#ifndef TIZEN_GRAPHICS_H
+#define TIZEN_GRAPHICS_H
#include <FBase.h>
#include <FGraphics.h>
@@ -33,15 +33,16 @@
#include "config.h"
#include "backends/graphics/opengl/opengl-graphics.h"
#include "graphics/font.h"
-#include "backends/platform/bada/form.h"
+#include "backends/platform/tizen/form.h"
-using namespace Osp::Graphics;
-using namespace Osp::Graphics::Opengl;
-using namespace Osp::App;
+using namespace Tizen::Graphics;
+using namespace Tizen::Graphics::Opengl;
+using namespace Tizen::App;
-class BadaGraphicsManager : public OpenGLGraphicsManager {
+class TizenGraphicsManager : public OpenGLGraphicsManager {
public:
- BadaGraphicsManager(BadaAppForm *appForm);
+ TizenGraphicsManager(TizenAppForm *appForm);
+ virtual ~TizenGraphicsManager();
Common::List<Graphics::PixelFormat> getSupportedFormats() const;
bool hasFeature(OSystem::Feature f);
@@ -61,7 +62,7 @@ private:
void showSplash();
bool loadEgl();
- BadaAppForm *_appForm;
+ TizenAppForm *_appForm;
EGLDisplay _eglDisplay;
EGLSurface _eglSurface;
EGLConfig _eglConfig;
diff --git a/backends/platform/bada/main.cpp b/backends/platform/tizen/main.cpp
index 8c40f24dd1..b12cc3adc9 100644
--- a/backends/platform/bada/main.cpp
+++ b/backends/platform/tizen/main.cpp
@@ -24,44 +24,28 @@
#include <FApp.h>
#include <FSystem.h>
-#include "backends/platform/bada/portdefs.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/application.h"
+#include "backends/platform/tizen/application.h"
-using namespace Osp::Base;
-using namespace Osp::Base::Collection;
-
-C_LINKAGE_BEGIN
-
-_EXPORT_ int OspMain(int argc, char *pArgv[]);
+using namespace Tizen::Base;
+using namespace Tizen::Base::Collection;
/**
- * The entry function of bada application called by the operating system.
+ * The entry function of tizen application called by the operating system.
*/
-int OspMain(int argc, char *pArgv[]) {
+extern "C" _EXPORT_ int OspMain(int argc, char *pArgv[]) {
result r = E_SUCCESS;
AppLog("Application started.");
- ArrayList *pArgs = new ArrayList();
- pArgs->Construct();
-
+ ArrayList args(SingleObjectDeleter);
+ args.Construct();
for (int i = 0; i < argc; i++) {
- pArgs->Add(*(new String(pArgv[i])));
+ args.Add(new (std::nothrow) String(pArgv[i]));
}
- r = Osp::App::Application::Execute(BadaScummVM::createInstance, pArgs);
- if (IsFailed(r)) {
- r &= 0x0000FFFF;
- }
-
- pArgs->RemoveAll(true);
- delete pArgs;
+ r = Tizen::App::UiApp::Execute(TizenScummVM::createInstance, &args);
+ TryLog(r == E_SUCCESS, "[%s] Application execution failed", GetErrorMessage(r));
AppLog("Application finished.");
return static_cast<int>(r);
}
-C_LINKAGE_END
-
-
diff --git a/backends/platform/bada/missing.cpp b/backends/platform/tizen/missing.cpp
index 10d45ca4b5..5ac55d0f6c 100644
--- a/backends/platform/bada/missing.cpp
+++ b/backends/platform/tizen/missing.cpp
@@ -26,7 +26,7 @@
#include <FSystem.h>
#include <FBase.h>
-#include "backends/platform/bada/portdefs.h"
+#include "backends/platform/tizen/portdefs.h"
#include <stdio.h>
#include <string.h>
@@ -48,7 +48,7 @@ void __assert_func(const char *file, int line,
systemError(buffer);
}
-void stderr_fprintf(void*, const char *format, ...) {
+void stderr_fprintf(void *, const char *format, ...) {
va_list ap;
char buffer[BUF_SIZE];
@@ -59,7 +59,7 @@ void stderr_fprintf(void*, const char *format, ...) {
AppLog(buffer);
}
-void stderr_vfprintf(void*, const char *format, va_list ap) {
+void stderr_vfprintf(void *, const char *format, va_list ap) {
char buffer[BUF_SIZE];
vsnprintf(buffer, sizeof(buffer), format, ap);
AppLog(buffer);
@@ -79,35 +79,4 @@ int printf(const char *format, ...) {
return result;
}
-int sprintf(char *str, const char *format, ...) {
- va_list ap;
- int result;
- char buffer[BUF_SIZE];
-
- va_start(ap, format);
- result = vsnprintf(buffer, sizeof(buffer), format, ap);
- va_end(ap);
-
- strcpy(str, buffer);
-
- return result;
-}
-
-char *strdup(const char *strSource) {
- char *buffer;
- int len = strlen(strSource) + 1;
- buffer = (char *)malloc(len);
- if (buffer) {
- memcpy(buffer, strSource, len);
- }
- return buffer;
-}
-
-int vsprintf(char *str, const char *format, va_list ap) {
- char buffer[BUF_SIZE];
- int result = vsnprintf(buffer, sizeof(buffer), format, ap);
- strcpy(str, buffer);
- return result;
-}
-
C_LINKAGE_END
diff --git a/backends/platform/bada/portdefs.h b/backends/platform/tizen/portdefs.h
index 813c5acde3..050ce7d1e0 100644
--- a/backends/platform/bada/portdefs.h
+++ b/backends/platform/tizen/portdefs.h
@@ -43,6 +43,9 @@
#define C_LINKAGE_END
#endif
+// value missing from osp gl headers
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+
C_LINKAGE_BEGIN
// for libFLAC
@@ -51,11 +54,11 @@ C_LINKAGE_BEGIN
#define fseeko fseek
#define ftello ftell
-// overcome use of fprintf since bada/newlib (1.2) does not
+// overcome use of fprintf since newlib (1.2) does not
// support stderr/stdout (undefined reference to `_impure_ptr').
-void stderr_fprintf(void*, const char *format, ...);
-void stderr_vfprintf(void*, const char *format, va_list ap);
+void stderr_fprintf(void *, const char *format, ...);
+void stderr_vfprintf(void *, const char *format, va_list ap);
#undef fprintf
#undef vfprintf
@@ -75,10 +78,7 @@ void stderr_vfprintf(void*, const char *format, va_list ap);
#define vfprintf stderr_vfprintf
int printf(const char *format, ...);
-int sprintf(char *str, const char *format, ...);
int simple_sscanf(const char *buffer, const char *format, ...);
-char *strdup(const char *s1);
-int vsprintf(char *str, const char *format, va_list ap);
C_LINKAGE_END
diff --git a/backends/platform/bada/sscanf.cpp b/backends/platform/tizen/sscanf.cpp
index aa846698f6..aa846698f6 100644
--- a/backends/platform/bada/sscanf.cpp
+++ b/backends/platform/tizen/sscanf.cpp
diff --git a/backends/platform/bada/system.cpp b/backends/platform/tizen/system.cpp
index 3f862c2571..54d92146e5 100644
--- a/backends/platform/bada/system.cpp
+++ b/backends/platform/tizen/system.cpp
@@ -34,53 +34,53 @@
#include "backends/audiocd/default/default-audiocd.h"
#include "backends/mutex/mutex.h"
#include "backends/fs/fs-factory.h"
-#include "backends/timer/bada/timer.h"
+#include "backends/timer/tizen/timer.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/system.h"
-#include "backends/platform/bada/graphics.h"
-#include "backends/platform/bada/audio.h"
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/system.h"
+#include "backends/platform/tizen/graphics.h"
+#include "backends/platform/tizen/audio.h"
-using namespace Osp::Base;
-using namespace Osp::Base::Runtime;
-using namespace Osp::Locales;
-using namespace Osp::Ui::Controls;
-using namespace Osp::System;
+using namespace Tizen::Base;
+using namespace Tizen::Base::Runtime;
+using namespace Tizen::Locales;
+using namespace Tizen::Ui;
+using namespace Tizen::Ui::Controls;
+using namespace Tizen::System;
-#define DEFAULT_CONFIG_FILE "/Home/scummvm.ini"
-#define RESOURCE_PATH "/Res"
+#define DEFAULT_CONFIG_FILE "scummvm.ini"
#define MUTEX_BUFFER_SIZE 5
//
-// BadaFilesystemFactory
+// TizenFilesystemFactory
//
-class BadaFilesystemFactory : public FilesystemFactory {
+class TizenFilesystemFactory : public FilesystemFactory {
AbstractFSNode *makeRootFileNode() const;
AbstractFSNode *makeCurrentDirectoryFileNode() const;
AbstractFSNode *makeFileNodePath(const Common::String &path) const;
};
-AbstractFSNode *BadaFilesystemFactory::makeRootFileNode() const {
- return new BadaFilesystemNode("/");
+AbstractFSNode *TizenFilesystemFactory::makeRootFileNode() const {
+ return new TizenFilesystemNode("/");
}
-AbstractFSNode *BadaFilesystemFactory::makeCurrentDirectoryFileNode() const {
- return new BadaFilesystemNode("/Home");
+AbstractFSNode *TizenFilesystemFactory::makeCurrentDirectoryFileNode() const {
+ return new TizenFilesystemNode("/");
}
-AbstractFSNode *BadaFilesystemFactory::makeFileNodePath(const Common::String &path) const {
+AbstractFSNode *TizenFilesystemFactory::makeFileNodePath(const Common::String &path) const {
AppAssert(!path.empty());
- return new BadaFilesystemNode(path);
+ return new TizenFilesystemNode(path);
}
//
-// BadaSaveFileManager
+// TizenSaveFileManager
//
-struct BadaSaveFileManager : public DefaultSaveFileManager {
+struct TizenSaveFileManager : public DefaultSaveFileManager {
bool removeSavefile(const Common::String &filename);
};
-bool BadaSaveFileManager::removeSavefile(const Common::String &filename) {
+bool TizenSaveFileManager::removeSavefile(const Common::String &filename) {
Common::String savePathName = getSavePath();
checkPath(Common::FSNode(savePathName));
@@ -95,18 +95,18 @@ bool BadaSaveFileManager::removeSavefile(const Common::String &filename) {
String unicodeFileName;
StringUtil::Utf8ToString(file.getPath().c_str(), unicodeFileName);
- switch (Osp::Io::File::Remove(unicodeFileName)) {
+ switch (Tizen::Io::File::Remove(unicodeFileName)) {
case E_SUCCESS:
return true;
case E_ILLEGAL_ACCESS:
setError(Common::kWritePermissionDenied, "Search or write permission denied: " +
- file.getName());
+ file.getName());
break;
default:
setError(Common::kPathDoesNotExist, "removeSavefile: '" + file.getName() +
- "' does not exist or path is invalid");
+ "' does not exist or path is invalid");
break;
}
@@ -114,40 +114,40 @@ bool BadaSaveFileManager::removeSavefile(const Common::String &filename) {
}
//
-// BadaMutexManager
+// TizenMutexManager
//
-struct BadaMutexManager : public MutexManager {
- BadaMutexManager();
- ~BadaMutexManager();
+struct TizenMutexManager : public MutexManager {
+ TizenMutexManager();
+ ~TizenMutexManager();
OSystem::MutexRef createMutex();
void lockMutex(OSystem::MutexRef mutex);
void unlockMutex(OSystem::MutexRef mutex);
void deleteMutex(OSystem::MutexRef mutex);
private:
- Mutex *buffer[MUTEX_BUFFER_SIZE];
+ Mutex *_buffer[MUTEX_BUFFER_SIZE];
};
-BadaMutexManager::BadaMutexManager() {
+TizenMutexManager::TizenMutexManager() {
for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) {
- buffer[i] = NULL;
+ _buffer[i] = NULL;
}
}
-BadaMutexManager::~BadaMutexManager() {
+TizenMutexManager::~TizenMutexManager() {
for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) {
- if (buffer[i] != NULL) {
- delete buffer[i];
+ if (_buffer[i] != NULL) {
+ delete _buffer[i];
}
}
}
-OSystem::MutexRef BadaMutexManager::createMutex() {
+OSystem::MutexRef TizenMutexManager::createMutex() {
Mutex *mutex = new Mutex();
mutex->Create();
for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) {
- if (buffer[i] == NULL) {
- buffer[i] = mutex;
+ if (_buffer[i] == NULL) {
+ _buffer[i] = mutex;
break;
}
}
@@ -155,22 +155,22 @@ OSystem::MutexRef BadaMutexManager::createMutex() {
return (OSystem::MutexRef) mutex;
}
-void BadaMutexManager::lockMutex(OSystem::MutexRef mutex) {
+void TizenMutexManager::lockMutex(OSystem::MutexRef mutex) {
Mutex *m = (Mutex *)mutex;
m->Acquire();
}
-void BadaMutexManager::unlockMutex(OSystem::MutexRef mutex) {
+void TizenMutexManager::unlockMutex(OSystem::MutexRef mutex) {
Mutex *m = (Mutex *)mutex;
m->Release();
}
-void BadaMutexManager::deleteMutex(OSystem::MutexRef mutex) {
+void TizenMutexManager::deleteMutex(OSystem::MutexRef mutex) {
Mutex *m = (Mutex *)mutex;
for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) {
- if (buffer[i] == m) {
- buffer[i] = NULL;
+ if (_buffer[i] == m) {
+ _buffer[i] = NULL;
}
}
@@ -178,84 +178,101 @@ void BadaMutexManager::deleteMutex(OSystem::MutexRef mutex) {
}
//
-// BadaEventManager
+// TizenEventManager
//
-struct BadaEventManager : public DefaultEventManager {
- BadaEventManager(Common::EventSource *boss);
+struct TizenEventManager : public DefaultEventManager {
+ TizenEventManager(Common::EventSource *boss);
void init();
int shouldQuit() const;
};
-BadaEventManager::BadaEventManager(Common::EventSource *boss) :
+TizenEventManager::TizenEventManager(Common::EventSource *boss) :
DefaultEventManager(boss) {
}
-void BadaEventManager::init() {
+void TizenEventManager::init() {
DefaultEventManager::init();
// theme and vkbd should have now loaded - clear the splash screen
- BadaSystem *system = (BadaSystem *)g_system;
- BadaGraphicsManager *graphics = system->getGraphics();
+ TizenSystem *system = (TizenSystem *)g_system;
+ TizenGraphicsManager *graphics = system->getGraphics();
if (graphics) {
graphics->setReady();
- graphics->updateScreen();
}
}
-int BadaEventManager::shouldQuit() const {
- BadaSystem *system = (BadaSystem *)g_system;
+int TizenEventManager::shouldQuit() const {
+ TizenSystem *system = (TizenSystem *)g_system;
return DefaultEventManager::shouldQuit() || system->isClosing();
}
//
-// BadaSystem
+// TizenAppFrame - avoid drawing the misplaced UiTheme at startup
//
-BadaSystem::BadaSystem(BadaAppForm *appForm) :
+struct TizenAppFrame : Frame {
+ result OnDraw(void) {
+ logEntered();
+ TizenAppForm *form = (TizenAppForm *)GetCurrentForm();
+ if (form->isStarting()) {
+ Canvas *canvas = GetCanvasN();
+ canvas->SetBackgroundColor(Color::GetColor(COLOR_ID_BLACK));
+ canvas->Clear();
+ delete canvas;
+ }
+ return E_SUCCESS;
+ }
+};
+
+//
+// TizenSystem
+//
+TizenSystem::TizenSystem(TizenAppForm *appForm) :
_appForm(appForm),
_audioThread(0),
_epoch(0) {
}
-result BadaSystem::Construct(void) {
+result TizenSystem::Construct(void) {
logEntered();
- _fsFactory = new BadaFilesystemFactory();
+ _fsFactory = new TizenFilesystemFactory();
if (!_fsFactory) {
return E_OUT_OF_MEMORY;
}
+ _resourcePath = fromString(App::GetInstance()->GetAppResourcePath());
return E_SUCCESS;
}
-BadaSystem::~BadaSystem() {
+TizenSystem::~TizenSystem() {
logEntered();
}
-result BadaSystem::initModules() {
+result TizenSystem::initModules() {
logEntered();
- _mutexManager = new BadaMutexManager();
+ _mutexManager = new TizenMutexManager();
if (!_mutexManager) {
return E_OUT_OF_MEMORY;
}
- _timerManager = new BadaTimerManager();
+ _timerManager = new TizenTimerManager();
if (!_timerManager) {
return E_OUT_OF_MEMORY;
}
- _savefileManager = new BadaSaveFileManager();
+ _savefileManager = new TizenSaveFileManager();
if (!_savefileManager) {
return E_OUT_OF_MEMORY;
}
- _graphicsManager = (GraphicsManager *)new BadaGraphicsManager(_appForm);
+ _graphicsManager = (GraphicsManager *)new TizenGraphicsManager(_appForm);
if (!_graphicsManager) {
return E_OUT_OF_MEMORY;
}
// depends on _graphicsManager when ENABLE_VKEYBD enabled
- _eventManager = new BadaEventManager(this);
+ _eventManager = new TizenEventManager(this);
if (!_eventManager) {
return E_OUT_OF_MEMORY;
}
@@ -284,19 +301,21 @@ result BadaSystem::initModules() {
return E_SUCCESS;
}
-void BadaSystem::initBackend() {
+void TizenSystem::initBackend() {
logEntered();
+ Common::String dataPath = fromString(App::GetInstance()->GetAppDataPath());
+
// use the mobile device theme
- ConfMan.set("gui_theme", "/Res/scummmobile");
+ ConfMan.set("gui_theme", _resourcePath + "scummmodern");
- // allow bada virtual keypad pack to be found
- ConfMan.set("vkeybdpath", "/Res/vkeybd_bada");
+ // allow tizen virtual keypad pack to be found
+ ConfMan.set("vkeybdpath", _resourcePath + "vkeybd_bada");
ConfMan.set("vkeybd_pack_name", "vkeybd_bada");
// set default save path to writable area
if (!ConfMan.hasKey("savepath")) {
- ConfMan.set("savepath", "/Home/Share");
+ ConfMan.set("savepath", dataPath);
}
// default to no auto-save
@@ -314,85 +333,93 @@ void BadaSystem::initBackend() {
AppLog("initModules failed");
} else {
OSystem::initBackend();
- }
- // replace kBigGUIFont using the large font from the scummmobile theme
- Common::File fontFile;
- Common::String fileName = "/Res/scummmobile/helvB14-iso-8859-1.fcc";
- BadaFilesystemNode file(fileName);
- if (file.exists()) {
- Common::SeekableReadStream *stream = file.createReadStream();
- if (stream) {
- if (fontFile.open(stream, fileName)) {
+ // replace kBigGUIFont for the vkbd and on-screen messages
+ Common::String fontCacheFile = dataPath + "helvR24.fcc";
+ TizenFilesystemNode file(fontCacheFile);
+ if (!file.exists()) {
+ Common::String bdfFile = _resourcePath + "fonts/helvR24.bdf";
+ TizenFilesystemNode file(bdfFile);
+ if (file.exists()) {
+ Common::SeekableReadStream *stream = file.createReadStream();
+ Common::File fontFile;
+ if (stream && fontFile.open(stream, bdfFile)) {
+ Graphics::BdfFont *font = Graphics::BdfFont::loadFont(fontFile);
+ Graphics::BdfFont::cacheFontData(*font, fontCacheFile);
+ FontMan.setFont(Graphics::FontManager::kBigGUIFont, font);
+ }
+ }
+ } else {
+ Common::SeekableReadStream *stream = file.createReadStream();
+ Common::File fontFile;
+ if (stream && fontFile.open(stream, fontCacheFile)) {
Graphics::BdfFont *font = Graphics::BdfFont::loadFromCache(fontFile);
if (font) {
- // use this font for the vkbd and on-screen messages
FontMan.setFont(Graphics::FontManager::kBigGUIFont, font);
}
}
}
}
-
logLeaving();
}
-void BadaSystem::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+void TizenSystem::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
// allow translations.dat and game .DAT files to be found
- s.addDirectory(RESOURCE_PATH, RESOURCE_PATH, priority);
+ s.addDirectory(_resourcePath, _resourcePath, priority);
}
-void BadaSystem::destroyBackend() {
+void TizenSystem::destroyBackend() {
closeAudio();
delete _graphicsManager;
- _graphicsManager = 0;
+ _graphicsManager = NULL;
delete _savefileManager;
- _savefileManager = 0;
+ _savefileManager = NULL;
delete _fsFactory;
- _fsFactory = 0;
+ _fsFactory = NULL;
delete _mixer;
- _mixer = 0;
+ _mixer = NULL;
delete _audiocdManager;
- _audiocdManager = 0;
+ _audiocdManager = NULL;
delete _timerManager;
- _timerManager = 0;
+ _timerManager = NULL;
delete _eventManager;
- _eventManager = 0;
+ _eventManager = NULL;
delete _mutexManager;
- _mutexManager = 0;
+ _mutexManager = NULL;
}
-bool BadaSystem::pollEvent(Common::Event &event) {
+bool TizenSystem::pollEvent(Common::Event &event) {
return _appForm->pollEvent(event);
}
-uint32 BadaSystem::getMillis() {
+uint32 TizenSystem::getMillis(bool skipRecord) {
long long result, ticks = 0;
SystemTime::GetTicks(ticks);
result = ticks - _epoch;
return result;
}
-void BadaSystem::delayMillis(uint msecs) {
+void TizenSystem::delayMillis(uint msecs) {
if (!_appForm->isClosing()) {
Thread::Sleep(msecs);
}
}
-void BadaSystem::updateScreen() {
+void TizenSystem::updateScreen() {
if (_graphicsManager != NULL) {
_graphicsManager->updateScreen();
}
}
-void BadaSystem::getTimeAndDate(TimeDate &td) const {
+void TizenSystem::getTimeAndDate(TimeDate &td) const {
DateTime currentTime;
if (E_SUCCESS == SystemTime::GetCurrentTime(WALL_TIME, currentTime)) {
@@ -410,11 +437,11 @@ void BadaSystem::getTimeAndDate(TimeDate &td) const {
}
}
-void BadaSystem::fatalError() {
+void TizenSystem::fatalError() {
systemError("ScummVM: Fatal internal error.");
}
-void BadaSystem::exitSystem() {
+void TizenSystem::exitSystem() {
if (_appForm) {
closeAudio();
closeGraphics();
@@ -422,7 +449,7 @@ void BadaSystem::exitSystem() {
}
}
-void BadaSystem::logMessage(LogMessageType::Type type, const char *message) {
+void TizenSystem::logMessage(LogMessageType::Type type, const char *message) {
if (type == LogMessageType::kError) {
systemError(message);
} else {
@@ -430,69 +457,70 @@ void BadaSystem::logMessage(LogMessageType::Type type, const char *message) {
}
}
-Common::SeekableReadStream *BadaSystem::createConfigReadStream() {
- BadaFilesystemNode file(DEFAULT_CONFIG_FILE);
+Common::SeekableReadStream *TizenSystem::createConfigReadStream() {
+ TizenFilesystemNode file(fromString(App::GetInstance()->GetAppDataPath()) + DEFAULT_CONFIG_FILE);
return file.createReadStream();
}
-Common::WriteStream *BadaSystem::createConfigWriteStream() {
- BadaFilesystemNode file(DEFAULT_CONFIG_FILE);
+Common::WriteStream *TizenSystem::createConfigWriteStream() {
+ TizenFilesystemNode file(fromString(App::GetInstance()->GetAppDataPath()) + DEFAULT_CONFIG_FILE);
return file.createWriteStream();
}
-void BadaSystem::closeAudio() {
+void TizenSystem::closeAudio() {
if (_audioThread) {
- _audioThread->Stop();
+ _audioThread->Quit();
_audioThread->Join();
delete _audioThread;
- _audioThread = 0;
+ _audioThread = NULL;
}
}
-void BadaSystem::closeGraphics() {
+void TizenSystem::closeGraphics() {
if (_graphicsManager) {
delete _graphicsManager;
- _graphicsManager = 0;
+ _graphicsManager = NULL;
}
}
-void BadaSystem::setMute(bool on) {
+void TizenSystem::setMute(bool on) {
// only change mute after eventManager init() has completed
if (_audioThread) {
- BadaGraphicsManager *graphics = getGraphics();
+ TizenGraphicsManager *graphics = getGraphics();
if (graphics && graphics->isReady()) {
_audioThread->setMute(on);
}
}
}
-int BadaSystem::setVolume(bool up, bool minMax) {
- int level = -1;
- if (_audioThread) {
- level = _audioThread->setVolume(up, minMax);
- }
- return level;
-}
-
//
// create the ScummVM system
//
-BadaAppForm *systemStart(Osp::App::Application *app) {
+TizenAppForm *systemStart(Tizen::App::Application *app) {
logEntered();
- BadaAppForm *appForm = new BadaAppForm();
+ Frame *appFrame = new (std::nothrow) TizenAppFrame();
+ if (!appFrame || appFrame->Construct() == E_FAILURE) {
+ AppLog("Failed to create appFrame");
+ return NULL;
+ }
+ app->AddFrame(*appFrame);
+
+ TizenAppForm *appForm = new TizenAppForm();
if (!appForm) {
AppLog("Failed to create appForm");
return NULL;
}
if (E_SUCCESS != appForm->Construct() ||
- E_SUCCESS != app->GetAppFrame()->GetFrame()->AddControl(*appForm)) {
+ E_SUCCESS != appFrame->AddControl(*appForm)) {
delete appForm;
AppLog("Failed to construct appForm");
return NULL;
}
+ appFrame->SetCurrentForm(appForm);
+ logLeaving();
return appForm;
}
@@ -502,13 +530,18 @@ BadaAppForm *systemStart(Osp::App::Application *app) {
void systemError(const char *message) {
AppLog("Fatal system error: %s", message);
- ArrayList *args = new ArrayList();
- args->Construct();
- args->Add(*(new String(message)));
- Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR, args);
+ if (strspn(message, "Config file buggy:") > 0) {
+ Tizen::Io::File::Remove(DEFAULT_CONFIG_FILE);
+ Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR_CONFIG, NULL);
+ } else {
+ ArrayList *args = new ArrayList();
+ args->Construct();
+ args->Add(*(new String(message)));
+ Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR, args);
+ }
if (g_system) {
- BadaSystem *system = (BadaSystem *)g_system;
+ TizenSystem *system = (TizenSystem *)g_system;
system->exitSystem();
}
}
diff --git a/backends/platform/bada/system.h b/backends/platform/tizen/system.h
index c28686cb3d..b38940cc95 100644
--- a/backends/platform/bada/system.h
+++ b/backends/platform/tizen/system.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef BADA_SYSTEM_H
-#define BADA_SYSTEM_H
+#ifndef TIZEN_SYSTEM_H
+#define TIZEN_SYSTEM_H
#include <FApp.h>
#include <FGraphics.h>
@@ -34,47 +34,46 @@
#include "common/scummsys.h"
#include "backends/modular-backend.h"
-#include "backends/platform/bada/fs.h"
-#include "backends/platform/bada/form.h"
-#include "backends/platform/bada/audio.h"
-#include "backends/platform/bada/graphics.h"
+#include "backends/platform/tizen/fs.h"
+#include "backends/platform/tizen/form.h"
+#include "backends/platform/tizen/audio.h"
+#include "backends/platform/tizen/graphics.h"
#if defined(_DEBUG)
-#define logEntered() AppLog("%s entered (%s %d)", \
- __FUNCTION__, __FILE__, __LINE__);
-#define logLeaving() AppLog("%s leaving (%s %d)", \
- __FUNCTION__, __FILE__, __LINE__);
+#define logEntered() AppLog("%s entered (%s %d)", __FUNCTION__, __FILE__, __LINE__);
+#define logLeaving() AppLog("%s leaving (%s %d)", __FUNCTION__, __FILE__, __LINE__);
#else
#define logEntered()
#define logLeaving()
#endif
-BadaAppForm *systemStart(Osp::App::Application *app);
+TizenAppForm *systemStart(Tizen::App::Application *app);
void systemError(const char *message);
-#define USER_MESSAGE_EXIT 1000
-#define USER_MESSAGE_EXIT_ERR 1001
+#define USER_MESSAGE_EXIT 1000
+#define USER_MESSAGE_EXIT_ERR 1001
+#define USER_MESSAGE_EXIT_ERR_CONFIG 1002
//
-// BadaSystem
+// TizenSystem
//
-class BadaSystem : public ModularBackend,
- Common::EventSource {
+class TizenSystem :
+ public ModularBackend,
+ Common::EventSource {
public:
- BadaSystem(BadaAppForm *appForm);
- ~BadaSystem();
+ TizenSystem(TizenAppForm *appForm);
+ ~TizenSystem();
result Construct();
void closeAudio();
void closeGraphics();
void destroyBackend();
void setMute(bool on);
- int setVolume(bool up, bool minMax);
void exitSystem();
bool isClosing() { return _appForm->isClosing(); }
- BadaGraphicsManager *getGraphics() {
- return (BadaGraphicsManager *)_graphicsManager;
+ TizenGraphicsManager *getGraphics() {
+ return (TizenGraphicsManager *)_graphicsManager;
}
private:
@@ -83,7 +82,7 @@ private:
void updateScreen();
bool pollEvent(Common::Event &event);
- uint32 getMillis();
+ uint32 getMillis(bool skipRecord = false);
void delayMillis(uint msecs);
void getTimeAndDate(TimeDate &t) const;
void fatalError();
@@ -94,9 +93,10 @@ private:
Common::SeekableReadStream *createConfigReadStream();
Common::WriteStream *createConfigWriteStream();
- BadaAppForm *_appForm;
+ TizenAppForm *_appForm;
AudioThread *_audioThread;
long long _epoch;
+ Common::String _resourcePath;
};
#endif
diff --git a/backends/platform/tizen/tizen.mk b/backends/platform/tizen/tizen.mk
new file mode 100644
index 0000000000..d8925b62dc
--- /dev/null
+++ b/backends/platform/tizen/tizen.mk
@@ -0,0 +1,7 @@
+# port files built under eclipse
+
+MODULE := backends/platform/tizen
+
+$(EXECUTABLE): $(OBJS)
+ rm -f $@
+ arm-linux-gnueabi-ar Tru $@ $(OBJS)
diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp
index 22a6495f8f..9d3a7473e3 100644
--- a/backends/platform/wii/osystem.cpp
+++ b/backends/platform/wii/osystem.cpp
@@ -203,7 +203,7 @@ bool OSystem_Wii::getFeatureState(Feature f) {
}
}
-uint32 OSystem_Wii::getMillis() {
+uint32 OSystem_Wii::getMillis(bool skipRecord) {
return ticks_to_millisecs(diff_ticks(_startup_time, gettime()));
}
diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h
index 5d6998d0b6..287c70ad6b 100644
--- a/backends/platform/wii/osystem.h
+++ b/backends/platform/wii/osystem.h
@@ -193,7 +193,7 @@ public:
const Graphics::PixelFormat *format);
virtual bool pollEvent(Common::Event &event);
- virtual uint32 getMillis();
+ virtual uint32 getMillis(bool skipRecord = false);
virtual void delayMillis(uint msecs);
virtual MutexRef createMutex();
diff --git a/backends/saves/recorder/recorder-saves.cpp b/backends/saves/recorder/recorder-saves.cpp
new file mode 100644
index 0000000000..49b4672913
--- /dev/null
+++ b/backends/saves/recorder/recorder-saves.cpp
@@ -0,0 +1,35 @@
+/* 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 "backends/saves/recorder/recorder-saves.h"
+#include "gui/EventRecorder.h"
+#include "common/savefile.h"
+
+Common::InSaveFile *RecorderSaveFileManager::openForLoading(const Common::String &filename) {
+ Common::InSaveFile *result = g_eventRec.processSaveStream(filename);
+ return result;
+}
+
+Common::StringArray RecorderSaveFileManager::listSaveFiles(const Common::String &pattern) {
+ return g_eventRec.listSaveFiles(pattern);
+}
+
diff --git a/backends/saves/recorder/recorder-saves.h b/backends/saves/recorder/recorder-saves.h
new file mode 100644
index 0000000000..692aeca329
--- /dev/null
+++ b/backends/saves/recorder/recorder-saves.h
@@ -0,0 +1,36 @@
+/* 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 BACKEND_SAVES_RECORDER_H
+#define BACKEND_SAVES_RECORDER_H
+
+#include "backends/saves/default/default-saves.h"
+
+/**
+ * Provides a savefile manager implementation for event recorder.
+ */
+class RecorderSaveFileManager : public DefaultSaveFileManager {
+ virtual Common::StringArray listSaveFiles(const Common::String &pattern);
+ virtual Common::InSaveFile *openForLoading(const Common::String &filename);
+};
+
+#endif
diff --git a/backends/timer/default/default-timer.cpp b/backends/timer/default/default-timer.cpp
index 9f56d58b12..ce93320f3d 100644
--- a/backends/timer/default/default-timer.cpp
+++ b/backends/timer/default/default-timer.cpp
@@ -80,7 +80,7 @@ DefaultTimerManager::~DefaultTimerManager() {
void DefaultTimerManager::handler() {
Common::StackLock lock(_mutex);
- const uint32 curTime = g_system->getMillis();
+ uint32 curTime = g_system->getMillis(true);
// Repeat as long as there is a TimerSlot that is scheduled to fire.
TimerSlot *slot = _head->next;
diff --git a/backends/timer/bada/timer.cpp b/backends/timer/tizen/timer.cpp
index e41ecd4864..fa226ce747 100644
--- a/backends/timer/bada/timer.cpp
+++ b/backends/timer/tizen/timer.cpp
@@ -20,15 +20,14 @@
*
*/
-#if defined(BADA)
+#if defined(TIZEN)
-#include "backends/timer/bada/timer.h"
+#include "backends/timer/tizen/timer.h"
//
-// TimerSlot
+// TimerSlot - an event driven thread
//
-TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback,
- uint32 interval, void *refCon) :
+TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback, uint32 interval, void *refCon) :
_timer(0),
_callback(callback),
_interval(interval),
@@ -36,16 +35,17 @@ TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback,
}
TimerSlot::~TimerSlot() {
+ delete _timer;
}
bool TimerSlot::OnStart() {
- _timer = new Osp::Base::Runtime::Timer();
+ _timer = new Tizen::Base::Runtime::Timer();
if (!_timer || IsFailed(_timer->Construct(*this))) {
AppLog("Failed to create timer");
return false;
}
- if (IsFailed(_timer->Start(_interval))) {
+ if (IsFailed(_timer->StartAsRepeatable(_interval))) {
AppLog("failed to start timer");
return false;
}
@@ -65,28 +65,28 @@ void TimerSlot::OnStop() {
void TimerSlot::OnTimerExpired(Timer &timer) {
_callback(_refCon);
- timer.Start(_interval);
}
//
-// BadaTimerManager
+// TizenTimerManager
//
-BadaTimerManager::BadaTimerManager() {
+TizenTimerManager::TizenTimerManager() {
}
-BadaTimerManager::~BadaTimerManager() {
- for (Common::List<TimerSlot>::iterator slot = _timers.begin();
- slot != _timers.end(); ) {
- slot->Stop();
- slot = _timers.erase(slot);
+TizenTimerManager::~TizenTimerManager() {
+ for (Common::List<TimerSlot *>::iterator it = _timers.begin(); it != _timers.end(); ) {
+ TimerSlot *slot = (*it);
+ slot->Quit();
+ slot->Join();
+ delete slot;
+ it = _timers.erase(it);
}
}
-bool BadaTimerManager::installTimerProc(TimerProc proc, int32 interval, void *refCon,
- const Common::String &id) {
+bool TizenTimerManager::installTimerProc(TimerProc proc, int32 interval, void *refCon, const Common::String &id) {
TimerSlot *slot = new TimerSlot(proc, interval / 1000, refCon);
- if (IsFailed(slot->Construct(THREAD_TYPE_EVENT_DRIVEN))) {
+ if (IsFailed(slot->Construct())) {
AppLog("Failed to create timer thread");
delete slot;
return false;
@@ -98,16 +98,18 @@ bool BadaTimerManager::installTimerProc(TimerProc proc, int32 interval, void *re
return false;
}
- _timers.push_back(*slot);
+ _timers.push_back(slot);
return true;
}
-void BadaTimerManager::removeTimerProc(TimerProc proc) {
- for (Common::List<TimerSlot>::iterator slot = _timers.begin();
- slot != _timers.end(); ++slot) {
+void TizenTimerManager::removeTimerProc(TimerProc proc) {
+ for (Common::List<TimerSlot *>::iterator it = _timers.begin(); it != _timers.end(); ++it) {
+ TimerSlot *slot = (*it);
if (slot->_callback == proc) {
- slot->Stop();
- slot = _timers.erase(slot);
+ slot->Quit();
+ slot->Join();
+ delete slot;
+ it = _timers.erase(it);
}
}
}
diff --git a/backends/timer/bada/timer.h b/backends/timer/tizen/timer.h
index 826064d7ff..4b2596401a 100644
--- a/backends/timer/bada/timer.h
+++ b/backends/timer/tizen/timer.h
@@ -20,20 +20,18 @@
*
*/
-#ifndef BADA_TIMER_H
-#define BADA_TIMER_H
+#ifndef TIZEN_TIMER_H
+#define TIZEN_TIMER_H
#include <FBase.h>
#include "common/timer.h"
#include "common/list.h"
-using namespace Osp::Base::Runtime;
+using namespace Tizen::Base::Runtime;
-struct TimerSlot: public ITimerEventListener, public Thread {
- TimerSlot(Common::TimerManager::TimerProc callback,
- uint32 interval,
- void *refCon);
+struct TimerSlot: public EventDrivenThread, public ITimerEventListener {
+ TimerSlot(Common::TimerManager::TimerProc callback, uint32 interval, void *refCon);
~TimerSlot();
bool OnStart(void);
@@ -46,17 +44,16 @@ struct TimerSlot: public ITimerEventListener, public Thread {
void *_refCon;
};
-class BadaTimerManager : public Common::TimerManager {
+class TizenTimerManager : public Common::TimerManager {
public:
- BadaTimerManager();
- ~BadaTimerManager();
+ TizenTimerManager();
+ ~TizenTimerManager();
- bool installTimerProc(TimerProc proc, int32 interval, void *refCon,
- const Common::String &id);
+ bool installTimerProc(TimerProc proc, int32 interval, void *refCon, const Common::String &id);
void removeTimerProc(TimerProc proc);
private:
- Common::List<TimerSlot> _timers;
+ Common::List<TimerSlot *> _timers;
};
#endif
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 42a3a64d34..a39c748adc 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -118,6 +118,13 @@ static const char HELP_STRING[] =
" --aspect-ratio Enable aspect ratio correction\n"
" --render-mode=MODE Enable additional render modes (cga, ega, hercGreen,\n"
" hercAmber, amiga)\n"
+#ifdef ENABLE_EVENTRECORDER
+ " --record-mode=MODE Specify record mode for event recorder (record, playback,\n"
+ " passthrough [default])\n"
+ " --record-file-name=FILE Specify record file name\n"
+ " --disable-display Disable any gfx output. Used for headless events\n"
+ " playback by Event Recorder\n"
+#endif
"\n"
#if defined(ENABLE_SKY) || defined(ENABLE_QUEEN)
" --alt-intro Use alternative intro for CD versions of Beneath a\n"
@@ -232,10 +239,9 @@ void registerDefaults() {
ConfMan.registerDefault("confirm_exit", false);
ConfMan.registerDefault("disable_sdl_parachute", false);
+ ConfMan.registerDefault("disable_display", false);
ConfMan.registerDefault("record_mode", "none");
ConfMan.registerDefault("record_file_name", "record.bin");
- ConfMan.registerDefault("record_temp_file_name", "record.tmp");
- ConfMan.registerDefault("record_time_file_name", "record.time");
ConfMan.registerDefault("gui_saveload_chooser", "grid");
ConfMan.registerDefault("gui_saveload_last_pos", "0");
@@ -424,6 +430,17 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
DO_OPTION_BOOL('f', "fullscreen")
END_OPTION
+#ifdef ENABLE_EVENTRECORDER
+ DO_LONG_OPTION_INT("disable-display")
+ END_OPTION
+
+ DO_LONG_OPTION("record-mode")
+ END_OPTION
+
+ DO_LONG_OPTION("record-file-name")
+ END_OPTION
+#endif
+
DO_LONG_OPTION("opl-driver")
END_OPTION
@@ -569,18 +586,6 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
END_OPTION
#endif
- DO_LONG_OPTION("record-mode")
- END_OPTION
-
- DO_LONG_OPTION("record-file-name")
- END_OPTION
-
- DO_LONG_OPTION("record-temp-file-name")
- END_OPTION
-
- DO_LONG_OPTION("record-time-file-name")
- END_OPTION
-
#ifdef IPHONE
// This is automatically set when launched from the Springboard.
DO_LONG_OPTION_OPT("launchedFromSB", 0)
diff --git a/base/main.cpp b/base/main.cpp
index 355a65f883..103d743bbc 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -42,8 +42,11 @@
#include "common/debug.h"
#include "common/debug-channels.h" /* for debug manager */
#include "common/events.h"
-#include "common/EventRecorder.h"
+#include "gui/EventRecorder.h"
#include "common/fs.h"
+#ifdef ENABLE_EVENTRECORDER
+#include "common/recorderfile.h"
+#endif
#include "common/system.h"
#include "common/textconsole.h"
#include "common/tokenizer.h"
@@ -409,7 +412,9 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
settings["gfx-mode"] = "default";
}
}
-
+ if (settings.contains("disable-display")) {
+ ConfMan.setInt("disable-display", 1, Common::ConfigManager::kTransientDomain);
+ }
setupGraphics(system);
// Init the different managers that are used by the engines.
@@ -422,13 +427,15 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
// take place after the backend is initiated and the screen has been setup
system.getEventManager()->init();
+#ifdef ENABLE_EVENTRECORDER
// Directly after initializing the event manager, we will initialize our
// event recorder.
//
// TODO: This is just to match the current behavior, when we further extend
// our event recorder, we might do this at another place. Or even change
// the whole API for that ;-).
- g_eventRec.init();
+ g_eventRec.RegisterEventSource();
+#endif
// Now as the event manager is created, setup the keymapper
setupKeymapper(system);
@@ -448,12 +455,29 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
// to save memory
PluginManager::instance().unloadPluginsExcept(PLUGIN_TYPE_ENGINE, plugin);
+#ifdef ENABLE_EVENTRECORDER
+ Common::String recordMode = ConfMan.get("record_mode");
+ Common::String recordFileName = ConfMan.get("record_file_name");
+
+ if (recordMode == "record") {
+ g_eventRec.init(g_eventRec.generateRecordFileName(ConfMan.getActiveDomainName()), GUI::EventRecorder::kRecorderRecord);
+ } else if (recordMode == "playback") {
+ g_eventRec.init(recordFileName, GUI::EventRecorder::kRecorderPlayback);
+ } else if ((recordMode == "info") && (!recordFileName.empty())) {
+ Common::PlaybackFile record;
+ record.openRead(recordFileName);
+ debug("info:author=%s name=%s description=%s", record.getHeader().author.c_str(), record.getHeader().name.c_str(), record.getHeader().description.c_str());
+ break;
+ }
+#endif
// Try to run the game
Common::Error result = runGame(plugin, system, specialDebug);
+#ifdef ENABLE_EVENTRECORDER
// Flush Event recorder file. The recorder does not get reinitialized for next game
// which is intentional. Only single game per session is allowed.
g_eventRec.deinit();
+#endif
#if defined(UNCACHED_PLUGINS) && defined(DYNAMIC_MODULES)
// do our best to prevent fragmentation by unloading as soon as we can
@@ -478,6 +502,11 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
#ifdef FORCE_RTL
g_system->getEventManager()->resetQuit();
#endif
+ #ifdef ENABLE_EVENTRECORDER
+ if (g_eventRec.checkForContinueGame()) {
+ continue;
+ }
+ #endif
// Discard any command line options. It's unlikely that the user
// wanted to apply them to *all* games ever launched.
@@ -501,7 +530,9 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
GUI::GuiManager::destroy();
Common::ConfigManager::destroy();
Common::DebugManager::destroy();
- Common::EventRecorder::destroy();
+#ifdef ENABLE_EVENTRECORDER
+ GUI::EventRecorder::destroy();
+#endif
Common::SearchManager::destroy();
#ifdef USE_TRANSLATION
Common::TranslationManager::destroy();
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp
index 012a2dfce5..e60c1aa7ff 100644
--- a/common/EventDispatcher.cpp
+++ b/common/EventDispatcher.cpp
@@ -24,7 +24,7 @@
namespace Common {
-EventDispatcher::EventDispatcher() : _mapper(0) {
+EventDispatcher::EventDispatcher() : _autoFreeMapper(false), _mapper(0) {
}
EventDispatcher::~EventDispatcher() {
@@ -38,7 +38,9 @@ EventDispatcher::~EventDispatcher() {
delete i->observer;
}
- delete _mapper;
+ if (_autoFreeMapper) {
+ delete _mapper;
+ }
_mapper = 0;
}
@@ -68,11 +70,15 @@ void EventDispatcher::dispatch() {
}
}
-void EventDispatcher::registerMapper(EventMapper *mapper) {
- delete _mapper;
+void EventDispatcher::registerMapper(EventMapper *mapper, bool autoFree) {
+ if (_autoFreeMapper) {
+ delete _mapper;
+ }
_mapper = mapper;
+ _autoFreeMapper = autoFree;
}
+
void EventDispatcher::registerSource(EventSource *source, bool autoFree) {
SourceEntry newEntry;
diff --git a/common/EventRecorder.cpp b/common/EventRecorder.cpp
deleted file mode 100644
index 5e24f128c3..0000000000
--- a/common/EventRecorder.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/EventRecorder.h"
-
-#include "common/bufferedstream.h"
-#include "common/config-manager.h"
-#include "common/random.h"
-#include "common/savefile.h"
-#include "common/textconsole.h"
-
-namespace Common {
-
-DECLARE_SINGLETON(EventRecorder);
-
-#define RECORD_SIGNATURE 0x54455354
-#define RECORD_VERSION 1
-
-uint32 readTime(ReadStream *inFile) {
- uint32 d = inFile->readByte();
- if (d == 0xff) {
- d = inFile->readUint32LE();
- }
-
- return d;
-}
-
-void writeTime(WriteStream *outFile, uint32 d) {
- //Simple RLE compression
- if (d >= 0xff) {
- outFile->writeByte(0xff);
- outFile->writeUint32LE(d);
- } else {
- outFile->writeByte(d);
- }
-}
-
-void readRecord(SeekableReadStream *inFile, uint32 &diff, Event &event, uint32 &millis) {
- millis = readTime(inFile);
-
- diff = inFile->readUint32LE();
-
- event.type = (EventType)inFile->readUint32LE();
-
- switch (event.type) {
- case EVENT_KEYDOWN:
- case EVENT_KEYUP:
- event.kbd.keycode = (KeyCode)inFile->readSint32LE();
- event.kbd.ascii = inFile->readUint16LE();
- event.kbd.flags = inFile->readByte();
- break;
- case EVENT_MOUSEMOVE:
- case EVENT_LBUTTONDOWN:
- case EVENT_LBUTTONUP:
- case EVENT_RBUTTONDOWN:
- case EVENT_RBUTTONUP:
- case EVENT_WHEELUP:
- case EVENT_WHEELDOWN:
- case EVENT_MBUTTONDOWN:
- case EVENT_MBUTTONUP:
- event.mouse.x = inFile->readSint16LE();
- event.mouse.y = inFile->readSint16LE();
- break;
- default:
- break;
- }
-}
-
-void writeRecord(WriteStream *outFile, uint32 diff, const Event &event, uint32 millis) {
- writeTime(outFile, millis);
-
- outFile->writeUint32LE(diff);
-
- outFile->writeUint32LE((uint32)event.type);
-
- switch (event.type) {
- case EVENT_KEYDOWN:
- case EVENT_KEYUP:
- outFile->writeSint32LE(event.kbd.keycode);
- outFile->writeUint16LE(event.kbd.ascii);
- outFile->writeByte(event.kbd.flags);
- break;
- case EVENT_MOUSEMOVE:
- case EVENT_LBUTTONDOWN:
- case EVENT_LBUTTONUP:
- case EVENT_RBUTTONDOWN:
- case EVENT_RBUTTONUP:
- case EVENT_WHEELUP:
- case EVENT_WHEELDOWN:
- case EVENT_MBUTTONDOWN:
- case EVENT_MBUTTONUP:
- outFile->writeSint16LE(event.mouse.x);
- outFile->writeSint16LE(event.mouse.y);
- break;
- default:
- break;
- }
-}
-
-EventRecorder::EventRecorder() {
- _recordFile = NULL;
- _recordTimeFile = NULL;
- _playbackFile = NULL;
- _playbackTimeFile = NULL;
- _timeMutex = g_system->createMutex();
- _recorderMutex = g_system->createMutex();
-
- _eventCount = 0;
- _lastEventCount = 0;
- _lastMillis = 0;
- _lastEventMillis = 0;
-
- _recordMode = kPassthrough;
-}
-
-EventRecorder::~EventRecorder() {
- deinit();
-
- g_system->deleteMutex(_timeMutex);
- g_system->deleteMutex(_recorderMutex);
-}
-
-void EventRecorder::init() {
- String recordModeString = ConfMan.get("record_mode");
- if (recordModeString.compareToIgnoreCase("record") == 0) {
- _recordMode = kRecorderRecord;
-
- debug(3, "EventRecorder: record");
- } else {
- if (recordModeString.compareToIgnoreCase("playback") == 0) {
- _recordMode = kRecorderPlayback;
- debug(3, "EventRecorder: playback");
- } else {
- _recordMode = kPassthrough;
- debug(3, "EventRecorder: passthrough");
- }
- }
-
- _recordFileName = ConfMan.get("record_file_name");
- if (_recordFileName.empty()) {
- _recordFileName = "record.bin";
- }
- _recordTempFileName = ConfMan.get("record_temp_file_name");
- if (_recordTempFileName.empty()) {
- _recordTempFileName = "record.tmp";
- }
- _recordTimeFileName = ConfMan.get("record_time_file_name");
- if (_recordTimeFileName.empty()) {
- _recordTimeFileName = "record.time";
- }
-
- // recorder stuff
- if (_recordMode == kRecorderRecord) {
- _recordCount = 0;
- _recordTimeCount = 0;
- _recordFile = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(_recordTempFileName), 128 * 1024);
- _recordTimeFile = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(_recordTimeFileName), 128 * 1024);
- _recordSubtitles = ConfMan.getBool("subtitles");
- }
-
- uint32 sign;
- uint32 randomSourceCount;
- if (_recordMode == kRecorderPlayback) {
- _playbackCount = 0;
- _playbackTimeCount = 0;
- _playbackFile = wrapBufferedSeekableReadStream(g_system->getSavefileManager()->openForLoading(_recordFileName), 128 * 1024, DisposeAfterUse::YES);
- _playbackTimeFile = wrapBufferedSeekableReadStream(g_system->getSavefileManager()->openForLoading(_recordTimeFileName), 128 * 1024, DisposeAfterUse::YES);
-
- if (!_playbackFile) {
- warning("Cannot open playback file %s. Playback was switched off", _recordFileName.c_str());
- _recordMode = kPassthrough;
- }
-
- if (!_playbackTimeFile) {
- warning("Cannot open playback time file %s. Playback was switched off", _recordTimeFileName.c_str());
- _recordMode = kPassthrough;
- }
- }
-
- if (_recordMode == kRecorderPlayback) {
- sign = _playbackFile->readUint32LE();
- if (sign != RECORD_SIGNATURE) {
- error("Unknown record file signature");
- }
-
- _playbackFile->readUint32LE(); // version
-
- // conf vars
- ConfMan.setBool("subtitles", _playbackFile->readByte() != 0);
-
- _recordCount = _playbackFile->readUint32LE();
- _recordTimeCount = _playbackFile->readUint32LE();
-
- randomSourceCount = _playbackFile->readUint32LE();
- for (uint i = 0; i < randomSourceCount; ++i) {
- RandomSourceRecord rec;
- rec.name = "";
- uint32 sLen = _playbackFile->readUint32LE();
- for (uint j = 0; j < sLen; ++j) {
- char c = _playbackFile->readSByte();
- rec.name += c;
- }
- rec.seed = _playbackFile->readUint32LE();
- _randomSourceRecords.push_back(rec);
- }
-
- _hasPlaybackEvent = false;
- }
-
- g_system->getEventManager()->getEventDispatcher()->registerSource(this, false);
- g_system->getEventManager()->getEventDispatcher()->registerObserver(this, EventManager::kEventRecorderPriority, false, true);
-}
-
-void EventRecorder::deinit() {
- debug(3, "EventRecorder: deinit");
-
- g_system->getEventManager()->getEventDispatcher()->unregisterSource(this);
- g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
-
- g_system->lockMutex(_timeMutex);
- g_system->lockMutex(_recorderMutex);
- _recordMode = kPassthrough;
- g_system->unlockMutex(_timeMutex);
- g_system->unlockMutex(_recorderMutex);
-
- delete _playbackFile;
- delete _playbackTimeFile;
-
- if (_recordFile != NULL) {
- _recordFile->finalize();
- delete _recordFile;
- _recordTimeFile->finalize();
- delete _recordTimeFile;
-
- _playbackFile = g_system->getSavefileManager()->openForLoading(_recordTempFileName);
-
- assert(_playbackFile);
-
- _recordFile = g_system->getSavefileManager()->openForSaving(_recordFileName);
- _recordFile->writeUint32LE(RECORD_SIGNATURE);
- _recordFile->writeUint32LE(RECORD_VERSION);
-
- // conf vars
- _recordFile->writeByte(_recordSubtitles ? 1 : 0);
-
- _recordFile->writeUint32LE(_recordCount);
- _recordFile->writeUint32LE(_recordTimeCount);
-
- _recordFile->writeUint32LE(_randomSourceRecords.size());
- for (uint i = 0; i < _randomSourceRecords.size(); ++i) {
- _recordFile->writeUint32LE(_randomSourceRecords[i].name.size());
- _recordFile->writeString(_randomSourceRecords[i].name);
- _recordFile->writeUint32LE(_randomSourceRecords[i].seed);
- }
-
- for (uint i = 0; i < _recordCount; ++i) {
- uint32 tempDiff;
- Event tempEvent;
- uint32 millis;
- readRecord(_playbackFile, tempDiff, tempEvent, millis);
- writeRecord(_recordFile, tempDiff, tempEvent, millis);
- }
-
- _recordFile->finalize();
- delete _recordFile;
- delete _playbackFile;
-
- //TODO: remove recordTempFileName'ed file
- }
-}
-
-void EventRecorder::registerRandomSource(RandomSource &rnd, const String &name) {
- if (_recordMode == kRecorderRecord) {
- RandomSourceRecord rec;
- rec.name = name;
- rec.seed = rnd.getSeed();
- _randomSourceRecords.push_back(rec);
- }
-
- if (_recordMode == kRecorderPlayback) {
- for (uint i = 0; i < _randomSourceRecords.size(); ++i) {
- if (_randomSourceRecords[i].name == name) {
- rnd.setSeed(_randomSourceRecords[i].seed);
- _randomSourceRecords.remove_at(i);
- break;
- }
- }
- }
-}
-
-void EventRecorder::processMillis(uint32 &millis) {
- uint32 d;
- if (_recordMode == kPassthrough) {
- return;
- }
-
- g_system->lockMutex(_timeMutex);
- if (_recordMode == kRecorderRecord) {
- d = millis - _lastMillis;
- writeTime(_recordTimeFile, d);
-
- _recordTimeCount++;
- }
-
- if (_recordMode == kRecorderPlayback) {
- if (_recordTimeCount > _playbackTimeCount) {
- d = readTime(_playbackTimeFile);
-
- while ((_lastMillis + d > millis) && (_lastMillis + d - millis > 50)) {
- _recordMode = kPassthrough;
- g_system->delayMillis(50);
- millis = g_system->getMillis();
- _recordMode = kRecorderPlayback;
- }
-
- millis = _lastMillis + d;
- _playbackTimeCount++;
- }
- }
-
- _lastMillis = millis;
- g_system->unlockMutex(_timeMutex);
-}
-
-bool EventRecorder::processDelayMillis(uint &msecs) {
- if (_recordMode == kRecorderPlayback) {
- _recordMode = kPassthrough;
-
- uint32 millis = g_system->getMillis();
-
- _recordMode = kRecorderPlayback;
-
- if (_lastMillis > millis) {
- // Skip delay if we're getting late
- return true;
- }
- }
-
- return false;
-}
-
-bool EventRecorder::notifyEvent(const Event &ev) {
- if (_recordMode != kRecorderRecord)
- return false;
-
- StackLock lock(_recorderMutex);
- ++_eventCount;
-
- writeRecord(_recordFile, _eventCount - _lastEventCount, ev, _lastMillis - _lastEventMillis);
-
- _recordCount++;
- _lastEventCount = _eventCount;
- _lastEventMillis = _lastMillis;
-
- return false;
-}
-
-bool EventRecorder::notifyPoll() {
- if (_recordMode != kRecorderRecord)
- return false;
-
- ++_eventCount;
-
- return false;
-}
-
-bool EventRecorder::pollEvent(Event &ev) {
- uint32 millis;
-
- if (_recordMode != kRecorderPlayback)
- return false;
-
- StackLock lock(_recorderMutex);
- ++_eventCount;
-
- if (!_hasPlaybackEvent) {
- if (_recordCount > _playbackCount) {
- readRecord(_playbackFile, const_cast<uint32&>(_playbackDiff), _playbackEvent, millis);
- _playbackCount++;
- _hasPlaybackEvent = true;
- }
- }
-
- if (_hasPlaybackEvent) {
- if (_playbackDiff <= (_eventCount - _lastEventCount)) {
- switch (_playbackEvent.type) {
- case EVENT_MOUSEMOVE:
- case EVENT_LBUTTONDOWN:
- case EVENT_LBUTTONUP:
- case EVENT_RBUTTONDOWN:
- case EVENT_RBUTTONUP:
- case EVENT_WHEELUP:
- case EVENT_WHEELDOWN:
- g_system->warpMouse(_playbackEvent.mouse.x, _playbackEvent.mouse.y);
- break;
- default:
- break;
- }
- ev = _playbackEvent;
- _hasPlaybackEvent = false;
- _lastEventCount = _eventCount;
- return true;
- }
- }
-
- return false;
-}
-
-} // End of namespace Common
diff --git a/common/EventRecorder.h b/common/EventRecorder.h
deleted file mode 100644
index 43a08b08cd..0000000000
--- a/common/EventRecorder.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef COMMON_EVENTRECORDER_H
-#define COMMON_EVENTRECORDER_H
-
-#include "common/scummsys.h"
-#include "common/events.h"
-#include "common/singleton.h"
-#include "common/mutex.h"
-#include "common/array.h"
-
-#define g_eventRec (Common::EventRecorder::instance())
-
-namespace Common {
-
-class RandomSource;
-class SeekableReadStream;
-class WriteStream;
-
-/**
- * Our generic event recorder.
- *
- * TODO: Add more documentation.
- */
-class EventRecorder : private EventSource, private EventObserver, public Singleton<EventRecorder> {
- friend class Singleton<SingletonBaseType>;
- EventRecorder();
- ~EventRecorder();
-public:
- void init();
- void deinit();
-
- /** Register random source so it can be serialized in game test purposes */
- void registerRandomSource(RandomSource &rnd, const String &name);
-
- /** TODO: Add documentation, this is only used by the backend */
- void processMillis(uint32 &millis);
-
- /** TODO: Add documentation, this is only used by the backend */
- bool processDelayMillis(uint &msecs);
-
-private:
- bool notifyEvent(const Event &ev);
- bool notifyPoll();
- bool pollEvent(Event &ev);
- bool allowMapping() const { return false; }
-
- class RandomSourceRecord {
- public:
- String name;
- uint32 seed;
- };
- Array<RandomSourceRecord> _randomSourceRecords;
-
- bool _recordSubtitles;
- volatile uint32 _recordCount;
- volatile uint32 _lastRecordEvent;
- volatile uint32 _recordTimeCount;
- volatile uint32 _lastEventMillis;
- WriteStream *_recordFile;
- WriteStream *_recordTimeFile;
- MutexRef _timeMutex;
- MutexRef _recorderMutex;
- volatile uint32 _lastMillis;
-
- volatile uint32 _playbackCount;
- volatile uint32 _playbackDiff;
- volatile bool _hasPlaybackEvent;
- volatile uint32 _playbackTimeCount;
- Event _playbackEvent;
- SeekableReadStream *_playbackFile;
- SeekableReadStream *_playbackTimeFile;
-
- volatile uint32 _eventCount;
- volatile uint32 _lastEventCount;
-
- enum RecordMode {
- kPassthrough = 0,
- kRecorderRecord = 1,
- kRecorderPlayback = 2
- };
- volatile RecordMode _recordMode;
- String _recordFileName;
- String _recordTempFileName;
- String _recordTimeFileName;
-};
-
-} // End of namespace Common
-
-#endif
diff --git a/common/debug.h b/common/debug.h
index dc94839082..859f3c41b3 100644
--- a/common/debug.h
+++ b/common/debug.h
@@ -117,5 +117,9 @@ void debugCN(uint32 debugChannels, const char *s, ...) GCC_PRINTF(2, 3);
*/
extern int gDebugLevel;
+//Global constant for EventRecorder debug channel
+enum GlobalDebugLevels {
+ kDebugLevelEventRec = 1 << 30
+};
#endif
diff --git a/common/events.h b/common/events.h
index 7366c51d36..9029a4096a 100644
--- a/common/events.h
+++ b/common/events.h
@@ -288,11 +288,14 @@ public:
* to the EventDispatcher, thus it will be deleted
* with "delete", when EventDispatcher is destroyed.
*
- * Note there is only one mapper per EventDispatcher
- * possible, thus when this method is called twice,
- * the former mapper will be destroied.
+ * @param autoFree Destroy previous mapper [default]
+ * Normally we allow only one event mapper to exists,
+ * However Event Recorder must intervent into normal
+ * event flow without altering its semantics. Thus during
+ * Event Recorder playback and recording we allow
+ * two mappers.
*/
- void registerMapper(EventMapper *mapper);
+ void registerMapper(EventMapper *mapper, bool autoFree = true);
/**
* Queries the setup event mapper.
@@ -326,6 +329,7 @@ public:
*/
void unregisterObserver(EventObserver *obs);
private:
+ bool _autoFreeMapper;
EventMapper *_mapper;
struct Entry {
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 00562f746a..ba44caafd9 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -102,18 +102,18 @@ String MacResManager::computeResForkMD5AsString(uint32 length) const {
return computeStreamMD5AsString(resForkStream, MIN<uint32>(length, _resForkSize));
}
-bool MacResManager::open(String filename) {
+bool MacResManager::open(const String &fileName) {
close();
#ifdef MACOSX
// Check the actual fork on a Mac computer
- String fullPath = ConfMan.get("path") + "/" + filename + "/..namedfork/rsrc";
+ String fullPath = ConfMan.get("path") + "/" + fileName + "/..namedfork/rsrc";
FSNode resFsNode = FSNode(fullPath);
if (resFsNode.exists()) {
SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();
if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
- _baseFileName = filename;
+ _baseFileName = fileName;
return true;
}
@@ -123,38 +123,39 @@ bool MacResManager::open(String filename) {
File *file = new File();
- // First, let's try to see if the Mac converted name exists
- if (file->open(constructAppleDoubleName(filename)) && loadFromAppleDouble(*file)) {
- _baseFileName = filename;
+ // Prefer standalone files first, starting with raw forks
+ if (file->open(fileName + ".rsrc") && loadFromRawFork(*file)) {
+ _baseFileName = fileName;
return true;
}
file->close();
- // Check .bin too
- if (file->open(filename + ".bin") && loadFromMacBinary(*file)) {
- _baseFileName = filename;
+ // Then try for AppleDouble using Apple's naming
+ if (file->open(constructAppleDoubleName(fileName)) && loadFromAppleDouble(*file)) {
+ _baseFileName = fileName;
return true;
}
file->close();
- // Maybe we have a dumped fork?
- if (file->open(filename + ".rsrc") && loadFromRawFork(*file)) {
- _baseFileName = filename;
+ // Check .bin for MacBinary next
+ if (file->open(fileName + ".bin") && loadFromMacBinary(*file)) {
+ _baseFileName = fileName;
return true;
}
file->close();
- // Fine, what about just the data fork?
- if (file->open(filename)) {
- _baseFileName = filename;
+ // As a last resort, see if just the data fork exists
+ if (file->open(fileName)) {
+ _baseFileName = fileName;
+ // FIXME: Is this really needed?
if (isMacBinary(*file)) {
- file->seek(0, SEEK_SET);
+ file->seek(0);
if (loadFromMacBinary(*file))
return true;
}
- file->seek(0, SEEK_SET);
+ file->seek(0);
_stream = file;
return true;
}
@@ -165,18 +166,18 @@ bool MacResManager::open(String filename) {
return false;
}
-bool MacResManager::open(FSNode path, String filename) {
+bool MacResManager::open(const FSNode &path, const String &fileName) {
close();
#ifdef MACOSX
// Check the actual fork on a Mac computer
- String fullPath = path.getPath() + "/" + filename + "/..namedfork/rsrc";
+ String fullPath = path.getPath() + "/" + fileName + "/..namedfork/rsrc";
FSNode resFsNode = FSNode(fullPath);
if (resFsNode.exists()) {
SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();
if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) {
- _baseFileName = filename;
+ _baseFileName = fileName;
return true;
}
@@ -184,52 +185,53 @@ bool MacResManager::open(FSNode path, String filename) {
}
#endif
- // First, let's try to see if the Mac converted name exists
- FSNode fsNode = path.getChild(constructAppleDoubleName(filename));
+ // Prefer standalone files first, starting with raw forks
+ FSNode fsNode = path.getChild(fileName + ".rsrc");
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
- if (loadFromAppleDouble(*stream)) {
- _baseFileName = filename;
+ if (loadFromRawFork(*stream)) {
+ _baseFileName = fileName;
return true;
}
delete stream;
}
- // Check .bin too
- fsNode = path.getChild(filename + ".bin");
+ // Then try for AppleDouble using Apple's naming
+ fsNode = path.getChild(constructAppleDoubleName(fileName));
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
- if (loadFromMacBinary(*stream)) {
- _baseFileName = filename;
+ if (loadFromAppleDouble(*stream)) {
+ _baseFileName = fileName;
return true;
}
delete stream;
}
- // Maybe we have a dumped fork?
- fsNode = path.getChild(filename + ".rsrc");
+ // Check .bin for MacBinary next
+ fsNode = path.getChild(fileName + ".bin");
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
- if (loadFromRawFork(*stream)) {
- _baseFileName = filename;
+ if (loadFromMacBinary(*stream)) {
+ _baseFileName = fileName;
return true;
}
delete stream;
}
- // Fine, what about just the data fork?
- fsNode = path.getChild(filename);
+ // As a last resort, see if just the data fork exists
+ fsNode = path.getChild(fileName);
if (fsNode.exists() && !fsNode.isDirectory()) {
SeekableReadStream *stream = fsNode.createReadStream();
- _baseFileName = filename;
+ _baseFileName = fileName;
+ // FIXME: Is this really needed?
if (isMacBinary(*stream)) {
- stream->seek(0, SEEK_SET);
+ stream->seek(0);
if (loadFromMacBinary(*stream))
return true;
}
- stream->seek(0, SEEK_SET);
+ stream->seek(0);
_stream = stream;
return true;
}
@@ -238,22 +240,22 @@ bool MacResManager::open(FSNode path, String filename) {
return false;
}
-bool MacResManager::exists(const String &filename) {
+bool MacResManager::exists(const String &fileName) {
// Try the file name by itself
- if (Common::File::exists(filename))
+ if (File::exists(fileName))
return true;
// Try the .rsrc extension
- if (Common::File::exists(filename + ".rsrc"))
+ if (File::exists(fileName + ".rsrc"))
return true;
// Check if we have a MacBinary file
- Common::File tempFile;
- if (tempFile.open(filename + ".bin") && isMacBinary(tempFile))
+ File tempFile;
+ if (tempFile.open(fileName + ".bin") && isMacBinary(tempFile))
return true;
// Check if we have an AppleDouble file
- if (tempFile.open(constructAppleDoubleName(filename)) && tempFile.readUint32BE() == 0x00051607)
+ if (tempFile.open(constructAppleDoubleName(fileName)) && tempFile.readUint32BE() == 0x00051607)
return true;
return false;
@@ -480,10 +482,10 @@ SeekableReadStream *MacResManager::getResource(uint32 typeID, uint16 resID) {
return _stream->readStream(len);
}
-SeekableReadStream *MacResManager::getResource(const String &filename) {
+SeekableReadStream *MacResManager::getResource(const String &fileName) {
for (uint32 i = 0; i < _resMap.numTypes; i++) {
for (uint32 j = 0; j < _resTypes[i].items; j++) {
- if (_resLists[i][j].nameOffset != -1 && filename.equalsIgnoreCase(_resLists[i][j].name)) {
+ if (_resLists[i][j].nameOffset != -1 && fileName.equalsIgnoreCase(_resLists[i][j].name)) {
_stream->seek(_dataOffset + _resLists[i][j].dataOffset);
uint32 len = _stream->readUint32BE();
@@ -499,13 +501,13 @@ SeekableReadStream *MacResManager::getResource(const String &filename) {
return 0;
}
-SeekableReadStream *MacResManager::getResource(uint32 typeID, const String &filename) {
+SeekableReadStream *MacResManager::getResource(uint32 typeID, const String &fileName) {
for (uint32 i = 0; i < _resMap.numTypes; i++) {
if (_resTypes[i].id != typeID)
continue;
for (uint32 j = 0; j < _resTypes[i].items; j++) {
- if (_resLists[i][j].nameOffset != -1 && filename.equalsIgnoreCase(_resLists[i][j].name)) {
+ if (_resLists[i][j].nameOffset != -1 && fileName.equalsIgnoreCase(_resLists[i][j].name)) {
_stream->seek(_dataOffset + _resLists[i][j].dataOffset);
uint32 len = _stream->readUint32BE();
@@ -574,7 +576,7 @@ void MacResManager::readMap() {
}
}
-Common::String MacResManager::constructAppleDoubleName(Common::String name) {
+String MacResManager::constructAppleDoubleName(String name) {
// Insert "._" before the last portion of a path name
for (int i = name.size() - 1; i >= 0; i--) {
if (i == 0) {
diff --git a/common/macresman.h b/common/macresman.h
index ed74da9cc6..cca6592f21 100644
--- a/common/macresman.h
+++ b/common/macresman.h
@@ -54,27 +54,32 @@ public:
/**
* Open a Mac data/resource fork pair.
+ *
+ * This uses SearchMan to find the data/resource forks. This should only be used
+ * from inside an engine.
+ *
* @param filename The base file name of the file
* @note This will check for the raw resource fork, MacBinary, and AppleDouble formats.
* @return True on success
*/
- bool open(String filename);
+ bool open(const String &fileName);
/**
* Open a Mac data/resource fork pair.
+ *
* @param path The path that holds the forks
* @param filename The base file name of the file
* @note This will check for the raw resource fork, MacBinary, and AppleDouble formats.
* @return True on success
*/
- bool open(FSNode path, String filename);
+ bool open(const FSNode &path, const String &fileName);
/**
* See if a Mac data/resource fork pair exists.
* @param filename The base file name of the file
* @return True if either a data fork or resource fork with this name exists
*/
- static bool exists(const String &filename);
+ static bool exists(const String &fileName);
/**
* Close the Mac data/resource fork pair.
@@ -94,12 +99,6 @@ public:
bool hasResFork() const;
/**
- * Check if the given stream is in the MacBinary format.
- * @param stream The stream we're checking
- */
- static bool isMacBinary(SeekableReadStream &stream);
-
- /**
* Read resource from the MacBinary file
* @param typeID FourCC of the type
* @param resID Resource ID to fetch
@@ -176,7 +175,13 @@ private:
bool loadFromMacBinary(SeekableReadStream &stream);
bool loadFromAppleDouble(SeekableReadStream &stream);
- static Common::String constructAppleDoubleName(Common::String name);
+ static String constructAppleDoubleName(String name);
+
+ /**
+ * Check if the given stream is in the MacBinary format.
+ * @param stream The stream we're checking
+ */
+ static bool isMacBinary(SeekableReadStream &stream);
enum {
kResForkNone = 0,
diff --git a/common/memstream.h b/common/memstream.h
index 260fb64d84..7fa6500753 100644
--- a/common/memstream.h
+++ b/common/memstream.h
@@ -89,8 +89,9 @@ public:
*/
class MemoryWriteStream : public WriteStream {
private:
- byte *_ptr;
const uint32 _bufSize;
+protected:
+ byte *_ptr;
uint32 _pos;
bool _err;
public:
@@ -117,6 +118,40 @@ public:
};
/**
+ * MemoryWriteStream subclass with ability to set stream position indicator.
+ */
+class SeekableMemoryWriteStream : public MemoryWriteStream {
+private:
+ byte *_ptrOrig;
+public:
+ SeekableMemoryWriteStream(byte *buf, uint32 len) : MemoryWriteStream(buf, len), _ptrOrig(buf) {}
+ uint32 seek(uint32 offset, int whence = SEEK_SET) {
+ switch (whence) {
+ case SEEK_END:
+ // SEEK_END works just like SEEK_SET, only 'reversed',
+ // i.e. from the end.
+ offset = size() + offset;
+ // Fall through
+ case SEEK_SET:
+ _ptr = _ptrOrig + offset;
+ _pos = offset;
+ break;
+ case SEEK_CUR:
+ _ptr += offset;
+ _pos += offset;
+ break;
+ }
+ // Post-Condition
+ if (_pos > size()) {
+ _pos = size();
+ _ptr = _ptrOrig + _pos;
+ }
+ return _pos;
+ }
+};
+
+
+/**
* A sort of hybrid between MemoryWriteStream and Array classes. A stream
* that grows as it's written to.
*/
diff --git a/common/module.mk b/common/module.mk
index d96b11ee40..9f9126c8ef 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -10,7 +10,6 @@ MODULE_OBJS := \
error.o \
EventDispatcher.o \
EventMapper.o \
- EventRecorder.o \
file.o \
fs.o \
gui_options.o \
@@ -51,5 +50,10 @@ MODULE_OBJS += \
rdft.o \
sinetables.o
+ifdef ENABLE_EVENTRECORDER
+MODULE_OBJS += \
+ recorderfile.o
+endif
+
# Include common rules
include $(srcdir)/rules.mk
diff --git a/common/random.cpp b/common/random.cpp
index fd75534c44..de1269b485 100644
--- a/common/random.cpp
+++ b/common/random.cpp
@@ -21,7 +21,7 @@
#include "common/random.h"
#include "common/system.h"
-#include "common/EventRecorder.h"
+#include "gui/EventRecorder.h"
namespace Common {
@@ -30,13 +30,12 @@ RandomSource::RandomSource(const String &name) {
// Use system time as RNG seed. Normally not a good idea, if you are using
// a RNG for security purposes, but good enough for our purposes.
assert(g_system);
- uint32 seed = g_system->getMillis();
- setSeed(seed);
- // Register this random source with the event recorder. This may end
- // up querying or resetting the current seed, so we must call it
- // *after* the initial seed has been set.
- g_eventRec.registerRandomSource(*this, name);
+#ifdef ENABLE_EVENTRECORDER
+ setSeed(g_eventRec.getRandomSeed(name));
+#else
+ setSeed(g_system->getMillis());
+#endif
}
void RandomSource::setSeed(uint32 seed) {
diff --git a/common/recorderfile.cpp b/common/recorderfile.cpp
new file mode 100644
index 0000000000..d08bc599f1
--- /dev/null
+++ b/common/recorderfile.cpp
@@ -0,0 +1,714 @@
+/* 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 "gui/EventRecorder.h"
+#include "common/md5.h"
+#include "common/recorderfile.h"
+#include "common/savefile.h"
+#include "common/bufferedstream.h"
+#include "graphics/thumbnail.h"
+#include "graphics/surface.h"
+#include "graphics/scaler.h"
+
+#define RECORD_VERSION 1
+
+namespace Common {
+
+PlaybackFile::PlaybackFile() : _tmpRecordFile(_tmpBuffer, kRecordBuffSize), _tmpPlaybackFile(_tmpBuffer, kRecordBuffSize) {
+ _readStream = NULL;
+ _writeStream = NULL;
+ _screenshotsFile = NULL;
+ _mode = kClosed;
+
+ _recordFile = 0;
+ _headerDumped = false;
+ _recordCount = 0;
+ _eventsSize = 0;
+ memset(_tmpBuffer, 1, kRecordBuffSize);
+}
+
+PlaybackFile::~PlaybackFile() {
+ close();
+}
+
+bool PlaybackFile::openWrite(const String &fileName) {
+ close();
+ _header.fileName = fileName;
+ _writeStream = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(fileName), 128 * 1024);
+ _headerDumped = false;
+ _recordCount = 0;
+ if (_writeStream == NULL) {
+ return false;
+ }
+ _mode = kWrite;
+ return true;
+}
+
+bool PlaybackFile::openRead(const String &fileName) {
+ close();
+ _header.fileName = fileName;
+ _eventsSize = 0;
+ _tmpPlaybackFile.seek(0);
+ _readStream = wrapBufferedSeekableReadStream(g_system->getSavefileManager()->openForLoading(fileName), 128 * 1024, DisposeAfterUse::YES);
+ if (_readStream == NULL) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load File\" result=fail reason=\"file %s not found\"", fileName.c_str());
+ return false;
+ }
+ if (!parseHeader()) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load File\" result=fail reason=\"header parsing failed\"");
+ return false;
+ }
+ _screenshotsFile = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving("screenshots.bin"), 128 * 1024);
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load File\" result=success");
+ _mode = kRead;
+ return true;
+}
+
+void PlaybackFile::close() {
+ delete _readStream;
+ _readStream = NULL;
+ if (_writeStream != NULL) {
+ dumpRecordsToFile();
+ _writeStream->finalize();
+ delete _writeStream;
+ _writeStream = NULL;
+ updateHeader();
+ }
+ if (_screenshotsFile != NULL) {
+ _screenshotsFile->finalize();
+ delete _screenshotsFile;
+ _screenshotsFile = NULL;
+ }
+ for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) {
+ free(i->_value.buffer);
+ }
+ _header.saveFiles.clear();
+ _mode = kClosed;
+}
+
+bool PlaybackFile::parseHeader() {
+ PlaybackFileHeader result;
+ ChunkHeader nextChunk;
+ _playbackParseState = kFileStateCheckFormat;
+ if (!readChunkHeader(nextChunk)) {
+ _playbackParseState = kFileStateError;
+ return false;
+ }
+ while ((_playbackParseState != kFileStateDone) && (_playbackParseState != kFileStateError)) {
+ if (processChunk(nextChunk)) {
+ if (!readChunkHeader(nextChunk)) {
+ warning("Error in header parsing");
+ _playbackParseState = kFileStateError;
+ }
+ }
+ }
+ return _playbackParseState == kFileStateDone;
+}
+
+bool PlaybackFile::checkPlaybackFileVersion() {
+ uint32 version;
+ version = _readStream->readUint32LE();
+ if (version != RECORD_VERSION) {
+ warning("Incorrect playback file version. Expected version %d, but got %d.", RECORD_VERSION, version);
+ return false;
+ }
+ return true;
+}
+
+
+String PlaybackFile::readString(int len) {
+ String result;
+ char buf[50];
+ int readSize = 49;
+ while (len > 0) {
+ if (len <= 49) {
+ readSize = len;
+ }
+ _readStream->read(buf, readSize);
+ buf[readSize] = 0;
+ result += buf;
+ len -= readSize;
+ }
+ return result;
+}
+
+bool PlaybackFile::readChunkHeader(PlaybackFile::ChunkHeader &nextChunk) {
+ nextChunk.id = (FileTag)_readStream->readUint32LE();
+ nextChunk.len = _readStream->readUint32LE();
+ return !_readStream->err() && !_readStream->eos();
+}
+
+bool PlaybackFile::processChunk(ChunkHeader &nextChunk) {
+ switch (_playbackParseState) {
+ case kFileStateCheckFormat:
+ if (nextChunk.id == kFormatIdTag) {
+ _playbackParseState = kFileStateCheckVersion;
+ } else {
+ warning("Unknown playback file signature");
+ _playbackParseState = kFileStateError;
+ }
+ break;
+ case kFileStateCheckVersion:
+ if ((nextChunk.id == kVersionTag) && checkPlaybackFileVersion()) {
+ _playbackParseState = kFileStateSelectSection;
+ } else {
+ _playbackParseState = kFileStateError;
+ }
+ break;
+ case kFileStateSelectSection:
+ switch (nextChunk.id) {
+ case kHeaderSectionTag:
+ _playbackParseState = kFileStateProcessHeader;
+ break;
+ case kHashSectionTag:
+ _playbackParseState = kFileStateProcessHash;
+ break;
+ case kRandomSectionTag:
+ _playbackParseState = kFileStateProcessRandom;
+ break;
+ case kEventTag:
+ case kScreenShotTag:
+ _readStream->seek(-8, SEEK_CUR);
+ _playbackParseState = kFileStateDone;
+ return false;
+ case kSaveTag:
+ _playbackParseState = kFileStateProcessSave;
+ break;
+ case kSettingsSectionTag:
+ _playbackParseState = kFileStateProcessSettings;
+ warning("Loading record header");
+ break;
+ default:
+ _readStream->skip(nextChunk.len);
+ break;
+ }
+ break;
+ case kFileStateProcessSave:
+ if (nextChunk.id == kSaveRecordTag) {
+ readSaveRecord();
+ } else {
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ case kFileStateProcessHeader:
+ switch (nextChunk.id) {
+ case kAuthorTag:
+ _header.author = readString(nextChunk.len);
+ break;
+ case kCommentsTag:
+ _header.notes = readString(nextChunk.len);
+ break;
+ case kNameTag:
+ _header.name = readString(nextChunk.len);
+ break;
+ default:
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ case kFileStateProcessHash:
+ if (nextChunk.id == kHashRecordTag) {
+ readHashMap(nextChunk);
+ } else {
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ case kFileStateProcessRandom:
+ if (nextChunk.id == kRandomRecordTag) {
+ processRndSeedRecord(nextChunk);
+ } else {
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ case kFileStateProcessSettings:
+ if (nextChunk.id == kSettingsRecordTag) {
+ if (!processSettingsRecord()) {
+ _playbackParseState = kFileStateError;
+ return false;
+ }
+ } else {
+ _playbackParseState = kFileStateSelectSection;
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+void PlaybackFile::returnToChunkHeader() {
+ _readStream->seek(-8, SEEK_CUR);
+}
+
+void PlaybackFile::readHashMap(ChunkHeader chunk) {
+ String hashName = readString(chunk.len - 32);
+ String hashMd5 = readString(32);
+ _header.hashRecords[hashName] = hashMd5;
+}
+
+void PlaybackFile::processRndSeedRecord(ChunkHeader chunk) {
+ String randomSourceName = readString(chunk.len - 4);
+ uint32 randomSourceSeed = _readStream->readUint32LE();
+ _header.randomSourceRecords[randomSourceName] = randomSourceSeed;
+}
+
+bool PlaybackFile::processSettingsRecord() {
+ ChunkHeader keyChunk;
+ if (!readChunkHeader(keyChunk) || (keyChunk.id != kSettingsRecordKeyTag)) {
+ warning("Invalid format of settings section");
+ return false;
+ }
+ String key = readString(keyChunk.len);
+ ChunkHeader valueChunk;
+ if (!readChunkHeader(valueChunk) || (valueChunk.id != kSettingsRecordValueTag)) {
+ warning("Invalid format of settings section");
+ return false;
+ }
+ String value = readString(valueChunk.len);
+ _header.settingsRecords[key] = value;
+ return true;
+}
+
+
+bool PlaybackFile::readSaveRecord() {
+ ChunkHeader fileNameChunk;
+ if (!readChunkHeader(fileNameChunk) || (fileNameChunk.id != kSaveRecordNameTag)) {
+ warning("Invalid format of save section");
+ return false;
+ }
+ String fileName = readString(fileNameChunk.len);
+ ChunkHeader saveBufferChunk;
+ if (!readChunkHeader(saveBufferChunk) || (saveBufferChunk.id != kSaveRecordBufferTag)) {
+ warning("Invalid format of save section");
+ return false;
+ }
+ SaveFileBuffer buf;
+ buf.size = saveBufferChunk.len;
+ buf.buffer = (byte *)malloc(saveBufferChunk.len);
+ _readStream->read(buf.buffer, buf.size);
+ _header.saveFiles[fileName] = buf;
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load save file\" filename=%s len=%d", fileName.c_str(), buf.size);
+ return true;
+}
+
+
+
+RecorderEvent PlaybackFile::getNextEvent() {
+ assert(_mode == kRead);
+ if (isEventsBufferEmpty()) {
+ PlaybackFile::ChunkHeader header;
+ header.id = kFormatIdTag;
+ while (header.id != kEventTag) {
+ if (!readChunkHeader(header) || _readStream->eos()) {
+ break;
+ }
+ switch (header.id) {
+ case kEventTag:
+ readEventsToBuffer(header.len);
+ break;
+ case kScreenShotTag:
+ _readStream->seek(-4, SEEK_CUR);
+ header.len = _readStream->readUint32BE();
+ _readStream->skip(header.len-8);
+ break;
+ case kMD5Tag:
+ checkRecordedMD5();
+ break;
+ default:
+ _readStream->skip(header.len);
+ break;
+ }
+ }
+ }
+ RecorderEvent result;
+ readEvent(result);
+ return result;
+}
+
+bool PlaybackFile::isEventsBufferEmpty() {
+ return (uint32)_tmpPlaybackFile.pos() == _eventsSize;
+}
+
+void PlaybackFile::readEvent(RecorderEvent& event) {
+ event.recordedtype = (RecorderEventType)_tmpPlaybackFile.readByte();
+ switch (event.recordedtype) {
+ case kRecorderEventTypeTimer:
+ event.time = _tmpPlaybackFile.readUint32LE();
+ break;
+ case kRecorderEventTypeNormal:
+ event.type = (EventType)_tmpPlaybackFile.readUint32LE();
+ switch (event.type) {
+ case EVENT_KEYDOWN:
+ case EVENT_KEYUP:
+ event.time = _tmpPlaybackFile.readUint32LE();
+ event.kbd.keycode = (KeyCode)_tmpPlaybackFile.readSint32LE();
+ event.kbd.ascii = _tmpPlaybackFile.readUint16LE();
+ event.kbd.flags = _tmpPlaybackFile.readByte();
+ break;
+ case EVENT_MOUSEMOVE:
+ case EVENT_LBUTTONDOWN:
+ case EVENT_LBUTTONUP:
+ case EVENT_RBUTTONDOWN:
+ case EVENT_RBUTTONUP:
+ case EVENT_WHEELUP:
+ case EVENT_WHEELDOWN:
+ case EVENT_MBUTTONDOWN:
+ case EVENT_MBUTTONUP:
+ event.time = _tmpPlaybackFile.readUint32LE();
+ event.mouse.x = _tmpPlaybackFile.readSint16LE();
+ event.mouse.y = _tmpPlaybackFile.readSint16LE();
+ break;
+ default:
+ event.time = _tmpPlaybackFile.readUint32LE();
+ break;
+ }
+ break;
+ }
+ event.synthetic = true;
+}
+
+void PlaybackFile::readEventsToBuffer(uint32 size) {
+ _readStream->read(_tmpBuffer, size);
+ _tmpPlaybackFile.seek(0);
+ _eventsSize = size;
+}
+
+void PlaybackFile::saveScreenShot(Graphics::Surface &screen, byte md5[16]) {
+ dumpRecordsToFile();
+ _writeStream->writeUint32LE(kMD5Tag);
+ _writeStream->writeUint32LE(16);
+ _writeStream->write(md5, 16);
+ Graphics::saveThumbnail(*_writeStream, screen);
+}
+
+void PlaybackFile::dumpRecordsToFile() {
+ if (!_headerDumped) {
+ dumpHeaderToFile();
+ _headerDumped = true;
+ }
+ if (_recordCount == 0) {
+ return;
+ }
+ _writeStream->writeUint32LE(kEventTag);
+ _writeStream->writeUint32LE(_tmpRecordFile.pos());
+ _writeStream->write(_tmpBuffer, _tmpRecordFile.pos());
+ _tmpRecordFile.seek(0);
+ _recordCount = 0;
+}
+
+void PlaybackFile::dumpHeaderToFile() {
+ _writeStream->writeUint32LE(kFormatIdTag);
+ // Specify size for first tag as NULL since we cannot calculate
+ // size of the file at time of the header dumping
+ _writeStream->writeUint32LE(0);
+ _writeStream->writeUint32LE(kVersionTag);
+ _writeStream->writeUint32LE(4);
+ _writeStream->writeUint32LE(RECORD_VERSION);
+ writeHeaderSection();
+ writeGameHash();
+ writeRandomRecords();
+ writeGameSettings();
+ writeSaveFilesSection();
+}
+
+void PlaybackFile::writeHeaderSection() {
+ uint32 headerSize = 0;
+ if (!_header.author.empty()) {
+ headerSize = _header.author.size() + 8;
+ }
+ if (!_header.notes.empty()) {
+ headerSize += _header.notes.size() + 8;
+ }
+ if (!_header.name.empty()) {
+ headerSize += _header.name.size() + 8;
+ }
+ if (headerSize == 0) {
+ return;
+ }
+ _writeStream->writeUint32LE(kHeaderSectionTag);
+ _writeStream->writeUint32LE(headerSize);
+ if (!_header.author.empty()) {
+ _writeStream->writeUint32LE(kAuthorTag);
+ _writeStream->writeUint32LE(_header.author.size());
+ _writeStream->writeString(_header.author);
+ }
+ if (!_header.notes.empty()) {
+ _writeStream->writeUint32LE(kCommentsTag);
+ _writeStream->writeUint32LE(_header.notes.size());
+ _writeStream->writeString(_header.notes);
+ }
+ if (!_header.name.empty()) {
+ _writeStream->writeUint32LE(kNameTag);
+ _writeStream->writeUint32LE(_header.name.size());
+ _writeStream->writeString(_header.name);
+ }
+}
+
+void PlaybackFile::writeGameHash() {
+ uint32 hashSectionSize = 0;
+ for (StringMap::iterator i = _header.hashRecords.begin(); i != _header.hashRecords.end(); ++i) {
+ hashSectionSize = hashSectionSize + i->_key.size() + i->_value.size() + 8;
+ }
+ if (_header.hashRecords.size() == 0) {
+ return;
+ }
+ _writeStream->writeUint32LE(kHashSectionTag);
+ _writeStream->writeUint32LE(hashSectionSize);
+ for (StringMap::iterator i = _header.hashRecords.begin(); i != _header.hashRecords.end(); ++i) {
+ _writeStream->writeUint32LE(kHashRecordTag);
+ _writeStream->writeUint32LE(i->_key.size() + i->_value.size());
+ _writeStream->writeString(i->_key);
+ _writeStream->writeString(i->_value);
+ }
+}
+
+void PlaybackFile::writeRandomRecords() {
+ uint32 randomSectionSize = 0;
+ for (RandomSeedsDictionary::iterator i = _header.randomSourceRecords.begin(); i != _header.randomSourceRecords.end(); ++i) {
+ randomSectionSize = randomSectionSize + i->_key.size() + 12;
+ }
+ if (_header.randomSourceRecords.size() == 0) {
+ return;
+ }
+ _writeStream->writeUint32LE(kRandomSectionTag);
+ _writeStream->writeUint32LE(randomSectionSize);
+ for (RandomSeedsDictionary::iterator i = _header.randomSourceRecords.begin(); i != _header.randomSourceRecords.end(); ++i) {
+ _writeStream->writeUint32LE(kRandomRecordTag);
+ _writeStream->writeUint32LE(i->_key.size() + 4);
+ _writeStream->writeString(i->_key);
+ _writeStream->writeUint32LE(i->_value);
+ }
+}
+
+void PlaybackFile::writeEvent(const RecorderEvent &event) {
+ assert(_mode == kWrite);
+ _recordCount++;
+ _tmpRecordFile.writeByte(event.recordedtype);
+ switch (event.recordedtype) {
+ case kRecorderEventTypeTimer:
+ _tmpRecordFile.writeUint32LE(event.time);
+ break;
+ case kRecorderEventTypeNormal:
+ _tmpRecordFile.writeUint32LE((uint32)event.type);
+ switch(event.type) {
+ case EVENT_KEYDOWN:
+ case EVENT_KEYUP:
+ _tmpRecordFile.writeUint32LE(event.time);
+ _tmpRecordFile.writeSint32LE(event.kbd.keycode);
+ _tmpRecordFile.writeUint16LE(event.kbd.ascii);
+ _tmpRecordFile.writeByte(event.kbd.flags);
+ break;
+ case EVENT_MOUSEMOVE:
+ case EVENT_LBUTTONDOWN:
+ case EVENT_LBUTTONUP:
+ case EVENT_RBUTTONDOWN:
+ case EVENT_RBUTTONUP:
+ case EVENT_WHEELUP:
+ case EVENT_WHEELDOWN:
+ case EVENT_MBUTTONDOWN:
+ case EVENT_MBUTTONUP:
+ _tmpRecordFile.writeUint32LE(event.time);
+ _tmpRecordFile.writeSint16LE(event.mouse.x);
+ _tmpRecordFile.writeSint16LE(event.mouse.y);
+ break;
+ default:
+ _tmpRecordFile.writeUint32LE(event.time);
+ break;
+ }
+ break;
+ }
+ if (_recordCount == kMaxBufferedRecords) {
+ dumpRecordsToFile();
+ }
+}
+
+void PlaybackFile::writeGameSettings() {
+ _writeStream->writeUint32LE(kSettingsSectionTag);
+ uint32 settingsSectionSize = 0;
+ for (StringMap::iterator i = _header.settingsRecords.begin(); i != _header.settingsRecords.end(); ++i) {
+ settingsSectionSize += i->_key.size() + i->_value.size() + 24;
+ }
+ _writeStream->writeUint32LE(settingsSectionSize);
+ for (StringMap::iterator i = _header.settingsRecords.begin(); i != _header.settingsRecords.end(); ++i) {
+ _writeStream->writeUint32LE(kSettingsRecordTag);
+ _writeStream->writeUint32LE(i->_key.size() + i->_value.size() + 16);
+ _writeStream->writeUint32LE(kSettingsRecordKeyTag);
+ _writeStream->writeUint32LE(i->_key.size());
+ _writeStream->writeString(i->_key);
+ _writeStream->writeUint32LE(kSettingsRecordValueTag);
+ _writeStream->writeUint32LE(i->_value.size());
+ _writeStream->writeString(i->_value);
+ }
+}
+
+int PlaybackFile::getScreensCount() {
+ if (_mode != kRead) {
+ return 0;
+ }
+ _readStream->seek(0);
+ int result = 0;
+ while (skipToNextScreenshot()) {
+ uint32 size = _readStream->readUint32BE();
+ _readStream->skip(size-8);
+ ++result;
+ }
+ return result;
+}
+
+bool PlaybackFile::skipToNextScreenshot() {
+ while (true) {
+ FileTag id = (FileTag)_readStream->readUint32LE();
+ if (_readStream->eos()) {
+ break;
+ }
+ if (id == kScreenShotTag) {
+ return true;
+ }
+ else {
+ uint32 size = _readStream->readUint32LE();
+ _readStream->skip(size);
+ }
+ }
+ return false;
+}
+
+Graphics::Surface *PlaybackFile::getScreenShot(int number) {
+ if (_mode != kRead) {
+ return NULL;
+ }
+ _readStream->seek(0);
+ int screenCount = 1;
+ while (skipToNextScreenshot()) {
+ if (screenCount == number) {
+ screenCount++;
+ _readStream->seek(-4, SEEK_CUR);
+ return Graphics::loadThumbnail(*_readStream);
+ } else {
+ uint32 size = _readStream->readUint32BE();
+ _readStream->skip(size-8);
+ screenCount++;
+ }
+ }
+ return NULL;
+}
+
+void PlaybackFile::updateHeader() {
+ if (_mode == kWrite) {
+ _readStream = g_system->getSavefileManager()->openForLoading(_header.fileName);
+ }
+ _readStream->seek(0);
+ skipHeader();
+ String tmpFilename = "_" + _header.fileName;
+ _writeStream = g_system->getSavefileManager()->openForSaving(tmpFilename);
+ dumpHeaderToFile();
+ uint32 readedSize = 0;
+ do {
+ readedSize = _readStream->read(_tmpBuffer, kRecordBuffSize);
+ _writeStream->write(_tmpBuffer, readedSize);
+ } while (readedSize != 0);
+ delete _writeStream;
+ _writeStream = NULL;
+ delete _readStream;
+ _readStream = NULL;
+ g_system->getSavefileManager()->removeSavefile(_header.fileName);
+ g_system->getSavefileManager()->renameSavefile(tmpFilename, _header.fileName);
+ if (_mode == kRead) {
+ openRead(_header.fileName);
+ }
+}
+
+void PlaybackFile::skipHeader() {
+ while (true) {
+ uint32 id = _readStream->readUint32LE();
+ if (_readStream->eos()) {
+ break;
+ }
+ if ((id == kScreenShotTag) || (id == kEventTag) || (id == kMD5Tag)) {
+ _readStream->seek(-4, SEEK_CUR);
+ return;
+ }
+ else {
+ uint32 size = _readStream->readUint32LE();
+ _readStream->skip(size);
+ }
+ }
+}
+
+void PlaybackFile::addSaveFile(const String &fileName, InSaveFile *saveStream) {
+ uint oldPos = saveStream->pos();
+ saveStream->seek(0);
+ _header.saveFiles[fileName].buffer = (byte *)malloc(saveStream->size());
+ _header.saveFiles[fileName].size = saveStream->size();
+ saveStream->read(_header.saveFiles[fileName].buffer, saveStream->size());
+ saveStream->seek(oldPos);
+}
+
+void PlaybackFile::writeSaveFilesSection() {
+ uint size = 0;
+ for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) {
+ size += i->_value.size + i->_key.size() + 24;
+ }
+ if (size == 0) {
+ return;
+ }
+ _writeStream->writeSint32LE(kSaveTag);
+ _writeStream->writeSint32LE(size);
+ for (HashMap<String, SaveFileBuffer>::iterator i = _header.saveFiles.begin(); i != _header.saveFiles.end(); ++i) {
+ _writeStream->writeSint32LE(kSaveRecordTag);
+ _writeStream->writeSint32LE(i->_key.size() + i->_value.size + 16);
+ _writeStream->writeSint32LE(kSaveRecordNameTag);
+ _writeStream->writeSint32LE(i->_key.size());
+ _writeStream->writeString(i->_key);
+ _writeStream->writeSint32LE(kSaveRecordBufferTag);
+ _writeStream->writeSint32LE(i->_value.size);
+ _writeStream->write(i->_value.buffer, i->_value.size);
+ }
+}
+
+
+void PlaybackFile::checkRecordedMD5() {
+ uint8 currentMD5[16];
+ uint8 savedMD5[16];
+ Graphics::Surface screen;
+ _readStream->read(savedMD5, 16);
+ if (!g_eventRec.grabScreenAndComputeMD5(screen, currentMD5)) {
+ return;
+ }
+ uint32 seconds = g_system->getMillis(true) / 1000;
+ String screenTime = String::format("%.2d:%.2d:%.2d", seconds / 3600 % 24, seconds / 60 % 60, seconds % 60);
+ if (memcmp(savedMD5, currentMD5, 16) != 0) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check screenshot\" time=%s result = fail", screenTime.c_str());
+ warning("Recorded and current screenshots are different");
+ } else {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check screenshot\" time=%s result = success", screenTime.c_str());
+ }
+ Graphics::saveThumbnail(*_screenshotsFile, screen);
+ screen.free();
+}
+
+
+}
diff --git a/common/recorderfile.h b/common/recorderfile.h
new file mode 100644
index 0000000000..1c95e5a915
--- /dev/null
+++ b/common/recorderfile.h
@@ -0,0 +1,180 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef COMMON_RECORDERFILE_H
+#define COMMON_RECORDERFILE_H
+
+#include "common/scummsys.h"
+#include "common/events.h"
+#include "common/mutex.h"
+#include "common/memstream.h"
+#include "common/config-manager.h"
+#include "common/savefile.h"
+
+//capacity of records buffer
+#define kMaxBufferedRecords 10000
+#define kRecordBuffSize sizeof(RecorderEvent) * kMaxBufferedRecords
+
+namespace Common {
+
+enum RecorderEventType {
+ kRecorderEventTypeNormal = 0,
+ kRecorderEventTypeTimer = 1
+};
+
+struct RecorderEvent : Event {
+ RecorderEventType recordedtype;
+ uint32 time;
+};
+
+
+
+class PlaybackFile {
+ typedef HashMap<String, uint32, IgnoreCase_Hash, IgnoreCase_EqualTo> RandomSeedsDictionary;
+ enum fileMode {
+ kRead = 0,
+ kWrite = 1,
+ kClosed = 2
+ };
+ enum PlaybackFileState {
+ kFileStateCheckFormat,
+ kFileStateCheckVersion,
+ kFileStateProcessHash,
+ kFileStateProcessHeader,
+ kFileStateProcessRandom,
+ kFileStateSelectSection,
+ kFileStateProcessSettings,
+ kFileStateProcessSave,
+ kFileStateDone,
+ kFileStateError
+ };
+ enum FileTag {
+ kFormatIdTag = MKTAG('P','B','C','K'),
+ kVersionTag = MKTAG('V','E','R','S'),
+ kHeaderSectionTag = MKTAG('H','E','A','D'),
+ kHashSectionTag = MKTAG('H','A','S','H'),
+ kRandomSectionTag = MKTAG('R','A','N','D'),
+ kEventTag = MKTAG('E','V','N','T'),
+ kScreenShotTag = MKTAG('B','M','H','T'),
+ kSettingsSectionTag = MKTAG('S','E','T','T'),
+ kAuthorTag = MKTAG('H','A','U','T'),
+ kCommentsTag = MKTAG('H','C','M','T'),
+ kNameTag = MKTAG('H','N','A','M'),
+ kHashRecordTag = MKTAG('H','R','C','D'),
+ kRandomRecordTag = MKTAG('R','R','C','D'),
+ kSettingsRecordTag = MKTAG('S','R','E','C'),
+ kSettingsRecordKeyTag = MKTAG('S','K','E','Y'),
+ kSettingsRecordValueTag = MKTAG('S','V','A','L'),
+ kSaveTag = MKTAG('S','A','V','E'),
+ kSaveRecordTag = MKTAG('R','S','A','V'),
+ kSaveRecordNameTag = MKTAG('S','N','A','M'),
+ kSaveRecordBufferTag = MKTAG('S','B','U','F'),
+ kMD5Tag = MKTAG('M','D','5',' ')
+ };
+ struct ChunkHeader {
+ FileTag id;
+ uint32 len;
+ };
+public:
+ struct SaveFileBuffer {
+ byte *buffer;
+ uint32 size;
+ };
+ struct PlaybackFileHeader {
+ String fileName;
+ String author;
+ String name;
+ String notes;
+ String description;
+ StringMap hashRecords;
+ StringMap settingsRecords;
+ HashMap<String, SaveFileBuffer> saveFiles;
+ RandomSeedsDictionary randomSourceRecords;
+ };
+ PlaybackFile();
+ ~PlaybackFile();
+
+ bool openWrite(const String &fileName);
+ bool openRead(const String &fileName);
+ void close();
+
+ RecorderEvent getNextEvent();
+ void writeEvent(const RecorderEvent &event);
+
+ void saveScreenShot(Graphics::Surface &screen, byte md5[16]);
+ Graphics::Surface *getScreenShot(int number);
+ int getScreensCount();
+
+ bool isEventsBufferEmpty();
+ PlaybackFileHeader &getHeader() {return _header;}
+ void updateHeader();
+ void addSaveFile(const String &fileName, InSaveFile *saveStream);
+private:
+ WriteStream *_recordFile;
+ WriteStream *_writeStream;
+ WriteStream *_screenshotsFile;
+ MemoryReadStream _tmpPlaybackFile;
+ SeekableReadStream *_readStream;
+ SeekableMemoryWriteStream _tmpRecordFile;
+
+ fileMode _mode;
+ bool _headerDumped;
+ int _recordCount;
+ uint32 _eventsSize;
+ byte _tmpBuffer[kRecordBuffSize];
+ PlaybackFileHeader _header;
+ PlaybackFileState _playbackParseState;
+
+ void skipHeader();
+ bool parseHeader();
+ bool processChunk(ChunkHeader &nextChunk);
+ void returnToChunkHeader();
+
+ bool readSaveRecord();
+ void checkRecordedMD5();
+ bool readChunkHeader(ChunkHeader &nextChunk);
+ void processRndSeedRecord(ChunkHeader chunk);
+ bool processSettingsRecord();
+
+ bool checkPlaybackFileVersion();
+
+ void dumpHeaderToFile();
+ void writeSaveFilesSection();
+ void writeGameSettings();
+ void writeHeaderSection();
+ void writeGameHash();
+ void writeRandomRecords();
+
+ void dumpRecordsToFile();
+
+ String readString(int len);
+ void readHashMap(ChunkHeader chunk);
+
+ bool skipToNextScreenshot();
+ void readEvent(RecorderEvent& event);
+ void readEventsToBuffer(uint32 size);
+ bool grabScreenAndComputeMD5(Graphics::Surface &screen, uint8 md5[16]);
+};
+
+} // End of namespace Common
+
+#endif
diff --git a/common/str.cpp b/common/str.cpp
index 5d647ee4f0..4a10792373 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -361,6 +361,25 @@ void String::deleteChar(uint32 p) {
_size--;
}
+void String::erase(uint32 p, uint32 len) {
+ assert(p < _size);
+
+ makeUnique();
+ // If len == npos or p + len is over the end, remove all the way to the end
+ if (len == npos || p + len >= _size) {
+ // Delete char at p as well. So _size = (p - 1) + 1
+ _size = p;
+ // Null terminate
+ _str[_size] = 0;
+ return;
+ }
+
+ for ( ; p + len <= _size; p++) {
+ _str[p] = _str[p + len];
+ }
+ _size -= len;
+}
+
void String::clear() {
decRefCount(_extern._refCount);
diff --git a/common/str.h b/common/str.h
index 5039130707..6b4475e1c4 100644
--- a/common/str.h
+++ b/common/str.h
@@ -43,6 +43,8 @@ namespace Common {
* behavior in some operations.
*/
class String {
+public:
+ static const uint32 npos = 0xFFFFFFFF;
protected:
/**
* The size of the internal storage. Increasing this means less heap
@@ -191,6 +193,9 @@ public:
/** Remove the character at position p from the string. */
void deleteChar(uint32 p);
+ /** Remove all characters from position p to the p + len. If len = String::npos, removes all characters to the end */
+ void erase(uint32 p, uint32 len = npos);
+
/** Set character c at position p, replacing the previous character there. */
void setChar(char c, uint32 p);
diff --git a/common/system.cpp b/common/system.cpp
index 59210544ab..d86b5b2b81 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -30,6 +30,9 @@
#include "common/taskbar.h"
#include "common/updates.h"
#include "common/textconsole.h"
+#ifdef ENABLE_EVENTRECORDER
+#include "gui/EventRecorder.h"
+#endif
#include "backends/audiocd/default/default-audiocd.h"
#include "backends/fs/fs-factory.h"
@@ -84,7 +87,7 @@ void OSystem::initBackend() {
error("Backend failed to instantiate audio CD manager");
if (!_eventManager)
error("Backend failed to instantiate event manager");
- if (!_timerManager)
+ if (!getTimerManager())
error("Backend failed to instantiate timer manager");
// TODO: We currently don't check _savefileManager, because at least
@@ -152,3 +155,15 @@ Common::String OSystem::getDefaultConfigFileName() {
Common::String OSystem::getSystemLanguage() const {
return "en_US";
}
+
+Common::TimerManager *OSystem::getTimerManager() {
+ return _timerManager;
+}
+
+Common::SaveFileManager *OSystem::getSavefileManager() {
+#ifdef ENABLE_EVENTRECORDER
+ return g_eventRec.getSaveManager(_savefileManager);
+#else
+ return _savefileManager;
+#endif
+}
diff --git a/common/system.h b/common/system.h
index 99b947d7f3..81c4bdf34e 100644
--- a/common/system.h
+++ b/common/system.h
@@ -890,8 +890,14 @@ public:
/** @name Events and Time */
//@{
- /** Get the number of milliseconds since the program was started. */
- virtual uint32 getMillis() = 0;
+ /** Get the number of milliseconds since the program was started.
+
+ @param skipRecord Skip recording of this value by event recorder.
+ This could be needed particularly when we are in
+ an on-screen GUI loop where player can pause
+ the recording.
+ */
+ virtual uint32 getMillis(bool skipRecord = false) = 0;
/** Delay/sleep for the specified amount of milliseconds. */
virtual void delayMillis(uint msecs) = 0;
@@ -907,9 +913,7 @@ public:
* Return the timer manager singleton. For more information, refer
* to the TimerManager documentation.
*/
- inline Common::TimerManager *getTimerManager() {
- return _timerManager;
- }
+ virtual Common::TimerManager *getTimerManager();
/**
* Return the event manager singleton. For more information, refer
@@ -1086,9 +1090,7 @@ public:
* and other modifiable persistent game data. For more information,
* refer to the SaveFileManager documentation.
*/
- inline Common::SaveFileManager *getSavefileManager() {
- return _savefileManager;
- }
+ Common::SaveFileManager *getSavefileManager();
#if defined(USE_TASKBAR)
/**
diff --git a/common/util.h b/common/util.h
index 4ca1c42929..392ced1ffe 100644
--- a/common/util.h
+++ b/common/util.h
@@ -41,10 +41,10 @@
#undef MAX
#endif
-template<typename T> inline T ABS (T x) { return (x>=0) ? x : -x; }
-template<typename T> inline T MIN (T a, T b) { return (a<b) ? a : b; }
-template<typename T> inline T MAX (T a, T b) { return (a>b) ? a : b; }
-template<typename T> inline T CLIP (T v, T amin, T amax)
+template<typename T> inline T ABS(T x) { return (x >= 0) ? x : -x; }
+template<typename T> inline T MIN(T a, T b) { return (a < b) ? a : b; }
+template<typename T> inline T MAX(T a, T b) { return (a > b) ? a : b; }
+template<typename T> inline T CLIP(T v, T amin, T amax)
{ if (v < amin) return amin; else if (v > amax) return amax; else return v; }
/**
diff --git a/common/winexe_ne.cpp b/common/winexe_ne.cpp
index 6bb40e0980..c3698d5fce 100644
--- a/common/winexe_ne.cpp
+++ b/common/winexe_ne.cpp
@@ -231,7 +231,7 @@ bool NEResources::readResourceTable(uint32 offset) {
if (id & 0x8000)
res.id = id & 0x7FFF;
else
- res.id = getResourceString(*_exe, offset + id);
+ res.id = getResourceString(*_exe, offset + id);
if (typeID & 0x8000 && ((typeID & 0x7FFF) < ARRAYSIZE(s_resTypeNames)) && s_resTypeNames[typeID & 0x7FFF][0] != 0)
debug(2, "Found resource %s %s", s_resTypeNames[typeID & 0x7FFF], res.id.toString().c_str());
diff --git a/configure b/configure
index dbd78d3f9d..1da7d7fb78 100755
--- a/configure
+++ b/configure
@@ -113,6 +113,7 @@ _seq_midi=auto
_sndio=auto
_timidity=auto
_zlib=auto
+_mpeg2=auto
_sparkle=auto
_png=auto
_theoradec=auto
@@ -138,9 +139,10 @@ _build_hq_scalers=yes
_enable_prof=no
_global_constructors=no
_bink=yes
-# Default vkeybd/keymapper options
+# Default vkeybd/keymapper/eventrec options
_vkeybd=no
_keymapper=no
+_eventrec=auto
# GUI translation options
_translation=yes
# Default platform settings
@@ -816,7 +818,7 @@ Usage: $0 [OPTIONS]...
Configuration:
-h, --help display this help and exit
- --backend=BACKEND backend to build (android, bada, dc, dingux, ds, gph,
+ --backend=BACKEND backend to build (android, tizen, dc, dingux, ds, gph,
iphone, linuxmoto, maemo, n64, null, openpandora, ps2,
psp, samsungtv, sdl, webos, wii, wince) [sdl]
@@ -845,7 +847,7 @@ Fine tuning of the installation directories:
Special configuration feature:
--host=HOST cross-compile to target HOST (arm-linux, ...)
special targets: android for Android
- bada for Samsung BADA
+ tizen for Samsung Tizen
caanoo for Caanoo
dingux for Dingux
dreamcast for Sega Dreamcast
@@ -898,6 +900,10 @@ Optional Features:
--disable-hq-scalers exclude HQ2x and HQ3x scalers
--disable-translation don't build support for translated messages
--disable-taskbar don't build support for taskbar and launcher integration
+ --enable-vkeybd build virtual keyboard support
+ --enable-keymapper build key mapper support
+ --enable-eventrecorder enable event recording functionality
+ --disable-eventrecorder disable event recording functionality
--enable-updates build support for updates
--enable-text-console use text console instead of graphical console
--enable-verbose-build enable regular echoing of commands during build
@@ -924,6 +930,9 @@ Optional Libraries:
--with-zlib-prefix=DIR Prefix where zlib is installed (optional)
--disable-zlib disable zlib (compression) support [autodetect]
+ --with-mpeg2-prefix=DIR Prefix where libmpeg2 is installed (optional)
+ --enable-mpeg2 enable mpeg2 codec for cutscenes [autodetect]
+
--with-opengl-prefix=DIR Prefix where OpenGL (ES) is installed (optional)
--disable-opengl disable OpenGL (ES) support [autodetect]
@@ -1004,6 +1013,8 @@ for ac_option in $@; do
--disable-sparkle) _sparkle=no ;;
--enable-nasm) _nasm=yes ;;
--disable-nasm) _nasm=no ;;
+ --enable-mpeg2) _mpeg2=yes ;;
+ --disable-mpeg2) _mpeg2=no ;;
--disable-png) _png=no ;;
--enable-png) _png=yes ;;
--disable-theoradec) _theoradec=no ;;
@@ -1036,6 +1047,8 @@ for ac_option in $@; do
--disable-vkeybd) _vkeybd=no ;;
--enable-keymapper) _keymapper=yes ;;
--disable-keymapper) _keymapper=no ;;
+ --enable-eventrecorder) _eventrec=yes ;;
+ --disable-eventrecorder) _eventrec=no ;;
--enable-text-console) _text_console=yes ;;
--disable-text-console) _text_console=no ;;
--with-fluidsynth-prefix=*)
@@ -1043,6 +1056,11 @@ for ac_option in $@; do
FLUIDSYNTH_CFLAGS="-I$arg/include"
FLUIDSYNTH_LIBS="-L$arg/lib"
;;
+ --with-mpeg2-prefix=*)
+ arg=`echo $ac_option | cut -d '=' -f 2`
+ MPEG2_CFLAGS="-I$arg/include"
+ MPEG2_LIBS="-L$arg/lib"
+ ;;
--with-alsa-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
ALSA_CFLAGS="-I$arg/include"
@@ -1247,16 +1265,6 @@ arm-riscos)
_host_os=riscos
_host_cpu=arm
;;
-bada)
- _host_os=bada
- if test "$_debug_build" = yes; then
- _host_cpu=i686
- _host_alias=i686-mingw32
- else
- _host_cpu=arm
- _host_alias=arm-samsung-nucleuseabi
- fi
- ;;
caanoo)
_host_os=gph-linux
_host_cpu=arm
@@ -1382,6 +1390,11 @@ samsungtv)
_host_cpu=arm
_host_alias=arm-linux-gnueabi
;;
+tizen)
+ _host_os=tizen
+ _host_cpu=arm
+ _host_alias=arm-linux-gnueabi
+ ;;
webos)
_host_os=webos
_host_cpu=arm
@@ -1491,12 +1504,6 @@ android)
exit 1
fi
;;
-bada)
- if test -z "$BADA_SDK"; then
- echo "Please set BADA_SDK in your environment. export BADA_SDK=<path to Bada SDK>"
- exit 1
- fi
- ;;
ds | gamecube | wii)
if test -z "$DEVKITPRO"; then
echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>"
@@ -1538,6 +1545,12 @@ psp)
exit 1
fi
;;
+tizen)
+ if test -z "$TIZEN_ROOTSTRAP"; then
+ echo "Please set TIZEN_ROOTSTRAP in your environment. export TIZEN_ROOTSTRAP=<path to Tizen SDK device profile>"
+ exit 1
+ fi
+ ;;
webos)
if test -z "$WEBOS_SDK"; then
echo "Please set WEBOS_SDK in your environment. export WEBOS_SDK=<path to WebOS SDK>"
@@ -1731,7 +1744,7 @@ if test "$have_gcc" = yes ; then
case $_host_os in
# newlib-based system include files suppress non-C89 function
# declarations under __STRICT_ANSI__
- amigaos* | android | bada | dreamcast | ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | wii | wince )
+ amigaos* | android | dreamcast | ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | tizen | wii | wince )
;;
*)
CXXFLAGS="$CXXFLAGS -ansi"
@@ -1767,12 +1780,13 @@ echo $_use_cxx11
# However, some platforms use GNU extensions in system header files, so
# for these we must not use -pedantic.
case $_host_os in
-android | gamecube | psp | wii | webos)
+android | gamecube | psp | tizen | wii | webos)
;;
*)
# ICC does not support pedantic, while GCC and clang do.
if test "$have_icc" = no ; then
- CXXFLAGS="$CXXFLAGS -pedantic"
+ # We *do* want the 'long long' extension.
+ CXXFLAGS="$CXXFLAGS -pedantic -Wno-long-long"
fi
;;
esac
@@ -1830,7 +1844,7 @@ esac
# Determine a data type with the given length
#
find_type_with_size() {
- for datatype in int short char long "long long" unknown; do
+ for datatype in int short char long "long long" __int64 "long long int" unknown; do
cat > tmp_find_type_with_size.cpp << EOF
typedef $datatype ac__type_sizeof_;
int main() {
@@ -2051,16 +2065,6 @@ case $_host_os in
add_line_to_config_mk "ANDROID_SDK = $ANDROID_SDK"
_seq_midi=no
;;
- bada)
- BADA_SDK_ROOT="`cygpath -m ${BADA_SDK}`"
- add_line_to_config_mk "BADA_SDK = $BADA_SDK"
- add_line_to_config_mk "BADA_SDK_ROOT = $BADA_SDK_ROOT"
-
- # assume dependencies have been installed in cygwin's /usr/local
- CYGWIN_USR_LOCAL="`cygpath -m /usr/local`"
- LDFLAGS="$LDFLAGS -L${CYGWIN_USR_LOCAL}/lib"
- CXXFLAGS="$CXXFLAGS -I${CYGWIN_USR_LOCAL}/include"
- ;;
beos*)
DEFINES="$DEFINES -DSYSTEM_NOT_SUPPORTING_D_TYPE"
# Needs -lbind -lsocket for the timidity MIDI driver
@@ -2176,7 +2180,7 @@ case $_host_os in
# When not cross-compiling, enable large file support, but don't
# care if getconf doesn't exist or doesn't recognize LFS_CFLAGS.
if test -z "$_host"; then
- CXXFLAGS="$CXXFLAGS $(getconf LFS_CFLAGS 2>/dev/null)"
+ CXXFLAGS="$CXXFLAGS `getconf LFS_CFLAGS 2>/dev/null`"
fi
;;
maemo)
@@ -2238,6 +2242,12 @@ case $_host_os in
# Needs -lbind -lsocket for the timidity MIDI driver
LIBS="$LIBS -lnsl -lsocket"
;;
+ tizen)
+ add_line_to_config_mk "TIZEN_ROOTSTRAP = $TIZEN_ROOTSTRAP"
+ LDFLAGS="$LDFLAGS --sysroot=${TIZEN_ROOTSTRAP}"
+ LDFLAGS="$LDFLAGS -L${TIZEN_LIBS}/lib"
+ CXXFLAGS="$CXXFLAGS -I${TIZEN_LIBS}/include"
+ ;;
webos)
CXXFLAGS="$CXXFLAGS --sysroot=$WEBOS_PDK/arm-gcc/sysroot"
CXXFLAGS="$CXXFLAGS -I$WEBOS_PDK/include"
@@ -2316,22 +2326,6 @@ if test -n "$_host"; then
arm-riscos|linupy)
DEFINES="$DEFINES -DLINUPY"
;;
- bada)
- _unix=yes
- _backend="bada"
- _port_mk="backends/platform/bada/bada.mk"
- if test "$_debug_build" = yes; then
- _arm_asm=no
- else
- _arm_asm=yes
- fi
- _taskbar=no
- _build_scalers=no
- _seq_midi=no
- _mt32emu=no
- _timidity=no
- _vkeybd=yes
- ;;
bfin*)
;;
caanoo)
@@ -2381,7 +2375,8 @@ if test -n "$_host"; then
DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER"
DEFINES="$DEFINES -DDISABLE_TEXT_CONSOLE"
DEFINES="$DEFINES -DDISABLE_COMMAND_LINE"
- if test "$_release_build" = yes; then
+ # Enable serial debugging output only when --enable-debug is passed
+ if test "$_release_build" = yes -o "$_debug_build" != yes; then
DEFINES="$DEFINES -DNOSERIAL"
fi
_optimization_level=-O3
@@ -2644,6 +2639,18 @@ if test -n "$_host"; then
_mt32emu=no
_vkeybd=yes
;;
+ tizen)
+ _unix=yes
+ _backend="tizen"
+ _port_mk="backends/platform/tizen/tizen.mk"
+ _arm_asm=yes
+ _taskbar=no
+ _build_scalers=no
+ _seq_midi=no
+ _mt32emu=no
+ _timidity=no
+ _vkeybd=yes
+ ;;
webos)
_backend="webos"
_port_mk="backends/platform/webos/webos.mk"
@@ -2694,34 +2701,6 @@ case $_backend in
LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
INCLUDES="$INCLUDES -I$ANDROID_NDK/sources/cxx-stl/system/include"
;;
- bada)
- # dirent.h not available. NONSTANDARD_PORT==ensure portdefs.h is included
- DEFINES="$DEFINES -DBADA -DDISABLE_STDIO_FILESTREAM -DNONSTANDARD_PORT"
- DEFINES="$DEFINES -DNO_STDERR_STDOUT"
- DEFINES="$DEFINES -DDISABLE_COMMAND_LINE"
- INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/bada '
- INCLUDES="$INCLUDES "'-I$(BADA_SDK)/include'
- INCLUDES="$INCLUDES "'-I$(BADA_SDK_ROOT)/Include'
- if test "$_debug_build" = yes; then
- # debug using with the simulator
- CXXFLAGS="$CXXFLAGS -D_DEBUG -DSHP -DBUILD_DLL -fmessage-length=0"
- else
- # created a shared library for inclusion via the eclipse build
- CXXFLAGS="$CXXFLAGS -DSHP"
- CXXFLAGS="$CXXFLAGS -fpic"
- CXXFLAGS="$CXXFLAGS -fshort-wchar"
- CXXFLAGS="$CXXFLAGS -mcpu=cortex-a8"
- CXXFLAGS="$CXXFLAGS -mfpu=vfpv3"
- CXXFLAGS="$CXXFLAGS -mfloat-abi=hard"
- CXXFLAGS="$CXXFLAGS -mlittle-endian"
- CXXFLAGS="$CXXFLAGS -mthumb-interwork"
- CXXFLAGS="$CXXFLAGS -Wno-psabi"
- CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
- CXXFLAGS="$CXXFLAGS -fno-short-enums"
- fi
- HOSTEXEPRE=lib
- HOSTEXEEXT=.a
- ;;
dc)
INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/dc'
INCLUDES="$INCLUDES "'-isystem $(ronindir)/include'
@@ -2729,7 +2708,8 @@ case $_backend in
LDFLAGS="$LDFLAGS -nostartfiles"
LDFLAGS="$LDFLAGS "'$(ronindir)/lib/crt0.o'
LDFLAGS="$LDFLAGS "'-L$(ronindir)/lib'
- if test "$_release_build" = yes; then
+ # Enable serial debugging output only when --enable-debug is passed
+ if test "$_release_build" = yes -o "$_debug_build" != yes; then
LIBS="$LIBS -lronin-noserial -lm"
else
LIBS="$LIBS -lronin -lm"
@@ -2804,6 +2784,25 @@ case $_backend in
LDFLAGS="$LDFLAGS -shared"
LDFLAGS="$LDFLAGS -fpic"
;;
+ tizen)
+ # dirent.h not available. NONSTANDARD_PORT==ensure portdefs.h is included
+ DEFINES="$DEFINES -DTIZEN -DDISABLE_STDIO_FILESTREAM -DNONSTANDARD_PORT"
+ DEFINES="$DEFINES -DNO_STDERR_STDOUT"
+ DEFINES="$DEFINES -DDISABLE_COMMAND_LINE"
+ INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/tizen'
+ INCLUDES="$INCLUDES "'-I$(TIZEN_ROOTSTRAP)/usr/include'
+ INCLUDES="$INCLUDES "'-I$(TIZEN_ROOTSTRAP)/usr/include/osp'
+ if test "$_debug_build" = yes; then
+ CXXFLAGS="$CXXFLAGS -D_DEBUG -DBUILD_DLL -O0 -g3"
+ fi
+ # created a shared library for inclusion via the eclipse build
+ CXXFLAGS="$CXXFLAGS -Wno-psabi"
+ CXXFLAGS="$CXXFLAGS --sysroot=${TIZEN_ROOTSTRAP}"
+ CXXFLAGS="$CXXFLAGS -fmessage-length=0"
+ CXXFLAGS="$CXXFLAGS -fPIC"
+ HOSTEXEPRE=lib
+ HOSTEXEEXT=.a
+ ;;
webos)
# There is no sdl-config in the WebOS PDK so we don't use find_sdlconfig here.
# The PDL library acts as the WebOS device toolchain, and is required to control the virtual keyboard among other OS-level events.
@@ -2869,7 +2868,7 @@ esac
# Enable 16bit support only for backends which support it
#
case $_backend in
- android | bada | dingux | dc | gph | iphone | maemo | openpandora | psp | samsungtv | sdl | webos | wii)
+ android | dingux | dc | gph | iphone | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
if test "$_16bit" = auto ; then
_16bit=yes
else
@@ -2882,6 +2881,20 @@ case $_backend in
esac
#
+# Enable Event Recorder only for backends that support it
+#
+case $_backend in
+ sdl)
+ if test "$_eventrec" = auto ; then
+ _eventrec=yes
+ fi
+ ;;
+ *)
+ _eventrec=no
+ ;;
+esac
+
+#
# Disable savegame timestamp support for backends which don't have a reliable real time clock
#
case $_backend in
@@ -3461,6 +3474,52 @@ define_in_config_if_yes "$_zlib" 'USE_ZLIB'
echo "$_zlib"
#
+# Check for LibMPEG2
+#
+echocheck "libmpeg2 >= 0.4.0"
+if test "$_mpeg2" = auto ; then
+ _mpeg2=no
+ cat > $TMPC << EOF
+typedef signed $type_1_byte int8_t;
+typedef signed $type_2_byte int16_t;
+typedef signed $type_4_byte int32_t;
+
+typedef unsigned $type_1_byte uint8_t;
+typedef unsigned $type_2_byte uint16_t;
+typedef unsigned $type_4_byte uint32_t;
+
+extern "C" {
+#include <mpeg2dec/mpeg2.h>
+}
+
+int main(void) {
+ #if MPEG2_RELEASE < MPEG2_VERSION(0, 4, 0)
+ #error libmpeg2 version too low
+ #endif
+
+ /* mpeg2_state_t first appears in 0.4.0 */
+ mpeg2_state_t state;
+
+ return 0;
+}
+EOF
+
+ if test -n "$_host"; then
+ # don't execute while cross compiling
+ cc_check $MPEG2_CFLAGS $MPEG2_LIBS -lmpeg2 && _mpeg2=yes
+ else
+ cc_check_no_clean $MPEG2_CFLAGS $MPEG2_LIBS -lmpeg2 && $TMPO$HOSTEXEEXT && _mpeg2=yes
+ cc_check_clean
+ fi
+fi
+if test "$_mpeg2" = yes ; then
+ INCLUDES="$INCLUDES $MPEG2_CFLAGS"
+ LIBS="$LIBS $MPEG2_LIBS -lmpeg2"
+fi
+define_in_config_if_yes "$_mpeg2" 'USE_MPEG2'
+echo "$_mpeg2"
+
+#
# Check for Sparkle if updates support is enabled
#
echocheck "Sparkle"
@@ -3563,8 +3622,8 @@ if test "$_libunity" = auto ; then
;;
*)
# Unity has a lots of dependencies, update the libs and cflags var with them
- LIBUNITY_LIBS="$LIBUNITY_LIBS $(pkg-config --libs unity = 3.8.4 2>> "$TMPLOG")"
- LIBUNITY_CFLAGS="$LIBUNITY_CFLAGS $(pkg-config --cflags unity = 3.8.4 2>> "$TMPLOG")"
+ LIBUNITY_LIBS="$LIBUNITY_LIBS `pkg-config --libs unity = 3.8.4 2>> "$TMPLOG"`"
+ LIBUNITY_CFLAGS="$LIBUNITY_CFLAGS `pkg-config --cflags unity = 3.8.4 2>> "$TMPLOG"`"
_libunity=no
cat > $TMPC << EOF
#include <unity.h>
@@ -3721,7 +3780,7 @@ EOF
fi
case $_host_os in
- bada)
+ tizen)
# components live in non-standard locations so just assume sane SDK
_opengl=yes
_opengles=yes
@@ -3797,10 +3856,21 @@ fi
define_in_config_if_yes $_nasm 'USE_NASM'
#
-# Enable vkeybd / keymapper
+# Enable vkeybd / keymapper / event recorder
#
define_in_config_if_yes $_vkeybd 'ENABLE_VKEYBD'
define_in_config_if_yes $_keymapper 'ENABLE_KEYMAPPER'
+define_in_config_if_yes $_eventrec 'ENABLE_EVENTRECORDER'
+
+#
+# Check if the keymapper and the event recorder are enabled simultaneously
+#
+if test "$_keymapper" = yes ; then
+ if test "$_eventrec" = yes ; then
+ echo "ERROR: The keymapper and the event recorder cannot be enabled simultaneously currently, please disable one of the two"
+ exit 1
+ fi
+fi
# Check whether to build translation support
#
@@ -3879,7 +3949,14 @@ fi
test "x$prefix" = xNONE && prefix=/usr/local
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-DEFINES="$DEFINES -DDATA_PATH=\\\"$datadir\\\""
+case $_host_os in
+ mingw*)
+ # Windows stores all the external data files in executable file.
+ ;;
+ *)
+ DEFINES="$DEFINES -DDATA_PATH=\\\"$datadir\\\""
+ ;;
+esac
case $_backend in
openpandora)
@@ -3946,7 +4023,11 @@ if test "$_vkeybd" = yes ; then
fi
if test "$_keymapper" = yes ; then
- echo ", keymapper"
+ echo_n ", keymapper"
+fi
+
+if test "$_eventrec" = yes ; then
+ echo ", event recorder"
else
echo
fi
diff --git a/devtools/README b/devtools/README
index c7f08d6dfa..482c24edc2 100644
--- a/devtools/README
+++ b/devtools/README
@@ -63,6 +63,13 @@ create_lure (dreammaster)
the lure.dat file.
+create_mort (Strangerke)
+-----------
+ Gathers several information found in the original DOS executable:
+ - Font data
+ - French, German and fan-made English translation
+
+
create_project (LordHoto, Littleboy)
--------------
Creates project files for Visual Studio 2005, 2008, 2010, 2012, Xcode and
diff --git a/devtools/create_kyradat/create_kyradat.cpp b/devtools/create_kyradat/create_kyradat.cpp
index ca809e0aac..01cde620e7 100644
--- a/devtools/create_kyradat/create_kyradat.cpp
+++ b/devtools/create_kyradat/create_kyradat.cpp
@@ -2350,8 +2350,10 @@ bool createIDMap(PAKFile &out, const ExtractInformation *eI, const int *needList
for (const int *id = needList; *id != -1; ++id) {
WRITE_BE_UINT16(dst, *id); dst += 2;
const ExtractFilename *fDesc = getFilenameDesc(*id);
- if (!fDesc)
+ if (!fDesc) {
+ delete[] map;
return false;
+ }
*dst++ = getTypeID(fDesc->type);
WRITE_BE_UINT32(dst, getFilename(eI, *id)); dst += 4;
}
@@ -2359,15 +2361,18 @@ bool createIDMap(PAKFile &out, const ExtractInformation *eI, const int *needList
char filename[12];
if (!getFilename(filename, eI, 0)) {
fprintf(stderr, "ERROR: Could not create ID map for game\n");
+ delete[] map;
return false;
}
out.removeFile(filename);
if (!out.addFile(filename, map, mapSize)) {
fprintf(stderr, "ERROR: Could not add ID map \"%s\" to kyra.dat\n", filename);
+ delete[] map;
return false;
}
+ delete[] map;
return true;
}
diff --git a/devtools/create_kyradat/pak.cpp b/devtools/create_kyradat/pak.cpp
index 0203285a8f..0d085f563c 100644
--- a/devtools/create_kyradat/pak.cpp
+++ b/devtools/create_kyradat/pak.cpp
@@ -142,6 +142,7 @@ bool PAKFile::outputAllFiles() {
printf("OK\n");
} else {
printf("FAILED\n");
+ fclose(file);
return false;
}
fclose(file);
@@ -168,6 +169,7 @@ bool PAKFile::outputFileAs(const char *f, const char *fn) {
printf("OK\n");
} else {
printf("FAILED\n");
+ fclose(file);
return false;
}
fclose(file);
diff --git a/devtools/create_lure/process_actions.cpp b/devtools/create_lure/process_actions.cpp
index db965730cb..d1ddbf03f2 100644
--- a/devtools/create_lure/process_actions.cpp
+++ b/devtools/create_lure/process_actions.cpp
@@ -149,6 +149,7 @@ uint16 process_action_sequence_entry(int supportIndex, byte *data, uint16 remain
if (startOffset == 0x7328) { startOffset = 0x72ae; maxOffset = 0x7382; }
if (startOffset == 0x702f) { startOffset = 0x6f3d; maxOffset = 0x70a3; }
if (startOffset == 0x7886) { startOffset = 0x742a; maxOffset = 0x7896; }
+ break;
case DE_DEU:
if (startOffset == 0x7edb) { startOffset = 0x7ead; maxOffset = 0x7f05; }
if (startOffset == 0x7ab8) { startOffset = 0x796c; maxOffset = 0x7ae2; }
diff --git a/devtools/create_mortdat/create_mortdat.cpp b/devtools/create_mortdat/create_mortdat.cpp
new file mode 100644
index 0000000000..653a0754eb
--- /dev/null
+++ b/devtools/create_mortdat/create_mortdat.cpp
@@ -0,0 +1,225 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This is a utility for extracting needed resource data from different language
+ * version of the Lure of the Temptress lure.exe executable files into a new file
+ * lure.dat - this file is required for the ScummVM Lure of the Temptress module
+ * to work properly
+ */
+
+// 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common/endian.h"
+#include "create_mortdat.h"
+#include "enginetext.h"
+#include "gametext.h"
+
+
+bool File::open(const char *filename, AccessMode mode) {
+ f = fopen(filename, (mode == kFileReadMode) ? "rb" : "wb");
+ return (f != NULL);
+}
+
+void File::close() {
+ fclose(f);
+ f = NULL;
+}
+
+int File::seek(int32 offset, int whence) {
+ return fseek(f, offset, whence);
+}
+
+long File::read(void *buffer, int len) {
+ return fread(buffer, 1, len, f);
+}
+void File::write(const void *buffer, int len) {
+ fwrite(buffer, 1, len, f);
+}
+
+byte File::readByte() {
+ byte v;
+ read(&v, sizeof(byte));
+ return v;
+}
+
+uint16 File::readWord() {
+ uint16 v;
+ read(&v, sizeof(uint16));
+ return FROM_LE_16(v);
+}
+
+uint32 File::readLong() {
+ uint32 v;
+ read(&v, sizeof(uint32));
+ return FROM_LE_32(v);
+}
+
+void File::writeByte(byte v) {
+ write(&v, sizeof(byte));
+}
+
+void File::writeWord(uint16 v) {
+ uint16 vTemp = TO_LE_16(v);
+ write(&vTemp, sizeof(uint16));
+}
+
+void File::writeLong(uint32 v) {
+ uint32 vTemp = TO_LE_32(v);
+ write(&vTemp, sizeof(uint32));
+}
+
+void File::writeString(const char *s) {
+ write(s, strlen(s) + 1);
+}
+
+uint32 File::pos() {
+ return ftell(f);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void openOutputFile(const char *outFilename) {
+ outputFile.open(outFilename, kFileWriteMode);
+
+ // Write header
+ outputFile.write("MORT", 4);
+ outputFile.writeByte(VERSION_MAJOR);
+ outputFile.writeByte(VERSION_MINOR);
+}
+
+/**
+ * Write out the data for the font
+ */
+void writeFontBlock() {
+ const int knownAddr[3] = {0x30cd, 0x36b0, 0x36c0};
+ byte checkBuffer[7];
+ byte fontBuffer[121 * 6];
+
+ // Move to just prior the font data and verify that we're reading the known mort.com
+ for (int i = 0; i <= 3; ++i) {
+ if ( i == 3) {
+ printf("Invalid mort.com input file");
+ exit(0);
+ }
+
+ mortCom.seek(knownAddr[i]);
+ mortCom.read(checkBuffer, 7);
+
+ if ((checkBuffer[0] == 0x59) && (checkBuffer[1] == 0x5B) && (checkBuffer[2] == 0x58) ||
+ (checkBuffer[3] == 0xC3) && (checkBuffer[4] == 0xE8) && (checkBuffer[5] == 0xD6) ||
+ (checkBuffer[6] == 0x02)) {
+ break;
+ }
+ }
+
+ // Read in the data
+ mortCom.read(fontBuffer, 121 * 6);
+
+ // Write out a section header to the output file and the font data
+ const char fontHeader[4] = { 'F', 'O', 'N', 'T' };
+ outputFile.write(fontHeader, 4); // Section Id
+ outputFile.writeWord(121 * 6); // Section size
+
+ outputFile.write(fontBuffer, 121 * 6);
+}
+
+void writeStaticStrings(const char **strings, DataType dataType, int languageId) {
+ // Write out a section header
+ const char sStaticStrings[4] = { 'S', 'S', 'T', 'R' };
+ const char sGameStrings[4] = { 'G', 'S', 'T', 'R' };
+
+ if (dataType == kStaticStrings)
+ outputFile.write(sStaticStrings, 4);
+ else if (dataType == kGameStrings)
+ outputFile.write(sGameStrings, 4);
+
+ // Figure out the block size
+ int blockSize = 1;
+ const char **s = &strings[0];
+ while (*s) {
+ blockSize += strlen(*s) + 1;
+ ++s;
+ }
+
+ outputFile.writeWord(blockSize);
+
+ // Write out a byte indicating the language for this block
+ outputFile.writeByte(languageId);
+
+ // Write out each of the strings
+ s = &strings[0];
+ while (*s) {
+ outputFile.writeString(*s);
+ ++s;
+ }
+}
+
+/**
+ * Write out the strings previously hard-coded into the engine
+ */
+void writeEngineStrings() {
+ writeStaticStrings(engineDataEn, kStaticStrings, 1);
+ writeStaticStrings(engineDataFr, kStaticStrings, 0);
+ writeStaticStrings(engineDataDe, kStaticStrings, 2);
+}
+
+/**
+ * Write out the strings used in the game
+ */
+void writeGameStrings() {
+ writeStaticStrings(gameDataEn, kGameStrings, 1);
+ writeStaticStrings(gameDataFr, kGameStrings, 0);
+ writeStaticStrings(gameDataDe, kGameStrings, 2);
+}
+
+void process() {
+ writeFontBlock();
+ writeGameStrings();
+ writeEngineStrings();
+}
+
+/**
+ * Main method
+ */
+int main(int argc, char *argv[]) {
+ if (argc != 2) {
+ printf("Usage:\n%s input_filename\nWhere input_filename is the name of the Mortevielle DOS executable.\n", argv[0]);
+ exit(0);
+ }
+
+ mortCom.open(argv[1], kFileReadMode);
+ openOutputFile(MORT_DAT);
+
+ process();
+
+ mortCom.close();
+ outputFile.close();
+}
diff --git a/devtools/create_mortdat/create_mortdat.h b/devtools/create_mortdat/create_mortdat.h
new file mode 100644
index 0000000000..8c210d32d9
--- /dev/null
+++ b/devtools/create_mortdat/create_mortdat.h
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This is a utility for extracting needed resource data from different language
+ * version of the Mortevielle executable files into a new file mort.dat - this
+ * is required for the ScummVM Mortevielle module to work properly
+ */
+
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 0
+
+enum AccessMode {
+ kFileReadMode = 1,
+ kFileWriteMode = 2
+};
+
+enum DataType {
+ kStaticStrings = 0,
+ kGameStrings = 1,
+ kEncryptionArrays = 2
+};
+
+#define MORT_DAT "mort.dat"
+
+class File {
+private:
+ FILE *f;
+public:
+ bool open(const char *filename, AccessMode mode = kFileReadMode);
+ void close();
+ int seek(int32 offset, int whence = SEEK_SET);
+ uint32 pos();
+ long read(void *buffer, int len);
+ void write(const void *buffer, int len);
+
+ byte readByte();
+ uint16 readWord();
+ uint32 readLong();
+ void writeByte(byte v);
+ void writeWord(uint16 v);
+ void writeLong(uint32 v);
+ void writeString(const char *s);
+};
+
+File outputFile, mortCom;
+
diff --git a/devtools/create_mortdat/enginetext.h b/devtools/create_mortdat/enginetext.h
new file mode 100644
index 0000000000..e1c40f898b
--- /dev/null
+++ b/devtools/create_mortdat/enginetext.h
@@ -0,0 +1,189 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This is a utility for extracting needed resource data from different language
+ * version of the Mortevielle executable files into a new file mort.dat - this
+ * is required for the ScummVM Mortevielle module to work properly
+ */
+
+#ifndef ENGINEDATA_H
+#define ENGINEDATA_H
+
+const char *engineDataEn[] = {
+ "[2][ ][YES][NO]",
+ "Go to",
+ "Someone enters, looks surprised, but says nothing",
+ " Cool ",
+ "Oppressive",
+ " Tense ",
+ "Idem",
+ "You",
+ "are",
+ "Alone",
+
+ "Gosh! You hear some noise...",
+ " | You should have noticed, | ",
+ "% of hints...",
+ "Do you want to wake up?",
+ "OK",
+ "",
+ " Save",
+
+ " Load",
+ " Restart",
+ "F3: Repeat",
+ "F8: Proceed",
+ "Hide self",
+ "take",
+ " probe ",
+ " raise ",
+ " -MORE- ",
+ " -STOP- ",
+ "[1] [So, use the DEP menu] [Ok]",
+ "lift",
+ "read",
+
+ "look",
+ "search",
+ "open",
+ "put",
+ "turn",
+ "tie",
+ "close",
+ "hit",
+ "pose",
+ "smash",
+
+ "smell",
+ "scratch",
+ "probe",
+ "[1] [ | Before, use the DEP menu...] [Ok]",
+ "& day",
+ NULL
+};
+
+const char *engineDataFr[] = {
+ "[2][ ][OUI][NON]",
+ "aller",
+ "quelqu'un entre, parait \202tonn\202 mais ne dit rien",
+ "Cool",
+ " Lourde ",
+ "Malsaine",
+ "Idem",
+ "Vous",
+ "\210tes",
+ "SEUL",
+
+ "Mince! Vous entendez du bruit...",
+ " | Vous devriez avoir remarqu\202| ",
+ "% des indices...",
+ "D\202sirez-vous vous r\202veiller?",
+ "OK",
+ "",
+ " Sauvegarde",
+
+ " Chargement",
+ " Recommence ",
+ "F3: Encore",
+ "F8: Suite",
+ "se cacher",
+
+ "prendre",
+ "sonder",
+ "soulever",
+ " -SUITE- ",
+ " -STOP- ",
+ "[1][Alors, utilisez le menu DEP...][ok]",
+ "soulever",
+ "lire",
+
+ "regarder",
+ "fouiller",
+ "ouvrir",
+ "mettre",
+ "tourner",
+ "attacher",
+ "fermer",
+ "frapper",
+ "poser",
+ "d\202foncer",
+
+ "sentir",
+ "gratter",
+ "sonder",
+ "[1][ | Avant, utilisez le menu DEP...][ok]",
+ "& jour",
+ NULL
+};
+
+const char *engineDataDe[] = {
+ "[2][ ][JA][NEIN]",
+ "gehen",
+ "Jemand kommt herein, scheint erstaunt, sagt nichts",
+ "Cool",
+ "Schwer",
+ "Ungesund",
+ "Idem",
+ "Sie",
+ "sind",
+ "allein",
+
+ "Verdammt! Sie hoeren ein Geraeush...",
+ "Sie haetten ",
+ "% der Hinweise| bemerken muessen...",
+ "Moechten Sie aufwachen?",
+ "OK",
+ "",
+ " schreiben",
+
+ " lesen",
+ " wieder ",
+ "F3: nochmals",
+ "F8: stop",
+ " sich verstecken",
+ " nehmen",
+ " sondieren",
+ " hochheben",
+ " -WEITER- ",
+ " -STOP- ",
+ "[1][ Benutzen Sie jetzt das Menue DEP...][OK]",
+ "hochheben",
+ "lesen",
+
+ "anschauen",
+ "durchsuchen",
+ "oeffnen",
+ "setzen",
+ "drehen",
+ "befestigen",
+ "schliessen",
+ "klopfen",
+ "hinlegen",
+ "eindruecken",
+
+ "fuehlen",
+ "abkratzen",
+ "sondieren",
+ "[1][ Benutzen Sie jetzt das Menue DEP...][OK]",
+ "& tag",
+ NULL
+};
+
+#endif
diff --git a/devtools/create_mortdat/gametext.h b/devtools/create_mortdat/gametext.h
new file mode 100644
index 0000000000..9a4f0f7fc5
--- /dev/null
+++ b/devtools/create_mortdat/gametext.h
@@ -0,0 +1,1794 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This is a utility for extracting needed resource data from different language
+ * version of the Mortevielle executable files into a new file mort.dat - this
+ * is required for the ScummVM Mortevielle module to work properly
+ */
+
+#ifndef GAMEDATA_H
+#define GAMEDATA_H
+
+const char *gameDataEn[] = {
+ "Calm within the storm$",
+ "Discussed in colours$",
+ "Your mauve!$",
+ "Be kind enough to leave the room...$",
+ "If you're NOT overdrawn...$",
+ "If you're feeling blue...$",
+ "Read what's on the walls?$",
+ "Water sports$",
+ "Room for envy?$",
+ "A glance at the forbidden$",
+ "Smell of a woodfire and tobacco$",
+ "Tobacco and old books$",
+ "Onions, cinnamon and spirits$",
+ "A place seldom visited$",
+ "Humidity and decay$",
+ "Sorry, no ""door to door""$",
+ "Rotting corpse: deady cryptomania$",
+ "And what's more, there are disused traps$",
+ "It's already open$",
+ "Danger: avalanches$",
+ "Proper Charlie's place?$",
+ "An imposing building$",
+ "The other side of the mystery$",
+ "Strange horoscope$",
+ "Look out... but she wishes well?$",
+ "An oak door$",
+ "A photograph$",
+ "The coat of arms$",
+ "$",
+ "Max, the servant, welcomes you and shows you to your room$",
+ "Mortville 6/2/51@ My dear Jerome@Regarding my telegram, I must tell you the reason for my wor-@ries. A year ago, Murielle, my lady companion, disappeared. The de@part may have had something to do@with the financial success of themanor, or... A silence hard to un@derstand for my son Guy. Not ha@ving been able to see the light of day over this affair, I count @on you to sort things out. If my state of health doesn't improve, @take the decisions that you feel @are apropriate.@ Kind regards, Julia DEFRANCK$",
+ "Later, Guy will inform you of Leo's suicide after a@heavy bet at the races$",
+ "F3: AGAIN F8: STOP$",
+ "The master of the premises$",
+ "The future heir$",
+ "JULIA's son$",
+ "A pretty picture$",
+ "Superman!$",
+ "Ida's husband$",
+ "Interesting remarks?$",
+ "Service included!$",
+ "Nothing underneath$",
+ "You could hear a pin drop$",
+ "Half an hour passes: nothing! Wait any longer?$",
+ "Admire! Contemplate!$",
+ "No! Nothing!$",
+ "Impossible$",
+ "That stains!$",
+ "A treatise on the history of the area$",
+ "A few coins...$",
+ "First commandment...$",
+ "Pleasing to the nostrils!$",
+ "Spades, Hearts...$",
+ "Just a spoonful of sugar...$",
+ "A romantic novel$",
+ "Worth more than a penny, (whistle)$",
+ "Just needs a little patience$",
+ "Watch the sharp bends$",
+ "Deep and dark$",
+ "Normal sensations$",
+ "Sniff!$",
+ "Not discreet! Be content to watch!$",
+ "Bless you! Dusty!$",
+ "The canvas is signed, the wallpaper is not!$",
+ "Nothing, Unlucky!$",
+ "Be more discreet!$",
+ "The shutters are closed$",
+ "Snow! And more snow!$",
+ "Brilliant! The work of a master!$",
+ "No doubt at all! A genuine fake!$",
+ "Hmm! A cheap reproduction!$",
+ "A rare and valuable piece$",
+ "Nothing special$",
+ "Linen, personal belongings...$",
+ "Not just anywhere!$",
+ "It's not time!$",
+ "One doesn't speak with ones mouth full! So once the meal is over...$",
+ "Someone comes in, messes about then goes out again$",
+ "Someone's approaching your hiding-place$",
+ "Someone surprises you!$",
+ "Impossible! You're too loaded!$",
+ "Try again!$",
+ "Still puzzled!?$",
+ "You leave Mortville.In Paris a message awaits you...$",
+ "You hurt yourself$",
+ "Nothing more here$",
+ "The sound seems normal$",
+ "It doesn't move$",
+ "You are answered$",
+ "Not the right moment!$",
+ "The same matter, from another angle!$",
+ "The reflection is tarnished, but the frame is gold!$",
+ "Bric-a-brac$",
+ "Facing failure!$",
+ "Smells like something you'd rather not see!$",
+ "Cleaning products$",
+ "Got an itch?$",
+ "It's stuck, frozen. Brrr!$",
+ "All the locks are jammed!$",
+ "Papers$",
+ "No! Father christmas hasn't got himself stuck!$",
+ "It leads onto a corridor$",
+ "China, silverware...$",
+ "No! It's not Julia's remains!$",
+ "An old engraving$",
+ "You find a deep diamond-shaped opening$",
+ "The wall slides open! A passage! Do you follow it?$",
+ "The passageway closes$",
+ "A secret drawer: a notebook! Do you read it?$",
+ "The drawer shuts$",
+ "Nothing! Flesh and blood stuck to the stone$",
+ "Certain details lead you to believe death was not immediate!$",
+ "A rotten affair!$",
+ "Did she cling to dear life with just one finger?$",
+ "Has the treasure packed its trunk?$",
+ "A slot the size of a coin$",
+ "Part of the stone wall pivots.A crypt! Do you enter?$",
+ "The ring turns, the wall closes$",
+ "A stone column behind the altar$",
+ "There is a noise!$",
+ "Occupied!$",
+ "Take another chance?$",
+ "Too deep!$",
+ "The cellar wall pivots$",
+ "Nothing$",
+ "The one and only!$",
+ "The object slides to the bottom$",
+ "You have nothing in hand$",
+ "It is not open$",
+ "There is already something$",
+ "The door is locked$",
+ "No reply$",
+ "A solid wooden ball$",
+ "There's no more space$",
+ "A wooden ball pierced through the side$",
+ "? ?$",
+ "Your move$",
+ "OK !$",
+ "Suddenly Max arrives with your suitcase: \"Thank you for your @visit!\".Mister discreet \"private eye\" (in need of a private optici@an!). Thoroughly demoralised, you@leave the manor. You are useless!$",
+ "Leo interrupts: \"The storm has died down,I am going into town in@1 hour. Get ready\". You have lost@time...but not your life$",
+ "Congestion, the deadly flu... You@are stuck here! Your whole case@sinks slowly beneath the water$",
+ "The water is rising fast, freezing your last illusions. Before you@have time to react...you are dead$",
+ "As soon as you reach the bottom of the well, a hand cuts the rope@Farewell sweet life!$",
+ "The storm covers your footprints.A wall of silence falls heavily@on your shoulders. Slowly you succumb to frosbite...$",
+ "You're not completely alone! A cold blade plunges into your back@In future, be more careful!$",
+ "You don't know what implication Leo may have had in Murielle's@death. Was she dead outright? In@any case, the family problems that you have uncovered in the course@of your enquiries would explain Leo's behaviour. You're not sure@that's the reason Julia had asked@for your help, but that's reason enough for you!Out of respect for@her, after taking certain precau-@tions you have a revealing talk with Leo.$",
+ "$",
+ "You don't have the keys to the manor. Your cries rest unheard@You're going to catch... your death!$",
+ "With a circular movement, the sword slices across you. Guts and@intestines spill out all over. A sorry state of affairs!$",
+ "Home, Sweet home !$",
+ "The mystery behind a closed door$",
+ "Bewitching charm of these old rooms$",
+ "An empty stomach$",
+ "Closer to heaven? Not so sure$",
+ "Afraid of the dark?$",
+ "Old rugs and a glint of gold$",
+ "Anguish!$",
+ "Safe? Perhaps not!$",
+ "A little ill at ease, eh!?$",
+ "Always further$",
+ "Your way of the cross!$",
+ "On the trail of...$",
+ "Watch what's hiding$",
+ "The road down to hell$",
+ "Feeling well? You look a little pale$",
+ "What lurks behind...?$",
+ "Close-up on:$",
+ "You notice, amongst other things$",
+ "And...$",
+ "That's all!$",
+ "A bit of reading$",
+ "The adventure awaits, you set off!$",
+ "Don't mess up YOUR next ADVENTURE!$",
+ "I don't understand$",
+ "There is an easier way$",
+ "No, not just now$",
+ "Too late$",
+ "$",
+ "Like a deep stony stare, a solitary eye that points towards the@stars; the artery that links hea-ven and hell. You must fathom@these depths keeping hold of that@which is, and will become. Monday, Tuesday, Wednesday, Sunday, from@the first Monday to the first Sunday,plunging from one day to the next your@\"IS\" or \"WILL BECOME\". Carrying your burden with love and light,@the smallest oversight will seal your fate.$",
+ "10/1/51: We think we've solved the mystery of the manuscript and@located the crypt. Is it the idea@of success in what seems like a dream that disturbs me so? I feel@I have committed myself rather too much, as far as Leo is @concerned... No! I mustgo on. @I should have put Guy in the picture but for a week now, I've had@no news of him$",
+ "Take your prayers as you would to the holy place. From the pillar@of wisdom, bring the sun to his@knees. Thus will it show you the place to offer alms of another@kind and like young Arthur, open the way of darkness.White is your@colour, golden your hearth. So@advance with caution Orpheus and light your way unto the sad@virgin. Offer her the circle of the man with three faces. That he@may regain the world and turn with it to its original@inglory!$",
+ "The mountains are the fangs in a monstrous mouth opening on the@finity of a celestial orgy, grin-ding the stars as we grind our@teeth into dust. You will drop your chord of stone at your feet.@The laugh of silence at the@highest pitch, and in your right hand, the measure of genius. Thus@will you pass between the two crescents beyond the abyss of the@wall of silence. The key to the melody is within your grasp. It@suffices to find the note that clashes.$",
+ " 9/12 INTER. 518 3/13 EXPENS. 23@ 9/12 SALES 1203 7/12 CHEQUE 1598@ TOTAL 1721 TOTAL 1721$",
+ " 5/1/51@@ Luc, my love@ Guy knows about us. After an argument I told him everything! I@think only of you. Max keeps pes-tering me, but it's finished with @him. He should stick to his pots and pans! When can you and I be alone together? For you I would@get a divorce.@I love you.@ Eva$",
+ " Mortville, 10/2/51@@ Pat@ I recall you owe me 50000 frs that I lent you for your business@I need that money, can you repay me quickly?@ Guy$",
+ " Mortville, 15/2/51@ Dear Sir@ I am writing to you on the sub-ject of our business deal. I have@decided to go all the way in the certainty that my partner, Pat@DEFRANCK, has been forging the accounts. @In spite of$",
+ " A pipe$",
+ " A pen$",
+ " A lighter$",
+ " A retort$",
+ " A shaving brush$",
+ " A tin of paint$",
+ " A flute$",
+ " An expensive ring$",
+ " A reel of thread$",
+ " An old book$",
+ " A wallet$",
+ " A dagger$",
+ " A pistol$",
+ " A bible$",
+ " A candle$",
+ " A jewellery box$",
+ " An iron$",
+ " A photo$",
+ " A pocket watch$",
+ " A rope$",
+ " Keys$",
+ " A pearl necklace$",
+ " A bottle of perfume$",
+ " Binoculars$",
+ " Glasses$",
+ " A leather purse$",
+ " A tennis ball$",
+ " Ammunition$",
+ " A cut-throat razor$",
+ " A hairbrush$",
+ " A clothes brush$",
+ " A pack of cards$",
+ " A shoe horn$",
+ " A screwdriver$",
+ " A hammer$",
+ " Keys$",
+ " Keys$",
+ " An ashtray$",
+ " A paintbrush$",
+ " A rope$",
+ " A wooden object$",
+ " Sleeping pills$",
+ " A gold ring$",
+ " A jewellery box$",
+ " An alarm clock$",
+ " A coat of armour$",
+ " A candlestick$",
+ " A pair of gloves$",
+ " A engraved goblet$",
+ " A parchment$",
+ " A dagger$",
+ " A dossier$",
+ " A parchment$",
+ " A parchment$",
+ " A dossier$",
+ " A dossier$",
+ " A letter$",
+ " A novel$",
+ " A wooden rod$",
+ " An envelope$",
+ " A letter$",
+ " An envelope$",
+ "Julia$",
+ "Julia's death$",
+ "Julia's relationships$",
+ "A message from Julia$",
+ "Julia's inheritance$",
+ "Julia's final actions$",
+ "Julia's gifts$",
+ "Julia's bedroom$",
+ "The photo at Julia's home$",
+ "Julia and yourself...$",
+ "L\202o's occupations$",
+ "Pat's occupations$",
+ "Guy's occupations$",
+ "Bob's occupations$",
+ "Eva's occupations$",
+ "Luc's occupations$",
+ "Ida's occupations$",
+ "Max's occupations$",
+ "Your occupations$",
+ "L\202o's relationships$",
+ "Pat's relationships$",
+ "Guy's relationships$",
+ "Bob's relationships$",
+ "Eva's relationships$",
+ "Luc's relationships$",
+ "Ida's relationships$",
+ "Max's relationships$",
+ "Your relationships$",
+ "Murielle$",
+ "Murielle's relationships$",
+ "Murielle and yourself...$",
+ "Murielle's disappearance$",
+ "The wall of silence$",
+ "The manuscripts$",
+ "The coat of arms$",
+ "Engravings in the cellar$",
+ "The well$",
+ "The secret passages$",
+ "The chapel$",
+ "The paintings$",
+ "The photo of the attic$",
+ "The body in the crypt$",
+ "$",
+ "$",
+ "END OF THE CONVERSATION$",
+ "That was the name old people gave to the mountain range that lies at the foot of the manor!$",
+ "These are the mountains one can see in front of the manor$",
+ "I don't know!$",
+ "She died from pulmonary embolism$",
+ "Mother died suddenly. And yet her health had seemed to improve\202$",
+ "Miss DEFRANCK died from a cold$",
+ "She died from pulmonary embolism$",
+ "Excuse me but I prefer to say nothing for now$",
+ "Only the good die young$",
+ "I loved my mother . My only regret is that she died in the DEFRANCK's manor$",
+ "That region has a lot of history and there is plenty to keep me busy. And also I love horses..$",
+ "He is a history enthusiast and a gambler. By the way he won a large sum one year ago$",
+ "He is already very busy with the management and maintenance of the mansion...$",
+ "I am the CEO of a small perfume company. But when I am here, I rest$",
+ "He is a dynamic man who has succeeded in perfurmes$",
+ "Him! He is an upstart rogue! Perfumes must have killed his common sense. Moreover, when he's here he spends his evenings in his room$",
+ "I was very concerned about my mother's health, and now I don't feel like doing anything at all$",
+ "He would have done better to look after me a bit more and a bit less after his mother$",
+ "(313) It is his business...$",
+ "He does not have much luck at the moment although his business is satisfactory$",
+ "I work with Pat but it's not going too well at the moment$",
+ "Oh really?! He has activities? He better take care of them seriously then$",
+ "Him and Pat are patners. I think it's going pretty well$",
+ "I take care of myself and that's already lots. How about you?$",
+ "(319) Oh that! I trust her. She knows how to keep herself busy$",
+ "(320) What! You have not yet discovered her main occupation..?$",
+ "She is working in the decoration business, and tastefully with that. She is always very well dressed$",
+ "If you like jewels, I have some good deals to propose for a short while$",
+ "The jewels...$",
+ "I don't know, but I'd like him to give me a bit more slack!$",
+ "When one is a housewife, one always find something to do...$",
+ "She could stay there doing nothing, but no! She sews, she reads...$",
+ "She has probably not very fulfilling occupations...$",
+ "A woman like there is no more: She is interested in everything!$",
+ "With the cooking and the cleaning I do not have much time for you$",
+ "I do not know how he manages to do everything. That's wonderful!",
+ "He would do more if he showed less interest in gossip and alcohol$",
+ "I am very independant. As long as nobody interferes in my business: No problem$",
+ "He is selfish. I wonder if he likes something other than his horses and grimoires$",
+ "I think he gets along well with everyone, except, perhaps, with Guy$",
+ "He has a temper. You have to learn how to deal with him...$",
+ "Business is business. As for the family, I leave it as it is...$",
+ "Relations? Friendly relations? Financial relations, without a doubt$",
+ "Oh I don't have anything against him$",
+ "He is a resourceful businessman. He sometimes tries to swim upstream but... he will always find a way to make it work$",
+ "(340) They all bore me... No! Not even that... Even if... some people...$",
+ "Contrary to his mother, he is a very shy person ! So when you say relations...$",
+ "He must be trying very hard to remain nice despite all his troubles$",
+ "(343) His romantic relationship: it's over. His relationship with me: hasn't really started. As for the other ones: I don't follow the \"other ones\"$",
+ "I like everyone, as long as they are not trying to screw me over$",
+ "It is not enough to have a bit of money and to know how to talk for everyone to like you$",
+ "Not much to say about him... He is a nice and generous man. And what's more, he can be quite funny$",
+ "Nowadays I get along rather well with everyone. But, here, I am not going to say more about this$",
+ "(348) Nice feathers, but a bird's brain... Ask her husband$",
+ "Is it for an appointment?$",
+ "(350) She is very lively! She does not burden herself with stupids prejudices$",
+ "In my line of work, one mostly encounters beautiful women and gangsters$",
+ "The only sure thing he has going for him, it's his jewelery... And his wife, but he doesn't realize that$",
+ "It's an interesting character. Who is not always very easy to follow, but worth knowing$",
+ "I hate no one, but I like things and people when they stay where they should be$",
+ "This stays between us. But you see: when I speak with her, I soon start to feel a bit uncomfortable!$",
+ "You'd have to try hard to not get along with her$",
+ "You know, in my line of work you hear everything but don't remember anything, and service is well done$",
+ "He's a submissive hypocrite! Personally I don't trust him$",
+ "I don't know what he thinks deep down inside, but he's always polite and impeccable$",
+ "Someone who lived in the manor, a year ago... maybe more$",
+ "She was more than a friend to my mother. In these moments, I would have loved to have her by my side$",
+ "Murielle has been Julia's lady-in-waiting$",
+ "She, too, was doing some research....$",
+ "She was a very educated person. Her abrupt leaving, a year ago, surprised me and caused me great sorrow$",
+ "Her and Leo shared a common passion for history and the local area$",
+ "I think everyone liked her$",
+ "She got along with everyone. She loved her son dearly. As for the relations between mother-in-law and daughter-in-law...$",
+ "Apart from Leo, she got along very well with Max...$",
+ "Even if your relations were unfrequent, Jerome, there was still a place for you in her heart...$",
+ "Apart from her family, not a lot of people$",
+ "Oh right! I think she deeply regretted this friend's leaving... err! Marielle... or Mireille...$",
+ "No, nothing!$",
+ "No... Not that I know of$",
+ "I met Julia when buying the manor. It was the only thing she owned. But all my wealth was hers...$",
+ "Apart from a few personal belongings, I think she didn't own anything anymore$",
+ "I think all her fortune came from Leo. So, pfft!$",
+ "(377) Apart from the letter for you I posted, nothing very important!$",
+ "I was very happy she gave me her bound bible as a present$",
+ "It happened fast and she didn't have time to make any particular will$",
+ "Her last gift suprised me$",
+ "Which gift?$",
+ "A chandelier...$",
+ "Yes, I got a present. My wife even got a bible$",
+ "Well yes! Like everyone, I believe$",
+ "A dagger$",
+ "I have never been looking around in the attic!$",
+ "(387) You either can read the past or pick a door$",
+ "The portrait of a young girl: it's Murielle...$",
+ "You know, I didn't know her that well$",
+ "She was very charming, but above all she was Julia's lady-in-waiting$",
+ "She was the only truly interesting woman I've met$",
+ "She had a great knowledge in history, and you learned a great deal when you asked her about it$",
+ "(393) I've always wondered why some people fancied her!$",
+ "If the room is closed, ask Leo$",
+ "(395) I closed her door after her death and I'd like it to remain this way for a while$",
+ "You know how it is: family relations$",
+ "All those years, I've never regretted serving her$",
+ "I loved her as much as she loved me, I think$",
+ "What made you think you could enter my wife's room?!!$",
+ "It must be the picture of Murielle with Julia's godson$",
+ "I don't remember$",
+ "This is Murielle. I took that picture, and actually they developed it backwards$",
+ "You sure are curious!... It's not worth anything$",
+ "(404) Grimoires, parchment and manuscripts: it is Leo's realm$",
+ "Too bad the motto doesn't appear here...$",
+ "This is beautiful... And very old...$",
+ "Hey! That's a place I've never visited$",
+ "According to Leo, it seems that the Moons are more recent$",
+ "Even under this weather, you managed to find a sun...$",
+ "Profound and disturbing: Progress is good$",
+ "For me, it remains the biggest of all mysteries$",
+ "The last days she was talking about a trip. And then...$",
+ "A little over a year ago, one night, she decided to leave...$",
+ "In any case, she wasn't meant to live here$",
+ "What?! Whose body? Which crypt?$",
+ "If there are any, I have never found them...$",
+ "Of course! And ghosts too...$",
+ "It's the oldest in the area: it is from the 11th century$",
+ "It was slightly renovated after the French Revolution$",
+ "Julia loved paintings$",
+ "They are different in styles, but not all of them are worth a lot$",
+ "What are you doing h-$",
+ "I'm sure you are looking for something in here$",
+ "I'm listening$",
+ "What do you want?$",
+ "Yes?$",
+ "I'm all yours...$",
+ "What's the matter?$",
+ "Go ahead$",
+ "What is it about?$",
+ "Max: at your service, sir$",
+ "In any case you have no business being in here! Get out!!$",
+ "You are too curious!$",
+ "Jerome! It's been a while... I'm very sad to announce you that Julia died. Her family is here: Guy, her son; Eva, her daughter-in-law; Leo, her husband, of course; her son-in-law Pat; cousins, too: Bob, Ida, Luc. The storm is getting stronger, you must stay here. Meals are served at 12am and 7pm, and there is a mass at the chapel every day at 10am$",
+ "When I saw you I knew you would uncover the truth... I knew why you were here: I had found the draft of Julia's letter. But I love to play, so... She hadn't wanted your task to be too easy, to protect me, probably, but she couldn't die knowing this mystery would remain unsolved. Did you find out that the wall of silence is the name the builders gave, during the construction of the manor, to the wall on which the coat of arms hangs?... And those gifts Julia left before dying were as many false leads, and their true purpose was to highlight how important the parchments were... That's right, more than a year ago I was working with Murielle on the decryption of those manuscripts I had just found. My wife made the connection between our work and Murielle's disappearance, but she never had any proof. Except that ring she found one day while going through my belongings. One night, we went exploring the secret passage we had found. Murielle died by accident in the room of the Virgin. I quickly took the ring from her, found the treasure and ran away. I didn't think she was still alive, and I didn't say a word because I needed the money. I told everyone the money was coming from a winning bet at the horseraces... Leave now, since you're not a policeman. Leave me alone!$",
+ "February 1951... Occupation: private eye. The cold was freezing Paris off, and my cases as well, when...$",
+ "A letter, a call, memories from a childhood not that long ago. Echoes of the many games we played in the disused rooms of Mortville Manor... And Julia, now an old woman.$",
+ " to the office$",
+ " to the kitchen$",
+ " to the cellar$",
+ " to the landing$",
+ " outside$",
+ " to the dining room$",
+ " inside the manor$",
+ " front of the manor$",
+ " to the chapel$",
+ " to the well$",
+ " north$",
+ " behind the manor$",
+ " south$",
+ " east$",
+ " west$",
+ " towards the manor$",
+ " further$",
+ " in the water$",
+ " out of the well$",
+ " in the well$",
+ " choice on screen$",
+ "In the MYSTERY series...$",
+ "MORTVILLE MANOR$",
+ "$",
+ "From an original idea of...$",
+ "Bernard GRELAUD and Bruno GOURIER$",
+ "$",
+ "Directed by: KYILKHOR CREATION and LANGLOIS$",
+ "$",
+ "With the cooperation of...$",
+ "B\202atrice et Jean_Luc LANGLOIS$",
+ "for the music and the voices,$",
+ "Bernard GRELAUD for the graphic conception,$",
+ "MARIA-DOLORES for the graphic direction,$",
+ "Bruno GOURIER for the technical direction,$",
+ "Mick ANDON for the translation. $",
+ "$",
+ "Publisher: KYILKHOR and B&JL LANGLOIS $",
+ "COPYRIGHT 1987: KYILKHOR and B&JL LANGLOIS$",
+ "$",
+ "YOUR MOVE$",
+ " attach$",
+ " wait$",
+ " force$",
+ " sleep$",
+ " listen$",
+ " enter$",
+ " close$",
+ " search$",
+ " knock$",
+ " scratch$",
+ " read$",
+ " eat$",
+ " place$",
+ " open$",
+ " take$",
+ " look$",
+ " smell$",
+ " sound$",
+ " leave$",
+ " lift$",
+ " turn$",
+ " hide yourself$",
+ " search$",
+ " read$",
+ " put$",
+ " look$",
+ " Leo$",
+ " Pat$",
+ " Guy$",
+ " Eva$",
+ " Bob$",
+ " Luc$",
+ " Ida$",
+ " Max$",
+ "JULIA...$",
+ "- Did she commit suicide?$",
+ "- Was she murdered?$",
+ "- Did she die by accident?$",
+ "- Did she die of natural causes?$",
+ "Where did the money used for the@restoration of the manor come from?$",
+ "- Blackmail$",
+ "- Honest work$",
+ "- Inheritance$",
+ "- Races$",
+ "- Rents$",
+ "- Hold-up$",
+ "- Other$",
+ "What is Leo's hobby?$",
+ "- Historical research$",
+ "- Politics$",
+ "- Painting$",
+ "- Drugs$",
+ "- Occult sciences$",
+ "- Leader of a sect$",
+ "Julia left several clues that are@represented in one place. Which one?$",
+ "- Chapel$",
+ "- Outside$",
+ "- Cellar$",
+ "- Attic$",
+ "- Kitchen$",
+ "- Dining room$",
+ "- Julia's room$",
+ "- Leo's room$",
+ "- Pat's room$",
+ "- Bob's room$",
+ "- Max's room$",
+ "- Luc/Ida's room$",
+ "- Guy/Eva's room$",
+ "The main clue that lead you@to the underground door is:$",
+ "- A dagger$",
+ "- A ring$",
+ "- A book$",
+ "- A parchment$",
+ "- A letter$",
+ "- A pendulum$",
+ "How many parchments were there in the manor?$",
+ "- None$",
+ "- Just one$",
+ "- Two$",
+ "- Three$",
+ "- Four$",
+ "- Five$",
+ "How many persons are involved in@this story?@(including Julia, but not yourself)$",
+ "- Nine$",
+ "- Ten$",
+ "- Eleven$",
+ "What was the first name@of the unknown character?$",
+ "- Mireille$",
+ "- Fran\207oise$",
+ "- Maguy$",
+ "- Emilie$",
+ "- Murielle$",
+ "- Sophie$",
+ "Who did Murielle have an affair with?$",
+ "- Bob$",
+ "- Luc$",
+ "- Guy$",
+ "- Leo$",
+ "- Max$",
+ "Murielle shared an occupation@with one other person. Who?$",
+ "[1][You realize that certain elements of|this investigation remain a mystery for you.|Therefore, you decide first to learn|more before undertaking new risks..][ok]$",
+ "[3][ | insert disk 1 | in drive A ][ok]$",
+ "[1][ | Disk error | All stop... ][ok]$",
+ "[1][ | You should have noticed |00% of the clues ][ok]$",
+ "[3][ | insert disk 2 | in drive A ][ok]$",
+ "[1][ |Before going any further, you decide to| look back on the knowledge you gained][ok]$",
+ "TBT - MASTER .$",
+ "TBT - rorL$",
+ NULL
+};
+
+const char *gameDataFr[] = {
+ "Le calme dans la tourmente$",
+ "Des go\227ts et des couleurs!$",
+ "Mauve qui peut!$",
+ "Pri\212re de laisser en sortant...$",
+ "Trou noir troublant$",
+ "Bleu... comme \"peur bleue\"!$",
+ "Chambre de \"Saigneur\"!$",
+ "Histoire d'eaux$",
+ "Vert nid$",
+ "Coup d'oeil sur l'interdit$",
+ "Odeur de feux de bois et de tabac$",
+ "Tabac et vieux bouquins$",
+ "Oignons, cannelle et spiritueux$",
+ "Un endroit bien peu visit\202$",
+ "Humidit\202 et moisissure$",
+ "Avis aux colporteurs...$",
+ "Corps putr\202fi\202 : cryptomanie mortelle!$",
+ "Et en plus... des pi\212ges d\202samorc\202s!$",
+ "C'est d\202j\205 ouvert$",
+ "Danger : avalanches$",
+ "Une odeur de saintet\202!$",
+ "Une b\203tisse imposante$",
+ "L'envers du myst\212re!$",
+ "Dr\223le d'horoscope!$",
+ "Tant va la cruche...$",
+ "Une porte en ch\212ne$",
+ "Une photo$",
+ "Les armoiries$",
+ "$",
+ "Max, le domestique, vous accueille puis vous conduit \205 votre chambre$",
+ "Mortevielle, le 16/2/51@ Mon cher J\202r\223me,@ Suite \205 mon t\202l\202gramme, je vous fais part des raisons de mon inqui\202tude :il y a un an, Murielle, ma dame de compagnie, disparaissait . D\202part ayant rapport avec le renouveau financier du Manoir, ou... Silence difficile \205 comprendre, surtout pour mon fils Guy . N'ayant pu jusqu'\205 pr\202sent, faire le jour sur cette affaire, je compte sur vous pour la mener \205 bien . Si mon \202tat de sant\202 ne s'am\202liorait pas, prenez les d\202cisions qui vous sembleront le plus appropri\202es...@ Amiti\202s. JULIA DEFRANCK$",
+ "Plus tard, Guy vous apprendra le suicide de L\202o... apr\212s un pari insens\202 aux courses!$",
+ "F3: encore@F8: suite$",
+ "Le ma\214tre des lieux$",
+ "Le futur h\202ritier$",
+ "Le fils de JULIA$",
+ "Joli brin!!!$",
+ "Superman!$",
+ "Le mari d'Ida$",
+ "Propos int\202ressants?$",
+ "Service compris...$",
+ "Rien dessous!$",
+ "Un ange passe...$",
+ "Une 1/2 h passe: rien! Attendez-vous encore?$",
+ "Admirez! Contemplez!$",
+ "Non ! Rien !$",
+ "Impossible$",
+ "\207a tache !$",
+ "Un trait\202 sur l'histoire de la r\202gion$",
+ "Quelques pi\212ces$",
+ "Premier commandement...$",
+ "Des p\202tales plein les narines !$",
+ "Pique, Coeur...$",
+ "\207a ne manque pas de cachets !$",
+ "Un roman d'amour$",
+ "Souffler n'est pas jouer$",
+ "Pas une r\202ussite!$",
+ "Gare aux rebondissements !$",
+ "Sombre et profond...$",
+ "Sensations normales$",
+ "Sniff!$",
+ "Pas discret ! Contentez-vous de regarder !$",
+ "Atchoum! De la p... poussi\212re$",
+ "La toile est sign\202e... pas le papier peint !$",
+ "Pas de chance, rien !$",
+ "Soyez plus discret !$",
+ "Les volets sont clos$",
+ "De la neige, encore de la neige !$",
+ "G\202nial : une toile de ma\214tre !$",
+ "Aucun doute : une v\202ritable imitation$",
+ "Hum ! Vous tiquez : de l'antique en toc !$",
+ "Une pi\212ce rare de valeur !$",
+ "Rien de remarquable$",
+ "Linge, objets personnels...$",
+ "Pas n'importe o\227 !$",
+ "Ce n'est pas l'heure !$",
+ "On ne parle pas la bouche pleine ! Donc, une fois le repas termin\202...$",
+ "Quelqu'un entre, s'affaire, ressort...$",
+ "On s'approche de votre cachette !$",
+ "On vous surprend !$",
+ "Non : vous \210tes trop charg\202 !$",
+ "Essayez de nouveau$",
+ "Vous restez perplexe !?$",
+ "Vous quittez le Manoir. A Paris, un message vous attend...$",
+ "A\213e, a\213e, a\213e !$",
+ "Rien de plus$",
+ "Le son para\214t normal$",
+ "Ca ne bouge pas$",
+ "On vous r\202pond$",
+ "Pas le moment !$",
+ "M\210me mati\212re, autre face !$",
+ "Le reflet est piqu\202, mais le cadre est d'or$",
+ "Bibelots, babioles...$",
+ "Vous essuyez un \202chec !$",
+ "Il est des odeurs... qu'il vaut mieux ne pas voir !$",
+ "Des produits m\202nagers$",
+ "\207a vous d\202mange ?$",
+ "C'est coinc\202, gel\202 ! Brrrr...$",
+ "Les huisseries sont bloqu\202es !$",
+ "Des papiers...$",
+ "Non ! Le p\212re No\210l n'est pas coinc\202 !$",
+ "\207a donne sur un couloir$",
+ "Vaisselle, argenterie...$",
+ "Non ! Ce ne sont pas les restes de Julia !$",
+ "Une gravure ancienne$",
+ "Il y a une profonde ouverture en losange$",
+ "Le mur coulisse... Un passage ! L'empruntez-vous ?$",
+ "Le passage se ferme$",
+ "Un tiroir secret... Un livret ! Le lisez-vous ?$",
+ "Le tiroir se referme$",
+ "Rien ! Sang et chairs collent \205 la pierre !$",
+ "Des d\202tails vous font supposer que... la mort ne fut pas imm\202diate !$",
+ "Des projets v\202reux ?$",
+ "Sa vie n'aurait-elle tenu qu'\205 un doigt ?$",
+ "Un tr\202sor se serait-il fait la malle ?$",
+ "Une fente de la taille d'une pi\212ce !$",
+ "Quelques pierres pivotent... Une crypte ! Y p\202n\202trez-vous ?$",
+ "La bague tourne, le mur se referme...$",
+ "Une colonne de pierres derri\212re l'autel$",
+ "Il y a du bruit...$",
+ "Occup\202 !$",
+ "Retentez-vous votre chance ?$",
+ "Trop profond !$",
+ "Le mur de la cave pivote$",
+ "Nothing !$",
+ "L'unique !$",
+ "L'objet glisse au fond...$",
+ "Vous n'avez rien en main$",
+ "Ce n'est pas ouvert$",
+ "Il y a d\202j\205 quelque chose$",
+ "La porte est ferm\202e$",
+ "Pas de r\202ponse$",
+ "Une boule de bois pleine$",
+ "Il n'y a plus de place$",
+ "Une boule de bois perc\202e par le travers$",
+ "? ?$",
+ "A vous de jouer$",
+ "OK !$",
+ "Soudain Max survient avec votre valise : \"Merci de votre visite ! D\202tective \"priv\202\"... de bon sens et de discr\202tion sans doute\" . D\202\207u d\202moralis\202, vous quittez le manoir@Vous \212tes NUL !$",
+ "L\202o vous interrompt : \"la temp\212te est calm\202e. Je pars en ville dans 1 heure. Tenez-vous pr\210t!\"... Bon... Vous avez perdu du temps... mais pas la vie$",
+ "Congestion, grippe fatale : vous y restez ! Votre enqu\212te tombe \205 l'eau$",
+ "L'eau monte tr\212s vite et refroidit vos derni\212res illusions... Avant que vous n'ayez eu le temps de r\202agir, vous \212tes mort!$",
+ "A peine \212tes-vous au fond du puits qu'une main tranche la corde... Adieu la vie!$",
+ "La temp\212te recouvre vos traces . Un mur de silence s'abat sur vos \202paules . Lentement vous succombez \205 la morsure du froid !$",
+ "Pas si seul que \207a ! Une lame glac\202e s'enfonce dans votre dos. A l'avenir, soyez plus prudent!$",
+ "Vous ignorez la responsabilit\202 exacte de L\202o dans la mort de Murielle... Est-elle morte sur le coup ? De toutes fa\207ons les probl\212mes familiaux d\202couverts lors de votre enqu\212te justifient l'attitude de L\202o... Vous n'\212tes pas s\227r que Julia vous ait appel\202 pour \207a mais c'est suffisant pour vous ! Par respect pour elle, et apr\212s certaines pr\202cautions, vous avez une entrevue r\202v\202latrice avec L\202o$",
+ "$",
+ "Vous n'avez pas les clefs du Manoir . Vos appels restent sans r\202ponse . Vous allez attraper... la mort !$",
+ "D'un mouvement circulaire, l'\202p\202e vous fend par le travers : tripes et boyaux \205 l'air, bonjour les vers!$",
+ "Home, Sweet home !$",
+ "Myst\212re d'une porte close$",
+ "Charme envo\227tant de vieilles pi\212ces$",
+ "La faim au ventre$",
+ "Plus pr\212s du ciel? Pas s\227r !$",
+ "Peur du noir?$",
+ "Vieux tapis et reflets d'or$",
+ "Angoisse !$",
+ "Sauv\202 ? Pas certain !$",
+ "Mal \205 l'aise, hein !$",
+ "Toujours plus loin !$",
+ "Votre chemin de croix !$",
+ "A la d\202couverte de...$",
+ "Attention \205 ce que cache...$",
+ "Une descente aux Enfers !$",
+ "Si ce n'est pas dans vos cordes :@ ne soyez pas sot!$",
+ "Avant la mise en pi\212ce !$",
+ "Gros plan sur :$",
+ "Vous remarquez particuli\212rement...$",
+ "Et encore...$",
+ "C'est fini !$",
+ "Un peu de lecture$",
+ "L'aventure vous attend, vous partez...$",
+ "Ne ratez pas VOTRE prochaine AVENTURE...$",
+ "Je ne comprends pas$",
+ "Il y a plus simple$",
+ "Non ! Pas ce coup-ci$",
+ "Trop tard$",
+ "$",
+ "Comme un regard profond tout couvert de peaux-pierres, pointant son oeil obscur aux astres de lumi\212re, il est la gorge reliant le ciel et les enfers . Il faut aller au fond de cette art\212re comme un rat au coeur m\210me de la terre !@Lundi, Mardi, Mercredi, Dimanche du 1e lundi au 1e dimanche, tu installeras \"ce rat\" entre chacun des jours . N'omets rien car ta venue serait ta retenue !@Porte ton fardeau comme un oeuf nouveau et donne lui le jour avec force et amour.$",
+ "10/1/50: Nous avons r\202solu le myst\212re du manuscrit et localis\202 la crypte . Est-ce l'id\202e d'aboutir dans ce qui n'\202tait qu'un \"r\212ve\" qui me rend si anxieuse ?@Je regrette de m'\210tre engag\202e vis \205 vis de L\202o . Non! je dois continuer ! J'aurais d\227 mettre Guy au courant... mais, depuis une semaine, je n'ai aucune nouvelle .$",
+ "Porte ta pri\212re au lieu saint qui se doit, changes-en l'air, tu auras la mati\212re !@Du pilier de la haute sagesse, le soleil aux genoux te montrera l'espace par lequel ton \205me s'ouvrira un chemin et gagnera son \212re . Avance comme un Orph\202e peu soucieux des t\202n\212bres : le blanc est ta couleur, l'or ta demeure . Eclaire ton chemin jusqu'\205 la myst\202rieuse . Offre-lui le cercle de l'homme aux trois facettes . Qu'il regagne le monde et qu'il tourne avec lui dans la richesse premi\212re.$",
+ "Les montagnes sont les crocs d'une gueule dantesque ouverte \205 l'infini de quelqu' orgie c\202leste, mastiquant des \202toiles comme nous broyons du noir .@Tu d\202poseras l'accord de pierre \205 tes pieds, le rire du silence sur la gamme d'en haut et dans ta main droite, une toile d'un m\212tre . Tu passeras ainsi entre les deux croissants, par del\205 les ab\214mes du Mur du Silence . La Cl\202 des champs est \205 ta port\202e, tu n'as qu'\205 retrouver la note qui d\202note.$",
+ " DECEMBRE@ 9 REMISE 518 13 AGIOS 23@ 19 VIREMENT 1203 17 TRESOR 1598@ TOTAL 1721 TOTAL 1721$",
+ " Le 5/01/51@@ Luc, mon amour@ Guy conna\214t notre liaison . A la suite d'une dispute, je lui ai tout dit . Je ne pense qu'\205 toi ! Max me relance mais j'ai d\202finitivement rompu avec lui . Qu'il reste \205 ses gamelles . Quand pourrons-nous nous voir seuls ? Pour toi je divorcerai... Je t'aime .@ ton Eva$",
+ " Mortevielle, le 10/2/51@@ Pat,@ Je te rappelle que tu me dois 50000 F que je t'ai pr\202t\202s pour ton affaire . J'en ai besoin, peux-tu me les rendre assez vite?@ Guy$",
+ " Mortevielle, le 15/2/51@ Ma\214tre,@ Je vous \202cris au sujet de notre affaire. Je suis d\202cid\202 \205 aller jusqu'au bout, certain que mon associ\202, Pat DEFRANCK, a falsifi\202 un livre de comptes . Malgr\202$",
+ " Une pipe$",
+ " Un stylo \205 plume$",
+ " Un briquet \205 essence$",
+ " Une cornue$",
+ " Un blaireau$",
+ " Un pot de peinture$",
+ " Une flute$",
+ " Une bague de valeur$",
+ " Une bobine de fil$",
+ " Un vieux bouquin$",
+ " Un porte-monnaie$",
+ " Un poignard$",
+ " Un r\202volver$",
+ " Une bible$",
+ " Une bougie$",
+ " Un coffret \205 bijoux$",
+ " Un fer \205 repasser$",
+ " Une photo$",
+ " Une montre \205 gousset$",
+ " Une corde$",
+ " Des clefs$",
+ " Un collier de perles$",
+ " Un flacon de parfum$",
+ " Des jumelles$",
+ " Des lunettes$",
+ " Une bourse en cuir$",
+ " Une balle de tennis$",
+ " Des munitions$",
+ " Un rasoir \205 main$",
+ " Une brosse \205 cheveux$",
+ " Une brosse \205 linge$",
+ " Un jeu de cartes$",
+ " Un chausse pied$",
+ " Un tournevis$",
+ " Un marteau$",
+ " Des clefs$",
+ " Des clefs$",
+ " Un cendrier$",
+ " Un pinceau$",
+ " Une corde$",
+ " Un objet en bois$",
+ " Des somnif\212res$",
+ " Une bague en or$",
+ " Un coffret \205 bijoux$",
+ " Un r\202veil matin$",
+ " Une cotte de mailles$",
+ " Un chandellier$",
+ " Une paire de gants$",
+ " Une coupe cisel\202e$",
+ " Un parchemin$",
+ " Un poignard$",
+ " Un dossier$",
+ " Un parchemin$",
+ " Un parchemin$",
+ " Un dossier$",
+ " Un dossier$",
+ " Une lettre$",
+ " Un roman$",
+ " Une baguette en bois$",
+ " Une enveloppe$",
+ " Une lettre$",
+ " Une enveloppe$",
+ "Julia$",
+ "La mort de Julia$",
+ "Les relations de Julia$",
+ "Un message de Julia$",
+ "L'h\202ritage de Julia$",
+ "Derniers actes de Julia$",
+ "Les cadeaux de Julia$",
+ "La chambre de Julia$",
+ "La photo chez Julia$",
+ "Julia et vous...$",
+ "Les occupations de L\202o$",
+ "Les occupations de Pat$",
+ "Les occupations de Guy$",
+ "Les occupations de Bob$",
+ "Les occupations d'Eva$",
+ "Les occupations de Luc$",
+ "Les occupations d'Ida$",
+ "Les occupations de Max$",
+ "Vos occupations$",
+ "Les relations de L\202o$",
+ "Les relations de Pat$",
+ "Les relations de Guy$",
+ "Les relations de Bob$",
+ "Les relations d'Eva$",
+ "Les relations de Luc$",
+ "Les relations d'Ida$",
+ "Les relations de Max$",
+ "Vos relations$",
+ "Murielle$",
+ "Les relations de Murielle$",
+ "Murielle et vous...$",
+ "Disparition de Murielle$",
+ "Le mur du silence$",
+ "Les manuscrits$",
+ "Le blason$",
+ "Les gravures dans la cave$",
+ "Le puits$",
+ "Les passages secrets$",
+ "La chapelle$",
+ "Les tableaux$",
+ "La photo du grenier$",
+ "Le corps dans la crypte$",
+ "$",
+ "$",
+ "FIN DE LA CONVERSATION$",
+ "Les vieux appelaient ainsi la chaine de montagne qui se dresse au pied du manoir !$",
+ "C'est le massif montagneux que l'on aper\207oit devant le manoir$",
+ "Je n'en sais rien !$",
+ "Elle est morte d'une embolie pulmonaire$",
+ "Ma m\202re est morte soudainement . Son \202tat semblait pourtant s'\210tre am\202lior\202$",
+ "Madame DEFRANCK est morte d'un coup de froid$",
+ "Elle est morte d'une embolie pulmonaire$",
+ "Pardonnez moi mais je pr\202f\212re, actuellement garder le silence$",
+ "Ce sont toujours les meilleurs qui partent les premiers$",
+ "J'aimais beaucoup ma m\212re . Je regrette seulement qu'elle soit morte dans le manoir des DEFRANCK$",
+ "C'est une r\202gion qui a un pass\202 charg\202 et j'ai largement de quoi m'occuper . Et puis j'aime beaucoup les chevaux..$",
+ "C'est un passionn\202 d'histoire et un joueur inv\202t\202r\202 . D'ailleurs, voici un an il a gagn\202 une grosse somme$",
+ "Il a d\202j\205 beaucoup a faire avec la gestion et l'entretien du manoir...$",
+ "Je suis PDG d'une petite soci\202t\202 de parfums . Mais quand je suis ici, je me repose$",
+ "C'est un homme dynamique qui a r\202ussi dans le parfum$",
+ "Lui ! C'est un arriviste v\202reux ! Les parfums ont du endormir son bon sens . D'ailleurs ici il passe ses soir\202es dans sa chambre$",
+ "J'ai \202t\202 tr\212s pr\202occup\202 par la sant\202 de ma m\212re, et maintenant je n'ai plus go\226t \205 rien$",
+ "Il aurait mieux fait de s'occuper un peu plus de moi et un peu moins de sa m\212re$",
+ "Ce sont ses affaires...$",
+ "Il n'a pas trop de chance en ce moment bien que ses affaires soient satisfaisantes$",
+ "Je travaille avec Pat mais \207a ne va pas tr\212s fort en ce moment$",
+ "Ah oui ?! Il a des occupations ? Il ferait bien de s'en occuper s\202rieusement alors$",
+ "Lui et Pat sont associ\202s . Je crois que \207a ne va pas trop mal$",
+ "Je m'occupe de moi et c'est d\202j\205 beaucoup . Et vous ?$",
+ "Oh \207a ! Je lui fais confiance . Elle sait s'occuper$",
+ "Mais ! Vous n'avez pas encore d\202couvert son occupation principale..?$",
+ "Elle fait dans la d\202coration avec beaucoup dego\226t d'ailleurs. Elle est toujours tr\212s bien habill\202e$",
+ "Si les bijoux vous interessent, j'ai quelques affaires interessantes \205 saisir rapidement$",
+ "Les bijoux...$",
+ "Je ne sais pas, mais j'aimerais bien qu'il s'occupe un peu moins de mes affaires !$",
+ "Quand on est une femme d'int\202rieur on trouve toujours de quoi s'occuper...$",
+ "Elle pourrait rester sans rien faire, mais non ! Elle coud, elle lit ...$",
+ "Elle n'a s\226rement pas des occupations tr\212s \202panouissantes ...$",
+ "Une femme comme il n'y en a plus : Elle s'interesse a tout !$",
+ "Entre la cuisine et le m\202nage, je n'ai pas beaucoup de temps \205 vous accorder$",
+ "Je ne sais pas comment il s'y prend pour tout faire . C'est merveilleux !$",
+ "Il en ferait plus si il s'occupait moins des rag\223ts et de la bouteille$",
+ "Je suis tr\212s ind\202pendant . Tant qu'on ne s'occupe pas de mes affaires : Pas de probl\212me$",
+ "C'est un \202go\213ste . Je me demande si il aime autre chose que ses chevaux et ses grimoires$",
+ "Je crois qu'il s'entend bien avec tout le monde, mis \205 part, peut \210tre, avec Guy$",
+ "C'est un homme de caract\212re . Il faut savoir le prendre ..$",
+ "Les affaires sont les affaires . Quant \205 la famille, je la laisse pour ce qu'elle est ...$",
+ "Relations ? Relations amicales ? Relations financi\212res sans doute$",
+ "Moi je n'ai rien \205 lui reprocher$",
+ "C'est un homme d'affaire d\202brouillard . Il nage parfois \205 contre-courant mais ... il s'en sortira toujours$",
+ "Ils m'ennuient tous .. Non ! Ce n'est m\210me pas \207a .. Quoique .. certains ..$",
+ "A l'inverse de sa m\212re, c'est une personne tr\212s renferm\202e ! Alors question relations ..$",
+ "Il doit sans doute faire beaucoup d'effort pour rester agr\202able malgr\202 tous ses ennuis$",
+ "Ses relations amoureuses : C'est termin\202 . Ses relations avec moi : Pas vraiment commenc\202es . Quant aux autres : Je ne suis pas les \"autres\"$",
+ "J'aime bien tout le monde, tant qu'on ne m'escroque pas$",
+ "Il ne suffit pas d'avoir un peu d'argent et d'\210tre beau parleur pour plaire \205 tout le monde$",
+ "Sans histoire .. C'est quelqu'un d'agr\202able et g\202n\202reux . De plus, il ne manque pas d'humour$",
+ "Actuellement je m'entends plut\223t bien avec tout le monde . Mais, ici, je ne vais pas m'\202tendre sur le sujet$",
+ "Beau plumage, mais \207a ne vole pas haut ... Parlez en \205 son mari$",
+ "C'est pour un rendez-vous ?$",
+ "Elle est tr\212s vivante ! Elle ne s'embarrasse pas de pr\202jug\202s stupides$",
+ "Dans mon m\202tier, on c\223toit surtout des belles femmes et des truands$",
+ "La seule valeur s\226re chez lui, c'est ses bijoux .. Et sa femme, mais \207a il ne s'en rend pas compte$",
+ "C'est quelqu'un d'interessant . De pas toujours facile \205 comprendre, mais qui m\202rite le d\202tour$",
+ "Je ne d\202teste personne, mais j'aime les choses et les gens quand ils sont \205 leur place$",
+ "C'est entre nous . Mais voyez : quand je parle avec elle, je me sens vite \205 l'\202troit !$",
+ "Pour ne pas s'entendre avec elle, faut y mettre de la mauvaise volont\202$",
+ "Vous savez dans mon m\202tier on entend tout mais on ne retient rien, et le service est bien fait$",
+ "C'est un hypocrite, un larbin ! Personnellement je ne lui fais pas confiance$",
+ "Je ne connait pas le fond de sa pens\202e mais c'est quelqu'un de toujours tr\212s correct et impeccable$",
+ "C'\202tait une personne qui a v\202cu au manoir, il y a un an .. peut \210tre plus$",
+ "C'\202tait plus qu'une amie pour ma m\212re . En ces moments, j'aurais aim\202 qu'elle soit \205 mes cot\202s$",
+ "Murielle a \202t\202 la dame de compagnie de Julia$",
+ "Elle aussi, faisait des recherches ...$",
+ "C'\202tait une femme tr\212s cultiv\202e . Son brusque d\202part, il y a un an, m'a surpris et beaucoup chagrin\202$",
+ "Elle partageait avec L\202o sa passion de l'histoire et de la r\202gion$",
+ "Je crois que tout le monde l'aimait bien$",
+ "Elle s'entendait bien avec tout le monde . Elle aimait beaucoup son fils . Quant aux relations belle-m\212re, belle-fille ..$",
+ "A part L\202o, elle avait de tr\212s bon rapport avec Max ...$",
+ "Bien que vos relations furent peu soutenues, J\202r\223me, elle vous portait toujours dans son coeur ...$",
+ "A part sa famille, pas grand monde$",
+ "Ah oui ! Je crois qu'elle a beaucoup regrett\202 le d\202part de cette amie .. euh ! Marielle .. ou Mireille ...$",
+ "Non rien !$",
+ "Non ... Pas que le sache$",
+ "J'ai connu Julia en achetant le manoir . C'\202tait son seul bien . Mais toute ma fortune \202tait la sienne ...$",
+ "Si ce n'est quelques objets personnels, je crois qu'elle n'avait plus rien \205 elle$",
+ "Je crois que toute sa fortune venait de L\202o . Alors, Pfuuut !$",
+ "A part la lettre pour vous que j'ai post\202, rien de bien important !$",
+ "J'ai \202t\202 tr\212s heureuse qu'elle m'offre sa bible reli\202e$",
+ "Ca a \202t\202 rapide et elle n'a pas eu le temps de prendre des dispositions particuli\212res$",
+ "Son dernier pr\202sent m'a surpris$",
+ "Quel cadeau ?$",
+ "Un chandellier ...$",
+ "Oui, j'ai eu un cadeau . Ma femme a m\210me eu une bible$",
+ "Et bien oui ! Comme tout le monde, je crois$",
+ "Un poignard$",
+ "Je n'ai jamais \202t\202 fouiller dans le grenier !$",
+ "Vous avez un don de double-vue ou un passe-partout$",
+ "Le portrait d'une jeune fille : C'est Murielle ...$",
+ "Vous savez, je la connaissais assez peu$",
+ "Elle \202tait tr\212s charmante, mais c'\202tait surtout la dame de compagnie de Julia$",
+ "C'est la seule femme vraiment interessante que j'ai rencontr\202$",
+ "Elle avait de grandes connaissances historiques, et la consulter \202tait tr\212s enrichissant$",
+ "Je me suis toujours demand\202 ce que certains pouvaient lui trouver !$",
+ "Si la chambre est ferm\202e, demandez \205 L\202o$",
+ "J'ai ferm\202 sa chambre apr\212s sa mort et j'aimerais qu'il en soit ainsi encore un certain temps$",
+ "Vous savez ce que c'est : Des relations familiales$",
+ "Durant toutes ces ann\202es, je ne l'ai jamais servie \205 contre-coeur$",
+ "Je l'aimais autant qu'elle m'aimais, je crois$",
+ "De quel droit avez-vous p\202n\202tr\202 dans la chambre de ma femme ?!!$",
+ "C'est sans doute la photo de Murielle avec le filleul de Julia$",
+ "Je ne me rappelle pas$",
+ "C'est Murielle . C'est moi qui l'ai prise. et d'ailleurs elle est tir\202e \205 l'envers$",
+ "Vous \210tes bien curieux !... C'est sans valeur$",
+ "Grimoires, parchemins et manuscrits : C'est le domaine de L\202o$",
+ "Dommage que la devise soit manquante ...$",
+ "C'est tr\212s beau ... Et tr\212s vieux ...$",
+ "Tiens ! C'est un endroit que je n'ai jamais visit\202$",
+ "D'apr\202s L\202o, il semblerait que les Lunes soient plus r\202centes$",
+ "M\210me par ce temps, vous avez d\202nich\202 un soleil ...$",
+ "Profond et inqui\202tant : Le progr\212s a du bon$",
+ "Ca reste pour moi le plus grand des myst\212res$",
+ "Les derniers temps elle parlait d'un voyage . Et puis ...$",
+ "Il y a un peu plus d'un an, un soir, elle a d\202cid\202 de partir ...$",
+ "De toutes fa\207ons elle n'\202tait pas faite pour vivre ici$",
+ "Quoi ?! Quel corps ? Quel crypte ?$",
+ "Si il y en a, je ne les ai jamais trouv\202 ...$",
+ "Bien s\226r ! ... Et des fant\223mes aussi ...$",
+ "C'est la plus vielle de la r\202gion : Elle date du XI eme si\212cle$",
+ "Elle fut l\202g\212rement restaur\202e apr\212s la r\202volution$",
+ "Julia aimait beaucoup la peinture$",
+ "Ils ont diff\202rents styles, mais n'ont pas tous une tr\212s grande valeur$",
+ "Que faites-vous l\205 ?$",
+ "Je suis s\226r que vous cherchez quelque chose ici$",
+ "Je vous \202coute$",
+ "Que d\202sirez-vous ?$",
+ "Oui ?$",
+ "Je suis \205 vous ...$",
+ "C'est pourquoi ?$",
+ "Allez-y$",
+ "C'est \205 quel sujet ?$",
+ "Max : \205 votre service, monsieur$",
+ "De toutes fa\207ons vous n'avez rien \205 faire ici ! Sortez !!$",
+ "Vous \210tes trop curieux !$",
+ "J\202r\223me ! Il y a longtemps ... Quelle tristesse, Julia est morte . Sa famille est ici : Guy, son fils . Eva, sa brue . L\202o, son mari bien s\226r . Son beau fils, Pat . Des cousins : Bob, Ida, Luc . La temp\212te redouble, il vous faut rester . Les repas sont \205 12h et 19h et il y a un recueillement \205 la chapelle tous les jours \205 10h$",
+ "En vous voyant j'ai compris que vous decouvririez la v\202rit\202 ... Car je savais pourquoi vous veniez : J'avais retrouv\202 le brouillon de la lettre de Julia . Mais je suis tr\212s joueur, alors ... Elle n'avait pas voulu que votre t\203che soit trop facile, pour me prot\202ger, sans doute, mais elle n'a pu mourir avec cette incertitude sur la conscience . Avez vous d\202couvert que le mur du silence est le nom que les ma\207ons ont donn\202 au mur qui porte ce blason, lors de la construction du manoir ? .. Et ces cadeaux que Julia a laiss\202 avant de mourir \202taient autant de faux indices qui ne servaient qu'\205 faire ressortir l'importance des parchemins ... Effectivement, il y a plus d'un an, je travailais avec Murielle au d\202cryptage de ces manuscrits que je venais de trouver . Ma femme a fait la relation entre notre travail et la disparition de Murielle mais elle n'a jamais eu de preuves . Si ce n'est cette bague qu'elle a retrouv\202 un jour dans mes affaires . Une nuit, nous nous sommes aventur\202s dans le passage secret que nous avions d\202couvert . Murielle est morte par accident dans la pi\212ce de la vierge . J'ai r\202cup\202r\202 la bague rapidement, trouv\202 le tr\202sor et me suis enfuis . Je ne pensais pas qu'elle vivait encore, et je n'ai rien dit car j'avais besoin d'argent . J'ai fait passer cette somme sur le compte des courses de chevaux ...Partez maintenant, puisque vous n'\210tes pas de la police . Laissez moi seul !$",
+ "F\202vrier 1951 ... Profession : detective priv\202 . Le froid figeait Paris et mes affaires lorsque ...$",
+ "Une lettre, un appel, des souvenirs d'une enfance encore proche . Que de jeux dans les pi\212ces d\202labr\202es du manoir de Mortevielle . Julia, une vieille femme a pr\202sent .$",
+ " au bureau$",
+ " \205 la cuisine$",
+ " \205 la cave$",
+ " dans le couloir$",
+ " dehors$",
+ " la salle \205 manger$",
+ " dans le manoir$",
+ " devant le manoir$",
+ " \205 la chapelle$",
+ " devant le puits$",
+ " au nord$",
+ " derri\212re le manoir$",
+ " au sud$",
+ " \205 l'est$",
+ " \205 l'ouest$",
+ " vers le manoir$",
+ " plus loin$",
+ " dans l'eau$",
+ " hors du puits$",
+ " dans le puits$",
+ " choix sur \202cran$",
+ " Dans la serie MYSTERE...$",
+ " LE MANOIR DE MORTEVIELLE$",
+ "$",
+ " Sur une idee de...$",
+ " Bernard GRELAUD et Bruno GOURIER$",
+ "$",
+ " Realisation: LANKHOR$",
+ "$",
+ " Avec la participation de...$",
+ " Beatrice et Jean-Luc LANGLOIS$",
+ " pour la musique et les voix,$",
+ " Bernard GRELAUD pour la conception graphique,$",
+ " MARIA-DOLORES pour la realisation graphique,$",
+ " Bruno GOURIER pour la realisation technique,$",
+ " Clement ROQUES pour l'adaptation sur IBM PC et compatibles .$",
+ "$",
+ " Edition: LANKHOR$",
+ " COPYRIGHT 1988: LANKHOR$",
+ "$",
+ " A VOUS DE JOUER$",
+ " attacher$",
+ " attendre$",
+ " d\202foncer$",
+ " dormir$",
+ " \202couter$",
+ " entrer$",
+ " fermer$",
+ " fouiller$",
+ " frapper$",
+ " gratter$",
+ " lire$",
+ " manger$",
+ " mettre$",
+ " ouvrir$",
+ " prendre$",
+ " regarder$",
+ " sentir$",
+ " sonder$",
+ " sortir$",
+ " soulever$",
+ " tourner$",
+ " se cacher$",
+ " fouiller$",
+ " lire$",
+ " poser$",
+ " regarder$",
+ " L\202o$",
+ " Pat$",
+ " Guy$",
+ " Eva$",
+ " Bob$",
+ " Luc$",
+ " Ida$",
+ " Max$",
+ "Comment Julia est-elle morte ?$",
+ "Elle s'est suicid\202e$",
+ "Elle est morte assassin\202e$",
+ "Elle est morte accidentellement$",
+ "Elle est morte naturellement$",
+ "D'o\227 provenait l'argent qui a permis la restauration du manoir ?$",
+ "chantage$",
+ "travail$",
+ "h\202ritage$",
+ "courses$",
+ "rentes$",
+ "hold-up$",
+ "d\202couverte$",
+ "Quel est le hobby de L\202o ?$",
+ "recherches historiques$",
+ "politique$",
+ "peinture$",
+ "drogue$",
+ "sciences occultes$",
+ "direction d'une secte$",
+ "Julia a laiss\202 une s\202rie d'indices . Ceux-ci sont repr\202sent\202s en un seul lieu . Lequel ?$",
+ "Chapelle$",
+ "Ext\202rieur$",
+ "Cave$",
+ "Grenier$",
+ "Cuisine$",
+ "Salle \205 manger$",
+ "Chambre Julia$",
+ "Chambre L\202o$",
+ "Chambre Pat$",
+ "Chambre Bob$",
+ "Chambre Max$",
+ "Chambre Luc/Ida$",
+ "Chambre Guy/Eva$",
+ "L'indice principal qui vous a permis d'arriver \205 la porte du souterrain est :$",
+ "Un poignard$",
+ "Une bague$",
+ "Un livre$",
+ "Un parchemin$",
+ "Une lettre$",
+ "Un pendule$",
+ "Combien y avait-il de parchemin dans le manoir ?$",
+ "Aucun$",
+ "Un seul$",
+ "Deux$",
+ "Trois$",
+ "Quatre$",
+ "Cinq$",
+ "Combien de personnes sont m\202l\202es \205 cette histoire - Julia y comprise, vous except\202 - ?$",
+ "Neuf$",
+ "Dix$",
+ "Onze$",
+ "Quel \202tait le pr\202nom de la personne inconnue ?$",
+ "Mireille$",
+ "Fran\207oise$",
+ "Maguy$",
+ "Emilie$",
+ "Murielle$",
+ "Sophie$",
+ "De qui Murielle \202tait-elle la ma\214tresse ?$",
+ "Bob$",
+ "Luc$",
+ "Guy$",
+ "L\202o$",
+ "Max$",
+ "Murielle partageait une occupation avec une autre personne . Qui ?$",
+ "[1][ |Seul le hazard vous a permis d'arriver ici . Vous pr\202f\202rez|retourner enqu\202ter afin de mieux comprendre ...][ok]$",
+ "[1][ |Ins\202rez la disquette 1 dans le lecteur A][ok]$",
+ "[1][ |! ERREUR DISQUETTE !|On arrete tout][ok]$",
+ "[1][ |Vous devriez avoir remarqu\202|00% des indices][ok]$",
+ "[1][ |Ins\202rez la disquette 2 dans le lecteur A][ok]$",
+ "[1][ |Avant d'aller plus loin, vous faites|un point sur l'\202tat de vos connaissances][ok]$",
+ " MASTER .$",
+ " rorL$",
+};
+
+const char *gameDataDe[] = {
+ "Ruhe vor dem Sturm$",
+ "Geschmacklose Farben$",
+ "Lila, der letzte Versuch$",
+ "Diesen Ort bitte sauberhalten...$",
+ "Beaengstigendes schwarzes Loch$",
+ "Der blaue Salon$",
+ "Das blutrote Zimmer$",
+ "Wassersport$",
+ "Der gruene Star$",
+ "Ein Auge aufs Verbotene werfen$",
+ "Geruch von Kaminfeuer und Tabak$",
+ "Tabak und alte Buecher$",
+ "Zwiebeln, Zimt und Spirituosen$",
+ "Ein wenig besuchter Ort$",
+ "Feuchtigkeit und Moder$",
+ "Hausieren verboten!$",
+ "Ein verwester Koerper: toedliche Kryptomanie!$",
+ "Da wird einem angst$",
+ "Es ist schon offen$",
+ "Achtung: Lawinen$",
+ "Ein Hauch von \"Heiligkeit\"$",
+ "Eine grosses eindrucksvolles Gemaeuer...$",
+ "Die Kehrseite des Geheimnisses!$",
+ "Ein merkwuerdiges Horoskop!$",
+ "Der Krug geht so lange...$",
+ "Eine Eichentuer$",
+ "Ein Foto$",
+ "Die Wappen$",
+ "$",
+ "Max, der Diener, empfaengt Sie und wird Sie dann in Ihr Zimmer begleiten$",
+ " Morteville 16/2/51@ Mein lieber Jer\223me@Im Anschluss an mein Telegramm teile ich Ihnen die Gruende meiner Unruhe mit: vor 1 Jahr verschwand meine Gesellschafterin Murielle. Eventuell hat das Verschwinden etwas mit dem finanziel len Umschwung auf dem Landsitz zu tun, oder... Eine Stille, die schwer zu verstehen ist fuer mei-nen Sohn Guy. Da ich bis heute nichts bezueglich dieser Sache unternehmen konnte, zaehle ich auf Sie, um die Affaere zu regeln. Falls sich mein Gesundheitszustand nicht bessert, treffen Sie bitte die Entscheidungen, die Sie fuer richtig halten. @ In Freundschaft. JULIA DEFRANCK$",
+ "Spaeter erzaehlt Ihnen Guy von Leo's Selbstmord nach einer verrueckten Wette beim Rennen!$",
+ "F3: WIEDERHOLUNG@F8: STOP$",
+ "Der Hausherr$",
+ "Der Zukuenftige Erbe$",
+ "Julias Sohn$",
+ "Ein niedliches Maedchen!$",
+ "Superman!$",
+ "Der Mann von Ida$",
+ "Interessante Aeusserungen?$",
+ "Service inbegriffen!$",
+ "Nichts darunter!$",
+ "Kein Mucks...$",
+ "Eine halbe Stunde spaeter: nichts! Warten Sie immer noch?$",
+ "Bewundern Sie! Denken Sie nach!$",
+ "Nein! Nichts!$",
+ "Unmoeglich$",
+ "Das macht Flecken!$",
+ "Eine Abhandlung ueber die Geschichte der Gegend$",
+ "Einige Muenzen$",
+ "Erstes Gebot...$",
+ "Das riecht gut!$",
+ "Pik, Herz...$",
+ "Es mangelt nicht an Pillen!$",
+ "Ein Liebesroman$",
+ "Pusten heisst noch nicht spielen$",
+ "Kein Erfolg!$",
+ "Vorsicht vor Ueberraschungen!$",
+ "Dunkel und tief...$",
+ "Normale Gefuehle$",
+ "Sniff!$",
+ "Unverschaemt! Begnuegen Sie sich mit anschauen!$",
+ "Gesundheit! St... Staub$",
+ "Das Bild ist unterzeichnet... aber nicht die Tapeten$",
+ "Kein Glueck, Nichts!$",
+ "Seien Sie diskreter!$",
+ "Die Vorhaenge sind geschlossen$",
+ "Schnee! Und noch mehr Schnee!$",
+ "Genial: ein Bild vom Meister!$",
+ "Kein Zweifel, das ist eine Faelschung!$",
+ "Hum! Sie stutzen - Antikes oder Schund?$",
+ "Ein selten wertvolles Stueck!$",
+ "Nichts Bemerkenswertes$",
+ "Waesche, persoenliche Objekte...$",
+ "Nicht irgendwo!$",
+ "Das ist nicht der Zeitpunkt!$",
+ "Man spricht nicht mit vollem Mund! Nenn erst einmal das essen beendet ist$",
+ "Jemand kommt rein, beeilt sich und geht wieder raus$",
+ "Man naehert sich Ihrem Versteck!$",
+ "Man ueberrascht Sie!$",
+ "Unmoeglich! Sie sind ueberlastet!$",
+ "Versuchen Sie es aufs neue$",
+ "Sie sind perplex!?$",
+ "Sie verlassen Morteville. In Paris erwartet Sie eine Nachricht...$",
+ "Sie tun sich weh!$",
+ "Nichts weiteres mehr hier$",
+ "Der Ton erscheint normal$",
+ "Es bewegt sich nicht$",
+ "Man antwortet Ihnen$",
+ "Nicht der Augenblick!$",
+ "Gleiches Material, andere Seite!$",
+ "Der Widerschein ist fleckig, aber der Rahmen ist aus Gold$",
+ "Nippsachen, wertlose Dinge...$",
+ "Sie erleiden einen Misserfolg!$",
+ "Hier stinkt es... Besser nicht anschauen!$",
+ "Haushaltsprodukte$",
+ "Da juckt Ihnen das Fell?$",
+ "Das ist esklemmt, zugefroren! Brrrr...$",
+ "Die Fensterrahmen sind blockiert!$",
+ "Papiere...$",
+ "Nein! Der Weihnachtsmann hat keine Schwierigkeiten!$",
+ "Da geht es auf einen Flur$",
+ "Geschirr, Silber...$",
+ "Nein! Das sind nicht die Reste von Julia!$",
+ "Eine alte Gravur$",
+ "Sie entdecken eine tiefe rhombenfoermige Oeffnung$",
+ "Die Mauer gleitet zur Seite! Eine Passage! Benutzen Sie sie?$",
+ "Der Durchgang schliesst sich$",
+ "Eine Geheimschublade. Ein Buechlein... Lesen Sie es?$",
+ "Die Schublade schliesst sich wieder$",
+ "Nichts! Blut und Haut kleben am Stein!$",
+ "Die Details lassen Sie darauf schliessen, dass der Tod nicht unmitte lbar eingetreten ist!$",
+ "Verdorbene Vorhaben?$",
+ "Hing ihr Leben an einem \"Finger\"?$",
+ "Ein Schatz sei verschwunden?$",
+ "Eine Ritze in Groesse einer Muenze!$",
+ "Einige Steine bewegen sich... Eine Krypta! Gehen Siehinein?$",
+ "Der Ring dreht sich, die Mauer schliesst sich wieder$",
+ "Eine Steinsaeule hinter dem Altar$",
+ "Es war laut...$",
+ "Besetzt!$",
+ "Versuchen Sie noch einmal Ihr Glueck?$",
+ "Zu tief!$",
+ "Die Mauer am Ende des Ganges dreht sich$",
+ "Nothing!$",
+ "Der einzigue!$",
+ "Das Objekt faellt hinunter...$",
+ "Sie haben nichts in den Haenden$",
+ "Es ist nicht offen$",
+ "Das ist schon etwas$",
+ "Die Tuer ist zu$",
+ "Keine Antwort$",
+ "Eine volle Holzkugel$",
+ "Es ist kein Platz mehr$",
+ "Eine, in der Mitte durchbohrte, Holzkugel$",
+ "? ?$",
+ "Sie sind dran!$",
+ "OK!$",
+ "Ploetzlich erscheint Max mit Ihrem Koffer : \"Danke fuer Ihren Besuch\" Privatdetektiv mit gutem Gespuer und zweifellos diskret. Demoralisiert verlassen Sie den Landsitz. Sie sind UNBEDEUTEND!$",
+ "Leo unterbricht Sie:\"Das Unwetterhat sich beruhigt. In 1 Stunde gehe ich in die Stadt. Halten Siesich bereit.\" Sie haben Zeit verloren...aber noch nicht das Leben$",
+ "Hochrotes Gesicht, fatale Grippe.Sie bleiben da. Ihre Nachforschun gen fallen ins Wasser$",
+ "Das Wasser steigt sehr schnell und daempft Ihre letzten Illusionen ... Bevor Sie Zeit haben, zu reagiren, sind Sie tot!$",
+ "Sie sind kaum auf dem Grund des Brunnens, als eine Hand das Seil durchschneidet. Leben, adieu!$",
+ "Der Sturm verwischt Ihre Spuren. Eine Mauer des Schweigens huellt Sie ein. Langsam sterben Sie den Erfrierungstod!$",
+ "Sie sind nicht so allein wie Sie denken. Eine kalte Klinge bohrt sich in Ihren Ruecken. Seien Sie in Zukunft vorsichtiger!$",
+ "Sie ignorieren die Schuld von Leoam Tode Murielles. War sie sofort tot? Auf jeden Fall gerechtfertigen die familiaeren Probleme, die waehrend Ihrer Untersuchung aufgedeckt wurden, die Haltung Leos. Sie sind nicht sicher, ob Julia Sie deswegen angerufen hat, aber es genuegt Ihnen. Aus Respekt fuer sie und nach einigen Vorsichtsmassnahmen, fuehren Sie ein aufschlussreiches Gespraech mit Leo.$",
+ "$",
+ "Sie haben keinen Schluessel fuer den Landsitz. Ihre Rufe bleiben ohne Antwort. Sie werden sterben.$",
+ "Mit einem fuerchterlichen Rundschlag spaltet Sie das Schwert entzwei - das Innere kehrt sich nach aussen.$",
+ "Home, Sweet home!$",
+ "Geheimnis einer geschlossenen Tuer$",
+ "Charme verzaubert die alten Zimmer$",
+ "Leerer Magen$",
+ "Naeher 'gen Himmel? Nicht sicher!$",
+ "Angst vorm Dunkeln?$",
+ "Alte Teppiche und Goldschimmer$",
+ "Angst!$",
+ "Gerettet? Nicht sicher!$",
+ "Man fuehlt sich unwohl, was!$",
+ "Immer noch weiter!$",
+ "Ihr Kreuzweg!$",
+ "Bei der Entdeckung von...$",
+ "Achtung, auf das was sich versteckt...$",
+ "Abstieg in die Hoelle!$",
+ "Na fuehlen Sie sich gut? Sie sehen etwas@ blass aus!$",
+ "Vor dem Eintreten!$",
+ "Zoom:$",
+ "Unter anderem bemerken Sie...$",
+ "Und noch mal...$",
+ "Es ist zu Ende!$",
+ "Ein wenig Lektuere$",
+ "Das Abenteuer wartet auf Sie: also los!$",
+ "Verpassen Sie nicht IHR naechstes ABENTEUER!$",
+ "Ich verstehe nicht$",
+ "Es gibt Einfacheres$",
+ "Nein! Nicht Diesmal$",
+ "Zu spaet$",
+ "$",
+ "Wie ein tiefer verschleierter Blick, sein lebloses Auge auf die Sterne gerichtet, ist er wie der Schlund, der Himmel und Hoelle verbindet. Du musst in diese Tiefe vordringen, so wie eine Ratte in die Erde. Montag, Dienstag, Mittwoch, Sonntag, vom 1. Montag bis zum 1. Sonntag -so wird jeder Tag durch das SEIN oder WERDEN bestimmt. Vebersieh nichts, denn sonst ist Dein Schicksal besiegelt.$",
+ "10/1/50: Wir haben das Mysterium des Manuskriptes geloest und die Krypta lokalisiert. Ist es der Gedanke, in diesem Traum mein Ziel zu erreichen, der mir so angst macht? Ich bedauere, dass ich mich gegenueber Leo so engagiert habe. Nein, ich muss weitermachen Ich haette Guy informieren muessen, aber ich habe seit einer Woche nichts mehr von ihm gehoert$",
+ "Trag deine Bitte an den heiligen Ort - so wirst Du mehr erfahren! Der Pfeiler der Weisheit und die Sonne an den Knien werden Dir die Stelle zeigen , die Deiner Seele den Weg in eine neue Welt oeffnen Vorwaerts Orpheus, ohne Angst vordem Ungewissen: Weiss ist Deine Farbe, Gold ist Dein Zuhause. Be-leuchte Deinen Weg, bis hin zur traurigen Jungfrau. Gib ihr den Kreis des Mannes mit den drei Gesichtern, auf dass er die Welt wieder erreicht und sich dreht in seinem urspruenglichen Reichtum$",
+ "Die Berge sind die Zaehne eines gigantischen unendlichen Schlundes, einer himmlischen Orgie, die Sterne verschlingend, so wie uns die Dunkelheit verschlingt. Du laesst das Seil der Steine zu Dei nen Fuessen fallen. Das Lachen der Stille und in Deiner rechten Hand das Werk eines Meisters. Anschliessend wirst Du zwischen den beiden Monden hindurchgehen; jenseits des Abgrundes der Mauer des Schweigens wirst Du den Schluessel zur Melodie findenes fehlt nur noch die passende Note...$",
+ " DEZEMBER@ 9 ABZUG 518 13 ZINSEN 23@19 VEBERWE. 1203 17 GUTHAB 1598@ TOTAL 1721 TOTAL 1721@$",
+ " 5/01/51@ Luc, mein Liebling@ Guy weiss von unserer Beziehung.Nach einem Streit habe ich ihm alles gesagt. Ich liebe nur Dich. Max sitzt mir dauernd auf dem Hals, aber ich habe definitiv mitihm gebrochen. Soll er doch bei seinen Toepfen bleiben. Wann koennen wir uns allein sehen? Wegen dir wuerde ich mich scheiden lassen@ Deine Eva$",
+ " Morteville, 10/2/51@ Pat@ Ich erinnere Dich daran, dass Du mir noch FF 5000,- schuldest, die ich Dir fuer Dein Geschaeft geliehen habe. Ich brauche sie jetzt. Kannst Du sie mir bitte moeglichst schnell wiedergeben?@ Guy$",
+ " Morteville, 15/2/51@ Lieber Herr@ Ich schreibe Ihnen unser Geschaeft betreffend. Ich bin entschlossen, bis zum Aeusserstenzu gehen, da ich mir sicher bin, dass mein Teilhaber, Pat Defranck ein Rechnungsbuch gefaelscht hat.$",
+ "Eine Pfeife$",
+ "Ein Fuellfederhalter$",
+ "Ein Gasfeuerzeug$",
+ "Eine Retorte$",
+ "Ein Rasierpinsel$",
+ "Ein Farbeimer$",
+ "Eine Floete$",
+ "Ein wertvoller Ring$",
+ "Eine Garnrolle$",
+ "Ein altes Buch$",
+ "Ein Portemonnaie$",
+ "Ein Dolch$",
+ "Ein Revolver$",
+ "Eine Bibel$",
+ "Eine Kerze$",
+ "Ein Schmuckkoffer$",
+ "Ein Buegeleisen$",
+ "Ein Foto$",
+ "Eine Taschenuhr$",
+ "Ein Seil$",
+ "Schluessel$",
+ "Ein Perlenkollier$",
+ "Ein Parfumflakon$",
+ "Ein Fernglas$",
+ "Eine Brille$",
+ "Ein Ledergeldbeutel$",
+ "Ein Tennisball$",
+ "Munition$",
+ "Ein Nassrasierer$",
+ "Eine Haarbuerste$",
+ "Eine Kleiderbuerste$",
+ "Ein Kartenspiel$",
+ "Ein Schuhanzieher$",
+ "Ein Schraubenzieher$",
+ "Ein Hammer$",
+ "Schluessel$",
+ "Schluessel$",
+ "Ein Aschenbecher$",
+ "Ein Pinsel$",
+ "Ein Seil$",
+ "Ein Gegenstand aus Holz$",
+ "Schlafmittel$",
+ "Ein goldener Ring$",
+ "Ein Schmuckkoffer$",
+ "Ein Wecker$",
+ "Ein Panzerhemd$",
+ "Ein Kerzenhalter$",
+ "Ein Paar Handschuhe$",
+ "Ein Ziselierter Becher$",
+ "Ein Pergament$",
+ "Ein Dolch$",
+ "Ein Dossier$",
+ "Ein Pergament$",
+ "Ein Pergament$",
+ "Ein Dossier$",
+ "Ein Dossier$",
+ "Ein Brief$",
+ "Ein Roman$",
+ "Ein Holzstock$",
+ "Ein Umschlag$",
+ "Ein Brief$",
+ "Ein Umschlag$",
+ "Julia$",
+ "Julias Tod$",
+ "Julias Beziehungen$",
+ "eine Nachricht von Julia$",
+ "Julias Erbschaft$",
+ "letzte Handlungen Julias$",
+ "Geschenk von Julia$",
+ "Julias Zimmer$",
+ "die Fotos bei Julia$",
+ "Julia und Sie...$",
+ "die Geschaefte von Leo$",
+ "die Geschaefte von Pat$",
+ "die Geschaefte von Guy$",
+ "die Geschaefte von Bob$",
+ "die Geschaefte von Eva$",
+ "die Geschaefte von Luc$",
+ "die Geschaefte von Ida$",
+ "die Geschaefte von Max$",
+ "Ihre Geschaefte$",
+ "Leos Beziehungen$",
+ "Pats Beziehungen$",
+ "Guys Beziehungen$",
+ "Bobs Beziehungen$",
+ "Evas Beziehungen$",
+ "Lucs Beziehungen$",
+ "Idas Beziehungen$",
+ "Maxs Beziehungen$",
+ "Ihre Beziehungen$",
+ "Murielle$",
+ "Murielles Beziehungen$",
+ "Murielle und Sie...$",
+ "Murielles Vershwinden$",
+ "Die Mauer des Schweigens$",
+ "Die manuskripte$",
+ "Das Wappen$",
+ "Die Inschriften im Keller$",
+ "Der Brunnen$",
+ "Die Geheimgaenge$",
+ "Die Kapelle$",
+ "Die Bilder$",
+ "Die Fotos vom Dachboden$",
+ "Koerper in der Krypta$",
+ "$",
+ "$",
+ "ENDE DER UNTERHALTUNG$",
+ "Die Alten nannten die Bergkette am Fusse des Landsitzes so.$",
+ "Das ist das Bergmassiv, das man vor dem Landsitz sieht.$",
+ "Ich weiss nichts davon.$",
+ "Sie ist an einer Lungenembolie gestorben.$",
+ "Meine Mutter ist ploetzlich gestorben, obwohl es schien, dass sich ihr Zustand verbesserte.$",
+ "Frau Defranck ist gestorben.$",
+ "Sie ist an einer Lungenembolie gestorben.$",
+ "Verzeihen Sie mir, aber ich ziehe es vor, im Moment Schweigen zu bewahren.$",
+ "Es sind immer die Guten, die als erste gehen muessen.$",
+ "Ich habe meine Mutter sehr geliebt; ich bedauere, dass sie auf dem Gut der Defrancks gestorben ist.$",
+ "Dies ist eine Gegend, die eine sehr bewegte Vergangenheit hat und es gibt genug Dinge, um die ich mich kuemmern kann und ausserdem liebe ich Pferde.$",
+ "Er interessiert sich sehr fuer Geschichte und er ist ein erfolgloser Spieler. Uebrigens hat er vor einem Jahr eine bedeutende Summe gewonnen.$",
+ "Er hat schon viel zu tun mit der Buchhaltung und der Verwaltung des Gutes.$",
+ "Ich bin Direktor einer Parfumfirma. Aber hier... Erholung.$",
+ "Ein dymamischer Mann, der in der Parfumbranche viel erreicht hat.$",
+ "Das ist ein uebler Emporkoemmling. Die Parfums muessen seinen gesunden Menschenverstand eingeschlaefert haben. Hier verbringt er seine Abende in seinem Zimmer.$",
+ "Vorher galt meine Hauptsorge der Gesundheit meiner Mutter. Jetzt finde ich an nichts mehr Gefallen.$",
+ "Er haette gut daran getan, sich ein bisschen mehr um mich zu kuemmern und etwas weniger um seine Mutter.$",
+ "Das sind seine Angelegenheiten.$",
+ "Er hat nicht viel Glueck im Moment, obwohl seine Geschaefte zufriedenstellend sind.$",
+ "Ich arbeite mit Pat. Es geht nicht besonders gut im Moment.$",
+ "Ah ja! Hat er Beschaeftigungen? Er taete besser daran, sich ernsthaft zu beschaeftigen.$",
+ "Er und Pat sind Geschaeftspartner. Ich glaube, es laeuft gar nicht mal schlecht.$",
+ "Ich kuemmere mich um mich und das ist schon genug. Und Sie?$",
+ "Oh, ich vetraue ihr. Sie versteht, sich zu beschaeftigen.$",
+ "Aber haben Sie noch nicht ihre Hauptbeschaeftigung entdeckt?$",
+ "Sie arbeitet in der Dekoration mit sehr viel Geschmack. Ausserdem ist sie immer sehr gut angezogen.$",
+ "Interessiert sie der Schmuck. Ich habe ein Geschaeft vorzuschlagen.$",
+ "Der Schmuck...$",
+ "Ich weiss nicht, aber ich glaube, ich wuerde es vorziehen, wenn er sich ein bisschen weniger um meine Angelegenheiten kuemmern wuerde.$",
+ "Eine Hausfrau hat immer zu tun.$",
+ "Sie koennte auch ohne Arbeit auskommen. Aber nein, sie naeht, sie liest...$",
+ "Sie hat sicherlich keine sehr erheiternden Taetigkeiten.$",
+ "Eine aussergewoehnliche Frau. Sie interessiert sich fuer alles.$",
+ "Zwischen Kueche und Haushalt habe ich nicht viel Zeit fuer sie.$",
+ "Wie schafft er es nur, alles zu machen? Oh Wunder!$",
+ "Er taete gut daran, wenn er sich weniger mit Klatsch und der Flasche beschaeftigen wuerde.$",
+ "Ich bin sehr selbstaendig. Solange man sich nicht um meine Angelegenheiten kuemmert, gibt es keine Probleme.$",
+ "Er ist ein Egoist. Ich frage mich, ob es fuer ihn noch etwas anderes gibt, als seine Pferde und seine Maerchenbuecher.$",
+ "Er versteht sich gut mit allen, ausser vielleicht mit Guy.$",
+ "Er ist ein Mann mit Charakter. Man muss ihn zu nehmen wissen.$",
+ "Geschaeft ist Geschaeft. Was die Familie anbetrifft...$",
+ "Beziehungen? Freundschaften? Finanzen zweifellos.$",
+ "Ich habe ihm nichts vorzuwerfen.$",
+ "Er ist ein pfiffiger Geschaeftsmann. Manchmal schwimmt er gegen den Strom, aber er weiss sich immer zu helfen.$",
+ "Sie langweilen mich alle. Nein, obwohl... einige...$",
+ "Im Gegensatz zur Mutter ist es eine sehr verschlossene Person. Also Frage: Beziehung.$",
+ "Er muss sich zweifellos sehr anstrengen, um trotz seiner Sorgen freundlich zu bleiben.$",
+ "Seine Liebesaffairen? Aus und vorbei. Mit mir? Es hat nie richtig angefangen. Was die anderen betrifft... ich bin nicht \"die anderen\".$",
+ "Ich mag jeden, solange man mich nicht betruegt.$",
+ "Es reicht nicht, ein bisschen Geld zu haben und ein guter Redner zu sein, um bei allen beliebt zu sein.$",
+ "Jemand, der nett ist und ausserdem noch Humor hat.$",
+ "Ueber diese Sache kann ich mich nicht auslassen.$",
+ "Das ist nicht besonders intelligent. Sprechen Sie mit dem Ehemann darueber.$",
+ "Ist es wegen eines Rendez-vous?$",
+ "Sie ist sehr lebhaft. sie laesst sich nicht durch Vorurteile in Verwirrung brignen.$",
+ "In meinem Beruf ist man vor allem schoenen Frauen und Gaunern sehr nahe.$",
+ "Sein einziges Vermoegen sind sein Schmuck und seine Frau, aber er ist sich dessen nicht bewusst.$",
+ "Jemand interessantes, aber nicht immer leicht zu verstehen, der aber die Muehe wert ist.$",
+ "Ich verachte niemanden, aber ich mag es sehr, wenn alles und alle dort sind, wo sie hingehoeren.$",
+ "Unter uns.. sehen Sie, wenn ich mit ihr spreche, fuehle ich mich schnell beengt.$",
+ "Um sich nicht mit ihr zu verstehen, braucht man wirklich viel schlechten Willen.$",
+ "In meinem Beruf hoert man alles, aber behaelt nichts. Nur der Service zaehlt.$",
+ "Das ist ein Heuchler, ein Kriecher. Ich persoenlich habe kein Vertrauen zu Ihm.$",
+ "Ich kenne seine wahren Gedanken nicht, aber er war stets korrekt.$",
+ "Sie hat vor einem Jahr, vielleicht laenger, auf dem Landsitz gewohnt.$",
+ "Mehr als eine Freundin fuer meine Mutter. In solchen Augenblicken haette ich gewuenscht, dass sie da ist.$",
+ "Sie war die Hausdame von Julia.$",
+ "Sie hat ebenfalls Recherchen angestellt. Aber Guy, der sie besser kennt als jeder andere, kann Ihnen mehr sagen.$",
+ "Ihre Beziehungen?... Sie war sehr kultiviert. Ihr ploetzliches Verschwinden vor einem Jahr hat mich erstaunt.$",
+ "Sie teilte mit Leo ihre Leidenschaft fuer Geschichte und fuer die Gegend.$",
+ "Ich glaube, jeder hatte sie gern.$",
+ "Sie verstand sich mit allen gut, aber ganz besonders liebte sie ihren Sohn. Was die Beziehungen Schwiegermutter Scwiegertochter anbetrifft...$",
+ "Ausser zu Leo hatte sie auch gute Beziehungen zu Max.$",
+ "Obwohl ihre Beziehungen nicht von Dauer waren, lag ihr immer viel an ihnen.$",
+ "Ausser ihrer Familie, nicht viele.$",
+ "Aber ja. Sie hat das Weggehen dieser Freundin sehr bedauert. Eh, Mireille, oder Marielle.$",
+ "Nein, nichts.$",
+ "Nein, nicht das ich wuesste.$",
+ "Ich habe Julia kennengelernt, als ich das Landgut kaufte. Es war das einzige, was ihr gehoerte, aber mein Besitz war auch der ihre.$",
+ "Wenn nicht einige persoenliche Dinge gewesen waeren, ich glaube, dann haette sie nichts eigenes mehr gehabt.$",
+ "Ich glaube, all ihr Reichtum kam von Leo. Also!$",
+ "Ausser des Briefes, den ich fuer sie aufgegeben habe, nichts wichtiges.$",
+ "Ich war gluecklich, als sie mir ihre eingebundene Bibel schenkte.$",
+ "Es ging schnell und sie hatte nicht die Zeit, um spezielle Entscheidungen zu treffen.$",
+ "Ihr letztes Geschenk hat mich ueberrascht.$",
+ "Was fuer ein Geschenk?$",
+ "Ein Kerzenleuchter.$",
+ "Ja, ich habe ein Geschenk bekommen. Meine Frau hat sogar eine Bibel bekommen.$",
+ "Aber ja. wie jeder, glaube ich.$",
+ "Ein Dolch$",
+ "Ich habe nie den Dachboden durchwuehlt.$",
+ "Haben Sie die Gabe eines Hellsehers, oder haben Sie einen Dietrich?$",
+ "Das Portrait einer jungen Frau? Das ist Murielle.$",
+ "Ich kannte sie zu wenig.$",
+ "Sehr charmant. Sie war vor allem die Hausdame von Julia.$",
+ "Das war die einzige wirklich interessante Frau, die ich getroffen habe.$",
+ "Sie hatte ein grosses Wissen vorzuweisen. Sie zu besuchen, war stets sehr bereichernd.$",
+ "Ich habe mich immer gefragt, was manche an ihr fanden.$",
+ "Das Zimmer ist verschlossen? Fragen Sie Leo.$",
+ "Ich habe ihr Zimmer nach ihrem Tod abgeschlossen und ich moechte, dass das auch noch eine zeitlang so bleibt.$",
+ "Wissen Sie, was das sind? Familienbeziehungen.$",
+ "In all den Jahren habe ich sie niemals gegen meinen Willen bedient.$",
+ "Ich habe sie so sehr geliebt, wie sie mich, glaube ich.$",
+ "Mit welchem Recht sind Sie in das Zimmer meiner Frau eingedrungen?$",
+ "Zweifellos das Foto von Murielle mit dem Patenkind von Julia.$",
+ "Ich erinnere mich nicht.$",
+ "Das ist Murielle. Ich war es, der sie fotografiert hat. Uebrigens ist das Foto seitenverkehrt abgezogen.$",
+ "Sie sind wirklich neugierig. Das ist wertlos.$",
+ "Maerchen, Pergamente und Manuskripte das ist Leos Spezialitaet.$",
+ "Schade, dass die Losung fehlt.$",
+ "Das ist sehr schoen und sehr alt.$",
+ "Das ist ein Ort, den ich nie gesehen habe.$",
+ "Leos Meinung nach schien es, als seien die Monde spaeter gemacht worden.$",
+ "M\210me par ce temps, vous avez d\202nich\202 un soleil ...$",
+ "Tief und beunruhigend. Der Fortschritt hat gutes an sich.$",
+ "Der Rest bleibt fuer mich eines der groessten Raetsel.$",
+ "In letzter Zeit sprach sie oft von einer Reise und dann...$",
+ "An einem Abend vor mehr als einem Jahr hat sie sich entschieden wegzugehen.$",
+ "Auf jeden Fall war sie fuer das Leben hier nicht geschaffen.$",
+ "Welcher Koerper? Welche Krypta?$",
+ "Wenn es sie ueberhaupt gibt, ich habe sie nie gefunden.$",
+ "Aber sicher! Und die Fantome auch.$",
+ "Es ist die aelteste der Stadt. Sie stammt aus dem 11. Jahrhundert.$",
+ "Nach der Revolution wurde sie leicht restauriert.$",
+ "Julia liebte die Malerei sehr.$",
+ "Sie haben verschiedene Stilrichtungen, aber sie haben nicht alle Wert.$",
+ "Was machen Sie da ?$",
+ "Ich bin sicher, Sie suchen etwas!$",
+ "Ich hoere.$",
+ "Was wuenschen Sie?$",
+ "Ja ?$",
+ "Ich stehe zu Ihrer Verfuegung.$",
+ "Weswegen?$",
+ "Na los doch!$",
+ "Wegen was?$",
+ "Max: Zu Ihren Diensten, Monsieur.$",
+ "Auf jeden Fall haben Sie hier nichts zu suchen! Gehen Sie raus!$",
+ "Sie sind zu neugierig!$",
+ "Jerome, es ist lange her. Wie traurig, Julia ist tot. Ihre Familie ist hier. Guy, ihr Sohn, und Eva, ihre Schwiegertochter. Leo, ihr Mann, sowie ihr Schwiegersohn Pat und die Cousins Bob, Ida und Luc. Das Unwetter verstaerkt sich. Sie muessen noch bleiben. Die Mahlzeiten sind um 12 Uhr und um 19 Uhr und es findet jeden Tag um 10 Uhr eine Andacht in der Kapelle statt.$",
+ "Als ich Sie sah, habe ich sofort begriffen, dass Sie die Wahrheit aufdecken wuerden, da ich wusste, warum Sie gekommen sind. Ich hatte den Entwurf von Julias Brief gefunden. Aber ich bin ein begeisterter Spieler, also.... Sie haette nicht gewollte, dass ihre Aufgabe zu leicht ausfaellt, zweifellos, um mich zu schuetzen, aber sie konnten nicht sterben mit dieser Ungewissheit.Haben Sie herausgefunden, dass die \"Mauer des Schweigens\" der Name ist, den die Maurer waehrend des Baus des Landsitzes der Mauer gegeben haben, die das Wappen traegt...? Und die Geschenke, die Julia vor ihrem Tod hinterlassen hat waren sowohl falsche Hinweise wie auch ein Mittel, um die Wichtigkeit der Pergamente herauszustellen. Tatsaechlich arbeitete ich vor mehr als einem Jahr mit Murielle an der Entzifferung dieser Pergamente, die ich gefunden hatte. Meine Frau sah einen Zusammenhang zwischen unserer Arbeit und dem Verschwinden Murielles,aber sie hat nie Beweise dafuer gehabt; wenn da nicht dieser Ring gewesen waere, den sie eines Tages unter meinen Sachen wiedergefunden hat. Eines nachts sind wir in dem Geheimgang, den wir entdeckt hatten,auf Erkundung gegangen. Murielle ist durch einen Unfall im \"Jungfrauenzimmer\" ums Leben gekommen. Ich habe ihren Ring schnell an mich genommen, habe den Schatz entdeckt und mich dann aus dem Staub gemacht. Ich dachte nicht daran, dass sie unter Umstaenden noch leben koennte, und ich habe nichts gesagt, da ich Geld brauchte. Ich habe das Geld beim Pferderennen verspielt. Gehen Sie jetzt, da sie ja nicht von der Polizei sind. Lassen Sie mich allein.$",
+ "Februar '51, Beruf: Privatdetektiv. Die Kaelte laesst Paris und meine Unternehmungen erstarren, als...$",
+ "Julia, heute eine alte Frau. Nichts als Erinnerungen und Spiele in den alten Zimmern des Landsitzes von Morteville.$",
+ "im Buero$",
+ "in der Kueche$",
+ "im Keller$",
+ "auf dem Flur$",
+ "draussen$",
+ "im Esszimmer$",
+ "im Landsitz$",
+ "vor dem Landsitz$",
+ "in der Kapelle$",
+ "vor dem Brunnen$",
+ "im Norden$",
+ "hinter dem Landsitz$",
+ "im Sueden$",
+ "im Osten$",
+ "im Westen$",
+ "in Richtung Landsitz$",
+ "noch weiter$",
+ "im Wasser$",
+ "ausser des Brunnens$",
+ "im Brunnen$",
+ "Wahl auf dem Bild$",
+ " In der Reihe RAETSEL...$",
+ " DER LANDSITZ VON MORTEVILLE$",
+ "$",
+ " Nach einer Idee von...$",
+ " Bernard GRELAUD und Bruno GOURIER$",
+ "$",
+ " Realisation: LANKHOR$",
+ "$",
+ " in Zusammenarbeit mit...$",
+ " Beatrice und Jean-Luc LANGLOIS Musik und Stimmen,$",
+ " Bernard GRELAUD graphische Gestaltung,$",
+ " Dominique SABLONS graphische Realisation ,$",
+ " Bruno GOURIER technische Realisation,$",
+ " Gabi NURGE Uebersetzung,$",
+ " Clement ROQUES IBM PC Realisation.$",
+ "$",
+ " Ausgabe: LANKHOR$",
+ " COPYRIGHT 1989: LANKHOR$",
+ "$",
+ " SIE SIND AM ZUG$",
+ "abkratzen$",
+ "anschauen$",
+ "ausgehen$",
+ "befestig.$",
+ "drehen$",
+ "durchsuch$",
+ "eindrueck$",
+ "eintreten$",
+ "essen$",
+ "fuehlen$",
+ "hochheben$",
+ "klopfen$",
+ "lesen$",
+ "nehmen$",
+ "oeffnen$",
+ "schlafen$",
+ "schliess.$",
+ "setzen$",
+ "sondieren$",
+ "warten$",
+ "zuhoeren$",
+ "anschauen$",
+ "durchsuch.$",
+ "hinlegen$",
+ "lesen$",
+ "s. verstec$",
+ "Leo$",
+ "Pat$",
+ "Guy$",
+ "Eva$",
+ "Bob$",
+ "Luc$",
+ "Ida$",
+ "Max$",
+ " JULIA$",
+ "hat sie Selbstmord begangen ?$",
+ "ist sie ermordet worden ?$",
+ "ist sie durch Unfall gestorben ?$",
+ "ist sie eines natuerlichen Todes gestorben ?$",
+ " Woher kam das Geld, das die restaurierung des landsitzes erlaubte ?$",
+ "Erpressung$",
+ "Arbeit$",
+ "Erbschaft$",
+ "Rennen$",
+ "Renten$",
+ "Raub$",
+ "Verschiedenes$",
+ " Was ist Leos Hobby ?$",
+ "Historische Recherchen$",
+ "Politik$",
+ "Malerei$",
+ "Drogen$",
+ "Okkultismus$",
+ "Fuehrung einer Sekte$",
+ " Julia Hat verschiedene Indizien hinterlassen. Diese befinden sich an einem einzigen Ort. Welchem ?$",
+ "Kapelle$",
+ "Draussen$",
+ "Keller$",
+ "Dachboden$",
+ "Kueche$",
+ "Esszimmer$",
+ "Julias Zimmer$",
+ "Leos Zimmer$",
+ "Pats Zimmer$",
+ "Bobs Zimmer$",
+ "Maxs Zimmer$",
+ "Luc/Idas Zimmer$",
+ "Guy/Evas Zimmer$",
+ " Der entscheidende Hinweis, der es Ihnen ermoeglichte, bis an die Tuer des Souterrains zu gelangen, war :$",
+ "ein Dolch$",
+ "ein Ring$",
+ "ein Buch$",
+ "ein Pergament$",
+ "ein Brief$",
+ "ein Pendel$",
+ " Wievele Pergamente befinden sich auf dem Landsitz ?$",
+ "kein$",
+ "eins$",
+ "zwei$",
+ "drei$",
+ "vier$",
+ "f\201nf$",
+ " Wieviele Personen sind in die Geschichte verwickelt ? (Julia eingeschlossen, ausgenommen Sie)$",
+ "neun$",
+ "zehn$",
+ "elf$",
+ " Wie war der Name der unbekannten Person ?$",
+ "Mireille$",
+ "Fran\207oise$",
+ "Maguy$",
+ "Emilie$",
+ "Murielle$",
+ "Sophie$",
+ " Wessen Geliebte war Murielle ?$",
+ "Bob$",
+ "Luc$",
+ "Guy$",
+ "Leo$",
+ "Max$",
+ " Murielle teilte eine Beschaeftigung mit einer anderen Person. Mit wem ?$",
+ "[1][Allein der Zufall hat es Ihnen ermoeglicht bis hierher zu komen.| Gehen Sie zurueck und forschen Sie noch einmal nach,|damit Sie das Gaze besser verstehen...][ok]$",
+ "[1][Legen Sie die Diskette 1 ein][ok]$",
+ "[1][Problem mit der Diskette | Alles abstellen...][OK]$",
+ "[1][Sie haetten 00% der Hinweise| bemerken muessen][ OK ]$",
+ "[1][Legen Sie die Diskette 2 ein][ok]$",
+ "[1][Bevor Sie weitermachen, fassen Sie Ihre Kenntnisse Zusammen][ok]$",
+ " MASTER .$",
+ " sgaf",
+ NULL
+};
+#endif
diff --git a/devtools/create_mortdat/module.mk b/devtools/create_mortdat/module.mk
new file mode 100644
index 0000000000..86b14d8284
--- /dev/null
+++ b/devtools/create_mortdat/module.mk
@@ -0,0 +1,11 @@
+
+MODULE := devtools/create_mortdat
+
+MODULE_OBJS := \
+ create_mortdat.o \
+
+# Set the name of the executable
+TOOL_EXECUTABLE := create_mortdat
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/devtools/create_neverhood/create_neverhood.cpp b/devtools/create_neverhood/create_neverhood.cpp
index f34f20882c..446ee5ec3b 100644
--- a/devtools/create_neverhood/create_neverhood.cpp
+++ b/devtools/create_neverhood/create_neverhood.cpp
@@ -69,13 +69,13 @@ bool loadExe(const char *filename) {
bool validateMd5() {
uint8 digest[16];
-
+
md5_buffer(data, dataSize, digest);
-
+
printf("MD5 of nhc.exe is %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
- digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
+ digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]);
-
+
if (memcmp(kNhcExeMd5, digest, 16)) {
printf("MD5 hash of nhc.exe doesn't match the expected value! Quitting...\n");
return false;
@@ -112,7 +112,7 @@ uint32 calcHash(const char *value) {
struct HitRect {
int16 x1, y1, x2, y2;
uint16 messageNum;
-
+
void load(uint32 offset) {
byte *item = getData(offset);
x1 = READ_LE_UINT16(item + 0);
@@ -120,7 +120,7 @@ struct HitRect {
x2 = READ_LE_UINT16(item + 4);
y2 = READ_LE_UINT16(item + 6);
messageNum = READ_LE_UINT16(item + 8);
- }
+ }
void save(FILE *fd) {
writeUint16LE(fd, x1);
@@ -129,11 +129,11 @@ struct HitRect {
writeUint16LE(fd, y2);
writeUint16LE(fd, messageNum);
}
-
+
int getItemSize() const {
return 10;
}
-
+
};
struct MessageItem {
@@ -141,22 +141,22 @@ struct MessageItem {
uint32 messageParam;
MessageItem() {}
MessageItem(uint16 msgNum, uint32 msgParam) : messageNum(msgNum), messageParam(msgParam) {}
-
+
void load(uint32 offset) {
byte *item = getData(offset);
messageNum = READ_LE_UINT16(item + 0);
messageParam = READ_LE_UINT32(item + 4);
- }
+ }
void save(FILE *fd) {
writeUint16LE(fd, messageNum);
writeUint32LE(fd, messageParam);
}
-
+
int getItemSize() const {
return 8;
}
-
+
};
struct SubRectItem {
@@ -175,7 +175,7 @@ struct SubRectItem {
// Add the message to the message list
addMessageList(messageListCount, messageListOffset);
}
-
+
void save(FILE *fd) {
writeUint16LE(fd, x1);
writeUint16LE(fd, y1);
@@ -183,11 +183,11 @@ struct SubRectItem {
writeUint16LE(fd, y2);
writeUint32LE(fd, messageListOffset);
}
-
+
int getItemSize() const {
return 16;
}
-
+
};
struct RectItem {
@@ -212,7 +212,7 @@ struct RectItem {
subItemOffset += 16;
subRectItems.push_back(subRectItem);
}
- }
+ }
void save(FILE *fd) {
writeUint16LE(fd, x1);
@@ -223,11 +223,11 @@ struct RectItem {
for (uint32 j = 0; j < subRectItems.size(); j++)
subRectItems[j].save(fd);
}
-
+
int getItemSize() const {
return 16;
}
-
+
};
struct NavigationItem {
@@ -238,10 +238,10 @@ struct NavigationItem {
byte interactive;
byte middleFlag;
uint32 mouseCursorFileHash;
-
+
void load(uint32 offset) {
byte *item = getData(offset);
- fileHash = READ_LE_UINT32(item + 0);
+ fileHash = READ_LE_UINT32(item + 0);
leftSmackerFileHash = READ_LE_UINT32(item + 4);
rightSmackerFileHash = READ_LE_UINT32(item + 8);
middleSmackerFileHash = READ_LE_UINT32(item + 12);
@@ -263,7 +263,7 @@ struct NavigationItem {
int getItemSize() const {
return 24;
}
-
+
};
struct SceneInfo140Item {
@@ -347,24 +347,24 @@ struct SceneInfo2700Item {
template<class ITEMCLASS>
class StaticDataList {
public:
- uint32 id;
+ uint32 id;
std::vector<ITEMCLASS> items;
-
+
virtual ~StaticDataList() {
}
-
+
void add(ITEMCLASS item) {
items.push_back(item);
}
-
+
int getCount() const {
return items.size();
}
-
+
ITEMCLASS *getListItem(int index) {
return &items[index];
}
-
+
virtual bool specialLoadList(uint32 count, uint32 offset) {
return false;
}
@@ -398,7 +398,7 @@ class RectList : public StaticDataList<RectItem> {
};
class MessageList : public StaticDataList<MessageItem> {
-public:
+public:
virtual bool specialLoadList(uint32 count, uint32 offset) {
// Special code for message lists which are set at runtime (but otherwise constant)
@@ -455,7 +455,7 @@ public:
}
return false;
}
-
+
};
class NavigationList : public StaticDataList<NavigationItem> {
@@ -465,11 +465,11 @@ template<class LISTCLASS>
class StaticDataListVector {
public:
std::vector<LISTCLASS*> lists;
-
+
void add(LISTCLASS *list) {
lists.push_back(list);
}
-
+
void loadListVector(const uint32 *offsets) {
for (int i = 0; offsets[i] != 0; i += 2) {
LISTCLASS *list = new LISTCLASS();
@@ -486,7 +486,7 @@ public:
lists.push_back(list);
}
}
-
+
void saveListVector(FILE *fd) {
writeUint32LE(fd, lists.size());
for (typename std::vector<LISTCLASS*>::iterator it = lists.begin(); it != lists.end(); it++) {
@@ -500,7 +500,7 @@ template<class ITEMCLASS>
class StaticDataVector {
public:
std::vector<ITEMCLASS> items;
-
+
void loadVector(const uint32 *offsets) {
for (int i = 0; offsets[i] != 0; i++) {
ITEMCLASS item;
@@ -508,7 +508,7 @@ public:
items.push_back(item);
}
}
-
+
void saveVector(FILE *fd) {
writeUint32LE(fd, items.size());
for (typename std::vector<ITEMCLASS>::iterator it = items.begin(); it != items.end(); it++) {
@@ -522,8 +522,8 @@ StaticDataListVector<HitRectList> hitRectLists;
StaticDataListVector<RectList> rectLists;
StaticDataListVector<MessageList> messageLists;
StaticDataListVector<NavigationList> navigationLists;
-StaticDataVector<SceneInfo140Item> sceneInfo140Items;
-StaticDataVector<SceneInfo2700Item> sceneInfo2700Items;
+StaticDataVector<SceneInfo140Item> sceneInfo140Items;
+StaticDataVector<SceneInfo2700Item> sceneInfo2700Items;
void addMessageList(uint32 messageListCount, uint32 messageListOffset) {
MessageList *messageList = new MessageList();
@@ -550,7 +550,7 @@ int main(int argc, char *argv[]) {
writeUint32LE(datFile, 0x11223344); // Some magic
writeUint32LE(datFile, DAT_VERSION);
-
+
messageLists.saveListVector(datFile);
rectLists.saveListVector(datFile);
hitRectLists.saveListVector(datFile);
diff --git a/devtools/create_neverhood/tables.h b/devtools/create_neverhood/tables.h
index ea39aa807d..eb136491db 100644
--- a/devtools/create_neverhood/tables.h
+++ b/devtools/create_neverhood/tables.h
@@ -122,7 +122,7 @@ static const uint32 rectListOffsets[] = {
// Scene2406
1, 0x004B78C8,
1, 0x004B78D8,
- // Scene2501
+ // Scene2501
1, 0x004B2608,
// Scene2732
1, 0x004AE360,
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index a8e09ff5eb..3ee5fc4f97 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -109,7 +109,7 @@ enum ProjectType {
int main(int argc, char *argv[]) {
#ifndef USE_WIN32_API
// Initialize random number generator for UUID creation
- std::srand((uint)std::time(0));
+ std::srand((unsigned int)std::time(0));
#endif
if (argc < 2) {
@@ -189,7 +189,7 @@ int main(int argc, char *argv[]) {
msvcVersion = atoi(argv[++i]);
- if (msvcVersion != 8 && msvcVersion != 9 && msvcVersion != 10 && msvcVersion != 11) {
+ if (msvcVersion != 8 && msvcVersion != 9 && msvcVersion != 10 && msvcVersion != 11 && msvcVersion != 12) {
std::cerr << "ERROR: Unsupported version: \"" << msvcVersion << "\" passed to \"--msvc-version\"!\n";
return -1;
}
@@ -264,7 +264,7 @@ int main(int argc, char *argv[]) {
setup.filePrefix.erase(setup.filePrefix.size() - 1);
} else if (!std::strcmp(argv[i], "--output-dir")) {
if (i + 1 >= argc) {
- std::cerr << "ERROR: Missing \"path\" parameter for \"--output-dirx\"!\n";
+ std::cerr << "ERROR: Missing \"path\" parameter for \"--output-dir\"!\n";
return -1;
}
@@ -279,12 +279,23 @@ int main(int argc, char *argv[]) {
setup.createInstaller = true;
} else if (!std::strcmp(argv[i], "--tools")) {
setup.devTools = true;
+ } else if (!std::strcmp(argv[i], "--tests")) {
+ setup.tests = true;
} else {
std::cerr << "ERROR: Unknown parameter \"" << argv[i] << "\"\n";
return -1;
}
}
+ // When building tests, disable some features
+ if (setup.tests) {
+ setFeatureBuildState("mt32emu", setup.features, false);
+ setFeatureBuildState("eventrecorder", setup.features, false);
+
+ for (EngineDescList::iterator j = setup.engines.begin(); j != setup.engines.end(); ++j)
+ j->enable = false;
+ }
+
// Print status
cout << "Enabled engines:\n\n";
for (EngineDescList::const_iterator i = setup.engines.begin(); i != setup.engines.end(); ++i) {
@@ -310,6 +321,23 @@ int main(int argc, char *argv[]) {
cout << " " << i->description << '\n';
}
+ // Check if the keymapper and the event recorder are enabled simultaneously
+ bool keymapperEnabled = false;
+ for (FeatureList::const_iterator i = setup.features.begin(); i != setup.features.end(); ++i) {
+ if (i->enable && !strcmp(i->name, "keymapper"))
+ keymapperEnabled = true;
+ if (i->enable && !strcmp(i->name, "eventrecorder") && keymapperEnabled) {
+ std::cerr << "ERROR: The keymapper and the event recorder cannot be enabled simultaneously currently, please disable one of the two\n";
+ return -1;
+ }
+ }
+
+ // Check if tools and tests are enabled simultaneously
+ if (setup.devTools && setup.tests) {
+ std::cerr << "ERROR: The tools and tests projects cannot be created simultaneously\n";
+ return -1;
+ }
+
// Setup defines and libraries
setup.defines = getEngineDefines(setup.engines);
setup.libraries = getFeatureLibraries(setup.features);
@@ -347,8 +375,8 @@ int main(int argc, char *argv[]) {
return -1;
case kProjectCodeBlocks:
- if (setup.devTools) {
- std::cerr << "ERROR: Building tools is not supported for the CodeBlocks project type!\n";
+ if (setup.devTools || setup.tests) {
+ std::cerr << "ERROR: Building tools or tests is not supported for the CodeBlocks project type!\n";
return -1;
}
@@ -520,8 +548,8 @@ int main(int argc, char *argv[]) {
break;
case kProjectXcode:
- if (setup.devTools) {
- std::cerr << "ERROR: Building tools is not supported for the XCode project type!\n";
+ if (setup.devTools || setup.tests) {
+ std::cerr << "ERROR: Building tools or tests is not supported for the XCode project type!\n";
return -1;
}
@@ -562,6 +590,11 @@ int main(int argc, char *argv[]) {
setup.projectDescription += "Tools";
}
+ if (setup.tests) {
+ setup.projectName += "-tests";
+ setup.projectDescription += "Tests";
+ }
+
provider->createProject(setup);
delete provider;
@@ -588,7 +621,7 @@ void displayHelp(const char *exe) {
" Additionally there are the following switches for changing various settings:\n"
"\n"
"Project specific settings:\n"
- " --codeblock build Code::Blocks project files\n"
+ " --codeblocks build Code::Blocks project files\n"
" --msvc build Visual Studio project files\n"
" --xcode build XCode project files\n"
" --file-prefix prefix allow overwriting of relative file prefix in the\n"
@@ -609,9 +642,12 @@ void displayHelp(const char *exe) {
" (default: false)\n"
" --installer Create NSIS installer after the build (implies --build-events)\n"
" (default: false)\n"
- " --tools Create project files for the devtools\n"
- " (ignores --build-events and --installer, as well as engine settings)\n"
- " (default: false)\n"
+ " --tools Create project files for the devtools\n"
+ " (ignores --build-events and --installer, as well as engine settings)\n"
+ " (default: false)\n"
+ " --tests Create project files for the tests\n"
+ " (ignores --build-events and --installer, as well as engine settings)\n"
+ " (default: false)\n"
"\n"
"Engines settings:\n"
" --list-engines list all available engines and their default state\n"
@@ -805,23 +841,26 @@ const Feature s_features[] = {
{ "vorbis", "USE_VORBIS", "libvorbisfile_static libvorbis_static libogg_static", true, "Ogg Vorbis support" },
{ "flac", "USE_FLAC", "libFLAC_static", true, "FLAC support" },
{ "png", "USE_PNG", "libpng", true, "libpng support" },
+ { "faad", "USE_FAAD", "libfaad", false, "AAC support" },
+ { "mpeg2", "USE_MPEG2", "libmpeg2", false, "MPEG-2 support" },
{ "theora", "USE_THEORADEC", "libtheora_static", true, "Theora decoding support" },
{"freetype", "USE_FREETYPE2", "freetype", true, "FreeType support" },
// Feature flags
- { "bink", "USE_BINK", "", true, "Bink video support" },
- { "scalers", "USE_SCALERS", "", true, "Scalers" },
- { "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" },
- { "16bit", "USE_RGB_COLOR", "", true, "16bit color support" },
- { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" },
- { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling.
- { "opengl", "USE_OPENGL", "opengl32", true, "OpenGL support" },
- { "taskbar", "USE_TASKBAR", "", true, "Taskbar integration support" },
- { "translation", "USE_TRANSLATION", "", true, "Translation support" },
- { "vkeybd", "ENABLE_VKEYBD", "", false, "Virtual keyboard support"},
- { "keymapper","ENABLE_KEYMAPPER", "", false, "Keymapper support"},
- { "langdetect", "USE_DETECTLANG", "", true, "System language detection support" } // This feature actually depends on "translation", there
- // is just no current way of properly detecting this...
+ { "bink", "USE_BINK", "", true, "Bink video support" },
+ { "scalers", "USE_SCALERS", "", true, "Scalers" },
+ { "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" },
+ { "16bit", "USE_RGB_COLOR", "", true, "16bit color support" },
+ { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" },
+ { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling.
+ { "opengl", "USE_OPENGL", "opengl32", true, "OpenGL support" },
+ { "taskbar", "USE_TASKBAR", "", true, "Taskbar integration support" },
+ { "translation", "USE_TRANSLATION", "", true, "Translation support" },
+ { "vkeybd", "ENABLE_VKEYBD", "", false, "Virtual keyboard support"},
+ { "keymapper", "ENABLE_KEYMAPPER", "", false, "Keymapper support"},
+ { "eventrecorder", "ENABLE_EVENTRECORDER", "", false, "Event recorder support"},
+ { "langdetect", "USE_DETECTLANG", "", true, "System language detection support" } // This feature actually depends on "translation", there
+ // is just no current way of properly detecting this...
};
const Tool s_tools[] = {
@@ -829,7 +868,9 @@ const Tool s_tools[] = {
{ "create_hugo", true},
{ "create_kyradat", true},
{ "create_lure", true},
+ { "create_neverhood", true},
{ "create_teenagent", true},
+ { "create_tony", true},
{ "create_toon", true},
{ "create_translations", true},
{ "qtable", true}
@@ -1114,69 +1155,66 @@ ProjectProvider::ProjectProvider(StringList &global_warnings, std::map<std::stri
: _version(version), _globalWarnings(global_warnings), _projectWarnings(project_warnings) {
}
-void ProjectProvider::createProject(const BuildSetup &setup) {
+void ProjectProvider::createProject(BuildSetup &setup) {
+ std::string targetFolder;
+
if (setup.devTools) {
_uuidMap = createToolsUUIDMap();
+ targetFolder = "/devtools/";
+ } else if (!setup.tests) {
+ _uuidMap = createUUIDMap(setup);
+ targetFolder = "/engines/";
+ }
- // We also need to add the UUID of the main project file.
- const std::string svmUUID = _uuidMap[setup.projectName] = createUUID();
-
- createWorkspace(setup);
-
- StringList in, ex;
-
- // Create tools project files
- for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
- if (i->first == setup.projectName)
- continue;
-
- in.clear(); ex.clear();
- const std::string moduleDir = setup.srcDir + "/devtools/" + i->first;
+ // We also need to add the UUID of the main project file.
+ const std::string svmUUID = _uuidMap[setup.projectName] = createUUID();
- createModuleList(moduleDir, setup.defines, in, ex);
- createProjectFile(i->first, i->second, setup, moduleDir, in, ex);
- }
+ createWorkspace(setup);
- // Create other misc. build files
- createOtherBuildFiles(setup);
+ StringList in, ex;
- } else {
- _uuidMap = createUUIDMap(setup);
-
- // We also need to add the UUID of the main project file.
- const std::string svmUUID = _uuidMap[setup.projectName] = createUUID();
-
- // Create Solution/Workspace file
- createWorkspace(setup);
+ // Create project files
+ for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
+ if (i->first == setup.projectName)
+ continue;
- StringList in, ex;
+ in.clear(); ex.clear();
+ const std::string moduleDir = setup.srcDir + targetFolder + i->first;
- // Create engine project files
- for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) {
- if (i->first == setup.projectName)
- continue;
+ createModuleList(moduleDir, setup.defines, setup.testDirs, in, ex);
+ createProjectFile(i->first, i->second, setup, moduleDir, in, ex);
+ }
- in.clear(); ex.clear();
- const std::string moduleDir = setup.srcDir + "/engines/" + i->first;
+ if (setup.tests) {
+ // Create the main project file.
+ in.clear(); ex.clear();
- createModuleList(moduleDir, setup.defines, in, ex);
- createProjectFile(i->first, i->second, setup, moduleDir, in, ex);
- }
+ createModuleList(setup.srcDir + "/backends", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/base", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/common", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/engines", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/graphics", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/gui", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/audio", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/test", setup.defines, setup.testDirs, in, ex);
+ createProjectFile(setup.projectName, svmUUID, setup, setup.srcDir, in, ex);
+ } else if (!setup.devTools) {
// Last but not least create the main project file.
in.clear(); ex.clear();
// File list for the Project file
- createModuleList(setup.srcDir + "/backends", setup.defines, in, ex);
- createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, in, ex);
- createModuleList(setup.srcDir + "/base", setup.defines, in, ex);
- createModuleList(setup.srcDir + "/common", setup.defines, in, ex);
- createModuleList(setup.srcDir + "/engines", setup.defines, in, ex);
- createModuleList(setup.srcDir + "/graphics", setup.defines, in, ex);
- createModuleList(setup.srcDir + "/gui", setup.defines, in, ex);
- createModuleList(setup.srcDir + "/audio", setup.defines, in, ex);
- createModuleList(setup.srcDir + "/audio/softsynth/mt32", setup.defines, in, ex);
- createModuleList(setup.srcDir + "/video", setup.defines, in, ex);
+ createModuleList(setup.srcDir + "/backends", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/base", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/common", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/engines", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/graphics", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/gui", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/audio", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/audio/softsynth/mt32", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/video", setup.defines, setup.testDirs, in, ex);
// Resource files
in.push_back(setup.srcDir + "/icons/" + setup.projectName + ".ico");
@@ -1195,10 +1233,10 @@ void ProjectProvider::createProject(const BuildSetup &setup) {
// Create the main project file.
createProjectFile(setup.projectName, svmUUID, setup, setup.srcDir, in, ex);
-
- // Create other misc. build files
- createOtherBuildFiles(setup);
}
+
+ // Create other misc. build files
+ createOtherBuildFiles(setup);
}
ProjectProvider::UUIDMap ProjectProvider::createUUIDMap(const BuildSetup &setup) const {
@@ -1306,7 +1344,7 @@ void ProjectProvider::addFilesToProject(const std::string &dir, std::ofstream &p
delete files;
}
-void ProjectProvider::createModuleList(const std::string &moduleDir, const StringList &defines, StringList &includeList, StringList &excludeList) const {
+void ProjectProvider::createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList) const {
const std::string moduleMkFile = moduleDir + "/module.mk";
std::ifstream moduleMk(moduleMkFile.c_str());
if (!moduleMk)
@@ -1437,6 +1475,59 @@ void ProjectProvider::createModuleList(const std::string &moduleDir, const Strin
++i;
}
}
+ } else if (*i == "TESTS") {
+ if (tokens.size() < 3)
+ error("Malformed TESTS definition in " + moduleMkFile);
+ ++i;
+
+ if (*i != ":=" && *i != "+=" && *i != "=")
+ error("Malformed TESTS definition in " + moduleMkFile);
+ ++i;
+
+ while (i != tokens.end()) {
+ // Read input
+ std::string folder = unifyPath(*i);
+
+ // Get include folder
+ const std::string source_dir = "$(srcdir)/";
+ const std::string selector = getLastPathComponent(folder);
+ const std::string module = getLastPathComponent(moduleDir);
+
+ folder.replace(folder.find(source_dir), source_dir.length(), "");
+ folder.replace(folder.find(selector), selector.length(), "");
+ folder.replace(folder.find(module), module.length(), moduleDir);
+
+ // Scan all files in the include folder
+ FileList files = listDirectory(folder);
+
+ if (files.empty())
+ continue;
+
+ // Add to list of test folders
+ testDirs.push_back(folder);
+
+ for (FileList::const_iterator f = files.begin(); f != files.end(); ++f) {
+ if (f->isDirectory)
+ continue;
+
+ std::string filename = folder + f->name;
+
+ if (shouldInclude.top()) {
+ // In case we should include a file, we need to make
+ // sure it is not in the exclude list already. If it
+ // is we just drop it from the exclude list.
+ excludeList.remove(filename);
+
+ includeList.push_back(filename);
+ } else if (std::find(includeList.begin(), includeList.end(), filename) == includeList.end()) {
+ // We only add the file to the exclude list in case it
+ // has not yet been added to the include list.
+ excludeList.push_back(filename);
+ }
+ }
+
+ ++i;
+ }
} else if (*i == "ifdef") {
if (tokens.size() < 2)
error("Malformed ifdef in " + moduleMkFile);
diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h
index de77793ee7..d0f2db364c 100644
--- a/devtools/create_project/create_project.h
+++ b/devtools/create_project/create_project.h
@@ -221,13 +221,16 @@ struct BuildSetup {
StringList defines; ///< List of all defines for the build.
StringList libraries; ///< List of all external libraries required for the build.
+ StringList testDirs; ///< List of all folders containing tests
bool devTools; ///< Generate project files for the tools
+ bool tests; ///< Generate project files for the tests
bool runBuildEvents; ///< Run build events as part of the build (generate revision number and copy engine/theme data & needed files to the build folder
bool createInstaller; ///< Create NSIS installer after the build
BuildSetup() {
devTools = false;
+ tests = false;
runBuildEvents = false;
createInstaller = false;
}
@@ -339,7 +342,7 @@ public:
*
* @param setup Description of the desired build setup.
*/
- void createProject(const BuildSetup &setup);
+ void createProject(BuildSetup &setup);
/**
* Returns the last path component.
@@ -430,10 +433,11 @@ protected:
*
* @param moduleDir Path to the module.
* @param defines List of set defines.
+ * @param testDirs List of folders containing tests.
* @param includeList Reference to a list, where included files should be added.
* @param excludeList Reference to a list, where excluded files should be added.
*/
- void createModuleList(const std::string &moduleDir, const StringList &defines, StringList &includeList, StringList &excludeList) const;
+ void createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList) const;
/**
* Creates an UUID for every enabled engine of the
@@ -448,7 +452,7 @@ protected:
* Creates an UUID for every enabled tool of the
* passed build description.
*
- * @return A map, which includes UUIDs for all enabled engines.
+ * @return A map, which includes UUIDs for all enabled tools.
*/
UUIDMap createToolsUUIDMap() const;
diff --git a/devtools/create_project/msbuild.cpp b/devtools/create_project/msbuild.cpp
index 0f77d91852..23bf1bc28a 100644
--- a/devtools/create_project/msbuild.cpp
+++ b/devtools/create_project/msbuild.cpp
@@ -52,6 +52,9 @@ int MSBuildProvider::getVisualStudioVersion() {
if (_version == 11)
return 2012;
+ if (_version == 12)
+ return 2013;
+
error("Unsupported version passed to getVisualStudioVersion");
}
@@ -66,7 +69,7 @@ inline void outputConfiguration(std::ostream &project, const std::string &config
inline void outputConfigurationType(const BuildSetup &setup, std::ostream &project, const std::string &name, const std::string &config, int version) {
project << "\t<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='" << config << "'\" Label=\"Configuration\">\n"
- "\t\t<ConfigurationType>" << ((name == setup.projectName || setup.devTools) ? "Application" : "StaticLibrary") << "</ConfigurationType>\n"
+ "\t\t<ConfigurationType>" << ((name == setup.projectName || setup.devTools || setup.tests) ? "Application" : "StaticLibrary") << "</ConfigurationType>\n"
"\t\t<PlatformToolset>v" << version << "0</PlatformToolset>\n"
"\t</PropertyGroup>\n";
}
@@ -88,7 +91,7 @@ void MSBuildProvider::createProjectFile(const std::string &name, const std::stri
error("Could not open \"" + projectFile + "\" for writing");
project << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
+ "<Project DefaultTargets=\"Build\" ToolsVersion=\"" << (_version >= 12 ? _version : 4) << ".0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
"\t<ItemGroup Label=\"ProjectConfigurations\">\n";
outputConfiguration(project, "Debug", "Win32");
@@ -105,7 +108,7 @@ void MSBuildProvider::createProjectFile(const std::string &name, const std::stri
"\t\t<ProjectGuid>{" << uuid << "}</ProjectGuid>\n"
"\t\t<RootNamespace>" << name << "</RootNamespace>\n"
"\t\t<Keyword>Win32Proj</Keyword>\n"
- "\t\t<VCTargetsPath Condition=\"'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and $(VisualStudioVersion) == ''\">$(VCTargetsPath11)</VCTargetsPath>\n"
+ "\t\t<VCTargetsPath Condition=\"'$(VCTargetsPath" << _version << ")' != '' and '$(VSVersion)' == '' and $(VisualStudioVersion) == ''\">$(VCTargetsPath" << _version << ")</VCTargetsPath>\n"
"\t</PropertyGroup>\n";
// Shared configuration
@@ -156,10 +159,26 @@ void MSBuildProvider::createProjectFile(const std::string &name, const std::stri
if (name == setup.projectName)
writeReferences(setup, project);
+ // Output auto-generated test runner
+ if (setup.tests) {
+ project << "\t<ItemGroup>\n";
+ project << "\t\t<ClCompile Include=\"test_runner.cpp\" />\n";
+ project << "\t</ItemGroup>\n";
+ }
+
project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n"
"\t<ImportGroup Label=\"ExtensionTargets\">\n"
- "\t</ImportGroup>\n"
- "</Project>\n";
+ "\t</ImportGroup>\n";
+
+ if (setup.tests) {
+ // We override the normal target to ignore the exit code (this allows us to have a clean output and not message about the command exit code)
+ project << "\t\t<Target Name=\"PostBuildEvent\">\n"
+ << "\t\t\t<Message Text=\"Description: Run tests\" />\n"
+ << "\t\t\t<Exec Command=\"$(TargetPath)\" IgnoreExitCode=\"true\" />\n"
+ << "\t\t</Target>\n";
+ }
+
+ project << "</Project>\n";
// Output filter file if necessary
createFiltersFile(setup, name);
@@ -184,7 +203,7 @@ void MSBuildProvider::createFiltersFile(const BuildSetup &setup, const std::stri
error("Could not open \"" + filtersFile + "\" for writing");
filters << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
+ "<Project ToolsVersion=\"" << (_version >= 12 ? _version : 4) << ".0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
// Output the list of filters
filters << "\t<ItemGroup>\n";
@@ -245,7 +264,7 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s
bool disableEditAndContinue = find(_disableEditAndContinue.begin(), _disableEditAndContinue.end(), name) != _disableEditAndContinue.end();
// Nothing to add here, move along!
- if (!setup.devTools && name != setup.projectName && !enableLanguageExtensions && !disableEditAndContinue && warningsIterator == _projectWarnings.end())
+ if ((!setup.devTools || !setup.tests) && name != setup.projectName && !enableLanguageExtensions && !disableEditAndContinue && warningsIterator == _projectWarnings.end())
return;
std::string warnings = "";
@@ -257,7 +276,7 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s
"\t\t<ClCompile>\n";
// Language Extensions
- if (setup.devTools || name == setup.projectName || enableLanguageExtensions)
+ if (setup.devTools || setup.tests || name == setup.projectName || enableLanguageExtensions)
project << "\t\t\t<DisableLanguageExtensions>false</DisableLanguageExtensions>\n";
// Edit and Continue
@@ -271,18 +290,18 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s
project << "\t\t</ClCompile>\n";
// Link configuration for main project
- if (name == setup.projectName || setup.devTools) {
+ if (name == setup.projectName || setup.devTools || setup.tests) {
std::string libraries;
for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i)
libraries += *i + ".lib;";
project << "\t\t<Link>\n"
- "\t\t\t<OutputFile>$(OutDir)" << (setup.devTools ? name : setup.projectName) << ".exe</OutputFile>\n"
+ "\t\t\t<OutputFile>$(OutDir)" << ((setup.devTools || setup.tests) ? name : setup.projectName) << ".exe</OutputFile>\n"
"\t\t\t<AdditionalDependencies>" << libraries << "%(AdditionalDependencies)</AdditionalDependencies>\n"
"\t\t</Link>\n";
- if (!setup.devTools && setup.runBuildEvents) {
+ if (!setup.devTools && !setup.tests && setup.runBuildEvents) {
project << "\t\t<PreBuildEvent>\n"
"\t\t\t<Message>Generate revision</Message>\n"
"\t\t\t<Command>" << getPreBuildEvent() << "</Command>\n"
@@ -293,6 +312,11 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s
"\t\t\t<Message>Copy data files to the build folder</Message>\n"
"\t\t\t<Command>" << getPostBuildEvent(isWin32, setup.createInstaller) << "</Command>\n"
"\t\t</PostBuildEvent>\n";
+ } else if (setup.tests) {
+ project << "\t\t<PreBuildEvent>\n"
+ "\t\t\t<Message>Generate runner.cpp</Message>\n"
+ "\t\t\t<Command>" << getTestPreBuildEvent(setup) << "</Command>\n"
+ "\t\t</PreBuildEvent>\n";
}
}
@@ -314,9 +338,8 @@ void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstrea
definesList += REVISION_DEFINE ";";
properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
+ "<Project DefaultTargets=\"Build\" ToolsVersion=\"" << (_version >= 12 ? _version : 4) << ".0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
"\t<PropertyGroup>\n"
- "\t\t<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>\n"
"\t\t<_PropertySheetDisplayName>" << setup.projectDescription << "_Global</_PropertySheetDisplayName>\n"
"\t\t<ExecutablePath>$(" << LIBS_DEFINE << ")\\bin;$(ExecutablePath)</ExecutablePath>\n"
"\t\t<LibraryPath>$(" << LIBS_DEFINE << ")\\lib\\" << (bits == 32 ? "x86" : "x64") << ";$(LibraryPath)</LibraryPath>\n"
@@ -328,9 +351,9 @@ void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstrea
"\t\t<ClCompile>\n"
"\t\t\t<DisableLanguageExtensions>true</DisableLanguageExtensions>\n"
"\t\t\t<DisableSpecificWarnings>" << warnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n"
- "\t\t\t<AdditionalIncludeDirectories>$(" << LIBS_DEFINE << ")\\include;" << prefix << ";" << prefix << "\\engines;$(TargetDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
+ "\t\t\t<AdditionalIncludeDirectories>$(" << LIBS_DEFINE << ")\\include;" << prefix << ";" << prefix << "\\engines;" << (setup.tests ? prefix + "\\test\\cxxtest;" : "") << "$(TargetDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"
"\t\t\t<PreprocessorDefinitions>" << definesList << "%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
- "\t\t\t<ExceptionHandling>" << (setup.devTools ? "Sync" : "") << "</ExceptionHandling>\n";
+ "\t\t\t<ExceptionHandling>" << ((setup.devTools || setup.tests) ? "Sync" : "") << "</ExceptionHandling>\n";
#if NEEDS_RTTI
properties << "\t\t\t<RuntimeTypeInfo>true</RuntimeTypeInfo>\n";
@@ -346,7 +369,7 @@ void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstrea
"\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"
"\t\t\t<SubSystem>Console</SubSystem>\n";
- if (!setup.devTools)
+ if (!setup.devTools && !setup.tests)
properties << "\t\t\t<EntryPointSymbol>WinMainCRTStartup</EntryPointSymbol>\n";
properties << "\t\t</Link>\n"
@@ -368,12 +391,11 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
error("Could not open \"" + setup.outputDir + '/' + setup.projectDescription + "_" + outputType + (isWin32 ? "" : "64") + getPropertiesExtension() + "\" for writing");
properties << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
+ "<Project DefaultTargets=\"Build\" ToolsVersion=\"" << (_version >= 12 ? _version : 4) << ".0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"
"\t<ImportGroup Label=\"PropertySheets\">\n"
"\t\t<Import Project=\"" << setup.projectDescription << "_Global" << (isWin32 ? "" : "64") << ".props\" />\n"
"\t</ImportGroup>\n"
"\t<PropertyGroup>\n"
- "\t\t<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>\n"
"\t\t<_PropertySheetDisplayName>" << setup.projectDescription << "_" << outputType << outputBitness << "</_PropertySheetDisplayName>\n"
"\t\t<LinkIncremental>" << (isRelease ? "false" : "true") << "</LinkIncremental>\n"
"\t</PropertyGroup>\n"
@@ -383,7 +405,7 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
if (isRelease) {
properties << "\t\t\t<IntrinsicFunctions>true</IntrinsicFunctions>\n"
"\t\t\t<WholeProgramOptimization>true</WholeProgramOptimization>\n"
- "\t\t\t<PreprocessorDefinitions>WIN32;RELEASE_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
+ "\t\t\t<PreprocessorDefinitions>WIN32;DISABLE_GUI_BUILTIN_THEME;RELEASE_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
"\t\t\t<StringPooling>true</StringPooling>\n"
"\t\t\t<BufferSecurityCheck>false</BufferSecurityCheck>\n"
"\t\t\t<DebugInformationFormat></DebugInformationFormat>\n"
@@ -395,7 +417,7 @@ void MSBuildProvider::createBuildProp(const BuildSetup &setup, bool isRelease, b
"\t\t\t<SetChecksum>true</SetChecksum>\n";
} else {
properties << "\t\t\t<Optimization>Disabled</Optimization>\n"
- "\t\t\t<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
+ "\t\t\t<PreprocessorDefinitions>WIN32;DISABLE_GUI_BUILTIN_THEME;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n"
"\t\t\t<MinimalRebuild>true</MinimalRebuild>\n"
"\t\t\t<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\n"
"\t\t\t<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\n"
diff --git a/devtools/create_project/msvc.cpp b/devtools/create_project/msvc.cpp
index b8d2401af9..2fedadcba5 100644
--- a/devtools/create_project/msvc.cpp
+++ b/devtools/create_project/msvc.cpp
@@ -161,6 +161,16 @@ std::string MSVCProvider::getPreBuildEvent() const {
return cmdLine;
}
+std::string MSVCProvider::getTestPreBuildEvent(const BuildSetup &setup) const {
+ // Build list of folders containing tests
+ std::string target = "";
+
+ for (StringList::const_iterator it = setup.testDirs.begin(); it != setup.testDirs.end(); ++it)
+ target += " $(SolutionDir)" + *it + "*.h";
+
+ return "&quot;$(SolutionDir)../../test/cxxtest/cxxtestgen.py&quot; --runner=ParenPrinter --no-std --no-eh -o $(SolutionDir)test_runner.cpp" + target;
+}
+
std::string MSVCProvider::getPostBuildEvent(bool isWin32, bool createInstaller) const {
std::string cmdLine = "";
diff --git a/devtools/create_project/msvc.h b/devtools/create_project/msvc.h
index 5a854b596a..b9b93fe109 100644
--- a/devtools/create_project/msvc.h
+++ b/devtools/create_project/msvc.h
@@ -88,6 +88,13 @@ protected:
std::string getPreBuildEvent() const;
/**
+ * Get the command line for the test generator
+ *
+ * @param setup Description of the desired build setup.
+ */
+ std::string getTestPreBuildEvent(const BuildSetup &setup) const;
+
+ /**
* Get the command line for copying data files to the build directory.
*
* @param isWin32 Bitness of property file.
diff --git a/devtools/create_project/msvc12/create_project.sln b/devtools/create_project/msvc12/create_project.sln
new file mode 100644
index 0000000000..759d5430f5
--- /dev/null
+++ b/devtools/create_project/msvc12/create_project.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "create_project", "create_project.vcxproj", "{CF177559-077D-4A08-AABE-BE0FD35F6C63}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Debug|Win32.Build.0 = Debug|Win32
+ {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.ActiveCfg = Release|Win32
+ {CF177559-077D-4A08-AABE-BE0FD35F6C63}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/devtools/create_project/msvc12/create_project.vcxproj b/devtools/create_project/msvc12/create_project.vcxproj
new file mode 100644
index 0000000000..c26b1e5f45
--- /dev/null
+++ b/devtools/create_project/msvc12/create_project.vcxproj
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CF177559-077D-4A08-AABE-BE0FD35F6C63}</ProjectGuid>
+ <RootNamespace>create_project</RootNamespace>
+ <VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and $(VisualStudioVersion) == ''">$(VCTargetsPath11)</VCTargetsPath>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableLanguageExtensions>false</DisableLanguageExtensions>
+ <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ </Link>
+ <PostBuildEvent>
+ <Command>@echo off
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc12\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc11\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc10\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc9\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc8\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\codeblocks\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\iphone\"</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4003;4512;4127</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <PostBuildEvent>
+ <Command>@echo off
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc12\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc11\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc10\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc9\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\msvc8\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\codeblocks\"
+xcopy /Y "$(TargetPath)" "$(SolutionDir)\..\..\..\dists\iphone\"</Command>
+ </PostBuildEvent>
+ <PreBuildEvent>
+ <Command>
+ </Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\codeblocks.cpp" />
+ <ClCompile Include="..\create_project.cpp" />
+ <ClCompile Include="..\msbuild.cpp" />
+ <ClCompile Include="..\msvc.cpp" />
+ <ClCompile Include="..\visualstudio.cpp" />
+ <ClCompile Include="..\xcode.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\codeblocks.h" />
+ <ClInclude Include="..\config.h" />
+ <ClInclude Include="..\create_project.h" />
+ <ClInclude Include="..\msbuild.h" />
+ <ClInclude Include="..\msvc.h" />
+ <ClInclude Include="..\visualstudio.h" />
+ <ClInclude Include="..\xcode.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\scripts\installer.vbs" />
+ <None Include="..\scripts\postbuild.cmd" />
+ <None Include="..\scripts\prebuild.cmd" />
+ <None Include="..\scripts\revision.vbs" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/devtools/create_project/msvc12/create_project.vcxproj.filters b/devtools/create_project/msvc12/create_project.vcxproj.filters
new file mode 100644
index 0000000000..436d1d3436
--- /dev/null
+++ b/devtools/create_project/msvc12/create_project.vcxproj.filters
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{2e3580c8-ec3a-4c81-8351-b668c668db2a}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{31aaf58c-d3cb-4ed6-8eca-163b4a9b31a6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="scripts">
+ <UniqueIdentifier>{f980f6fb-41b6-4161-b035-58b200c85cad}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\codeblocks.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\create_project.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\msvc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\msbuild.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\visualstudio.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\xcode.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\codeblocks.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\create_project.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\msvc.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\msbuild.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\visualstudio.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\xcode.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\scripts\prebuild.cmd">
+ <Filter>scripts</Filter>
+ </None>
+ <None Include="..\scripts\revision.vbs">
+ <Filter>scripts</Filter>
+ </None>
+ <None Include="..\scripts\postbuild.cmd">
+ <Filter>scripts</Filter>
+ </None>
+ <None Include="..\scripts\installer.vbs">
+ <Filter>scripts</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/devtools/create_project/visualstudio.cpp b/devtools/create_project/visualstudio.cpp
index de2df96d78..23225d3435 100644
--- a/devtools/create_project/visualstudio.cpp
+++ b/devtools/create_project/visualstudio.cpp
@@ -83,7 +83,7 @@ void VisualStudioProvider::createProjectFile(const std::string &name, const std:
// Check for project-specific warnings:
std::map< std::string, std::list<std::string> >::iterator warningsIterator = _projectWarnings.find(name);
- if (setup.devTools || name == setup.projectName) {
+ if (setup.devTools || setup.tests || name == setup.projectName) {
std::string libraries;
for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i)
@@ -140,6 +140,11 @@ void VisualStudioProvider::createProjectFile(const std::string &name, const std:
else
addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
+ // Output auto-generated test runner
+ if (setup.tests) {
+ project << "\t\t<File RelativePath=\"test_runner.cpp\" />\n";
+ }
+
project << "\t</Files>\n"
"</VisualStudioProject>\n";
}
@@ -161,7 +166,7 @@ void VisualStudioProvider::outputConfiguration(const BuildSetup &setup, std::ost
}
void VisualStudioProvider::outputBuildEvents(std::ostream &project, const BuildSetup &setup, const bool isWin32) {
- if (!setup.devTools && setup.runBuildEvents) {
+ if (!setup.devTools && !setup.tests && setup.runBuildEvents) {
project << "\t\t\t<Tool\tName=\"VCPreBuildEventTool\"\n"
"\t\t\t\tCommandLine=\"" << getPreBuildEvent() << "\"\n"
"\t\t\t/>\n"
@@ -169,6 +174,17 @@ void VisualStudioProvider::outputBuildEvents(std::ostream &project, const BuildS
"\t\t\t\tCommandLine=\"" << getPostBuildEvent(isWin32, setup.createInstaller) << "\"\n"
"\t\t\t/>\n";
}
+
+ // Generate runner file before build for tests
+ if (setup.tests) {
+ project << "\t\t\t<Tool\tName=\"VCPreBuildEventTool\"\n"
+ "\t\t\t\tCommandLine=\"" << getTestPreBuildEvent(setup) << "\"\n"
+ "\t\t\t/>\n";
+
+ project << "\t\t\t<Tool\tName=\"VCPostBuildEventTool\"\n"
+ "\t\t\t\tCommandLine=\"$(TargetPath)\" IgnoreExitCode=\"true\"\n"
+ "\t\t\t/>\n";
+ }
}
void VisualStudioProvider::writeReferences(const BuildSetup &setup, std::ofstream &output) {
@@ -212,9 +228,9 @@ void VisualStudioProvider::outputGlobalPropFile(const BuildSetup &setup, std::of
"\t\tName=\"VCCLCompilerTool\"\n"
"\t\tDisableLanguageExtensions=\"" << (setup.devTools ? "false" : "true") << "\"\n"
"\t\tDisableSpecificWarnings=\"" << warnings << "\"\n"
- "\t\tAdditionalIncludeDirectories=\"" << prefix << ";" << prefix << "\\engines;$(" << LIBS_DEFINE << ")\\include;$(TargetDir)\"\n"
+ "\t\tAdditionalIncludeDirectories=\"" << prefix << ";" << prefix << "\\engines;$(" << LIBS_DEFINE << ")\\include;" << (setup.tests ? prefix + "\\test\\cxxtest;" : "") << "$(TargetDir)\"\n"
"\t\tPreprocessorDefinitions=\"" << definesList << "\"\n"
- "\t\tExceptionHandling=\"" << (setup.devTools ? "1" : "0") << "\"\n";
+ "\t\tExceptionHandling=\"" << ((setup.devTools || setup.tests) ? "1" : "0") << "\"\n";
#if NEEDS_RTTI
properties << "\t\tRuntimeTypeInfo=\"true\"\n";
@@ -235,7 +251,7 @@ void VisualStudioProvider::outputGlobalPropFile(const BuildSetup &setup, std::of
"\t\tIgnoreDefaultLibraryNames=\"\"\n"
"\t\tSubSystem=\"1\"\n";
- if (!setup.devTools)
+ if (!setup.devTools && !setup.tests)
properties << "\t\tEntryPointSymbol=\"WinMainCRTStartup\"\n";
properties << "\t\tAdditionalLibraryDirectories=\"$(" << LIBS_DEFINE << ")\\lib\\" << ((bits == 32) ? "x86" : "x64") << "\"\n"
diff --git a/devtools/create_teenagent/static_tables.h b/devtools/create_teenagent/static_tables.h
index 6e7fdfe91c..5c9b5b3d21 100644
--- a/devtools/create_teenagent/static_tables.h
+++ b/devtools/create_teenagent/static_tables.h
@@ -15148,7 +15148,7 @@ const static char* dialog_162[] = {
};
// Note:
-// The usage of this in the engine overlaps the previous dialog i.e. the
+// The usage of this in the engine overlaps the previous dialog i.e. the
// starting offset used is two bytes early, thus implicitly changing the
// first command of this dialog from NEW_LINE to CHANGE_CHARACTER.
const static char* dialog_163[] = {
diff --git a/devtools/credits.pl b/devtools/credits.pl
index 06df7fa50e..7d39730c63 100755
--- a/devtools/credits.pl
+++ b/devtools/credits.pl
@@ -754,10 +754,6 @@ begin_credits("Credits");
add_person("Angus Lees", "Gus", "");
end_section();
- begin_section("BADA");
- add_person("Chris Warren-Smith", "", "");
- end_section();
-
begin_section("Dreamcast");
add_person("Marcus Comstedt", "", "");
end_section();
@@ -818,6 +814,10 @@ begin_credits("Credits");
add_person("Lars Persson", "AnotherGuest", "");
end_section();
+ begin_section("Tizen / BADA");
+ add_person("Chris Warren-Smith", "", "");
+ end_section();
+
begin_section("WebOS");
add_person("Klaus Reimer", "kayahr", "");
end_section();
diff --git a/devtools/extract_mort/extract_mort.cpp b/devtools/extract_mort/extract_mort.cpp
new file mode 100644
index 0000000000..159309c0fa
--- /dev/null
+++ b/devtools/extract_mort/extract_mort.cpp
@@ -0,0 +1,428 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * This is a utility for extracting needed resource data from different language
+ * version of the Lure of the Temptress lure.exe executable files into a new file
+ * lure.dat - this file is required for the ScummVM Lure of the Temptress module
+ * to work properly
+ */
+
+// 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common/endian.h"
+
+enum AccessMode {
+ kFileReadMode = 1,
+ kFileWriteMode = 2
+};
+
+class File {
+private:
+ FILE *f;
+public:
+ bool open(const char *filename, AccessMode mode = kFileReadMode) {
+ f = fopen(filename, (mode == kFileReadMode) ? "rb" : "wb");
+ return (f != NULL);
+ }
+ void close() {
+ fclose(f);
+ f = NULL;
+ }
+ int seek(int32 offset, int whence = SEEK_SET) {
+ return fseek(f, offset, whence);
+ }
+ long read(void *buffer, int len) {
+ return fread(buffer, 1, len, f);
+ }
+ void write(const void *buffer, int len) {
+ fwrite(buffer, 1, len, f);
+ }
+ byte readByte() {
+ byte v;
+ read(&v, sizeof(byte));
+ return v;
+ }
+ uint16 readWord() {
+ uint16 v;
+ read(&v, sizeof(uint16));
+ return FROM_LE_16(v);
+ }
+ uint32 readLong() {
+ uint32 v;
+ read(&v, sizeof(uint32));
+ return FROM_LE_32(v);
+ }
+ void readString(char *sLine) {
+ while ((*sLine = readByte()) != '\n')
+ ++sLine;
+
+ *sLine = '\0';
+ }
+ void writeByte(byte v) {
+ write(&v, sizeof(byte));
+ }
+ void writeWord(uint16 v) {
+ uint16 vTemp = TO_LE_16(v);
+ write(&vTemp, sizeof(uint16));
+ }
+ void writeLong(uint32 v) {
+ uint32 vTemp = TO_LE_32(v);
+ write(&vTemp, sizeof(uint32));
+ }
+ void writeString(const char *s) {
+ fprintf(f, "%s", s);
+ }
+ uint32 pos() {
+ return ftell(f);
+ }
+ uint32 size() {
+ int pos = ftell(f);
+ fseek (f, 0, SEEK_END);
+ int end = ftell (f);
+ fseek (f, pos, SEEK_SET);
+
+ return end;
+ }
+};
+
+File textFile, txxInp, txxNtp;
+int _version;
+
+/*-------------------------------------------------------------------------*/
+
+#define BUFFER_SIZE 32768
+
+const byte tabdrFr[32] = {
+ 32, 101, 115, 97, 114, 105, 110,
+ 117, 116, 111, 108, 13, 100, 99,
+ 112, 109, 46, 118, 130, 39, 102,
+ 98, 44, 113, 104, 103, 33, 76,
+ 85, 106, 30, 31
+};
+
+const byte tab30Fr[32] = {
+ 69, 67, 74, 138, 133, 120, 77, 122,
+ 121, 68, 65, 63, 73, 80, 83, 82,
+ 156, 45, 58, 79, 49, 86, 78, 84,
+ 71, 81, 64, 66, 135, 34, 136, 91
+};
+
+const byte tab31Fr[32]= {
+ 93, 47, 48, 53, 50, 70, 124, 75,
+ 72, 147, 140, 150, 151, 57, 56, 51,
+ 107, 139, 55, 89, 131, 37, 54, 88,
+ 119, 0, 0, 0, 0, 0, 0, 0
+};
+
+const byte tabdrDe[32] = {
+ 0x20, 0x65, 0x6E, 0x69, 0x73, 0x72, 0x74,
+ 0x68, 0x61, 0x75, 0x0D, 0x63, 0x6C, 0x64,
+ 0x6D, 0x6F, 0x67, 0x2E, 0x62, 0x66, 0x53,
+ 0x2C, 0x77, 0x45, 0x7A, 0x6B, 0x44, 0x76,
+ 0x9C, 0x47, 0x1E, 0x1F
+};
+
+const byte tab30De[32] = {
+ 0x49, 0x4D, 0x21, 0x42, 0x4C, 0x70, 0x41, 0x52,
+ 0x57, 0x4E, 0x48, 0x3F, 0x46, 0x50, 0x55, 0x4B,
+ 0x5A, 0x4A, 0x54, 0x31, 0x4F, 0x56, 0x79, 0x3A,
+ 0x6A, 0x5B, 0x5D, 0x40, 0x22, 0x2F, 0x30, 0x35
+};
+
+const byte tab31De[32]= {
+ 0x78, 0x2D, 0x32, 0x82, 0x43, 0x39, 0x33, 0x38,
+ 0x7C, 0x27, 0x37, 0x3B, 0x25, 0x28, 0x29, 0x36,
+ 0x51, 0x59, 0x71, 0x81, 0x87, 0x88, 0x93, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const byte *tabdr, *tab30, *tab31;
+uint16 ctrlChar;
+
+/**
+ * Extracts a single character from the game data
+ */
+static void extractCharacter(unsigned char &c, uint &idx, uint &pt, bool &the_end, const uint16 *strData) {
+ uint16 oct, ocd;
+
+ /* 5-8 */
+ oct = FROM_LE_16(strData[idx]);
+
+ oct = ((uint16)(oct << (16 - pt))) >> (16 - pt);
+ if (pt < 6) {
+ idx = idx + 1;
+ oct = oct << (5 - pt);
+ pt = pt + 11;
+ oct = oct | (FROM_LE_16(strData[idx]) >> pt);
+ } else {
+ pt = pt - 5;
+ oct = (uint)oct >> pt;
+ }
+
+ if (oct == ctrlChar) {
+ c = '$';
+ the_end = true;
+ } else if (oct == 30 || oct == 31) {
+ ocd = FROM_LE_16(strData[idx]);
+ ocd = (uint16)(ocd << (16 - pt)) >> (16 - pt);
+ if (pt < 6) {
+ idx = idx + 1;
+ ocd = ocd << (5 - pt);
+ pt = pt + 11;
+ ocd = ocd | (FROM_LE_16(strData[idx]) >> pt);
+ } else {
+ pt = pt - 5;
+ ocd = (uint)ocd >> pt;
+ }
+ if (oct == 30)
+ c = (char)tab30[ocd];
+ else
+ c = (char)tab31[ocd];
+
+ if (c == '\0')
+ the_end = true;
+ } else {
+ c = (char)tabdr[oct];
+ }
+}
+
+/**
+ * Puts a compressed 5-bit value into the string data buffer
+ */
+static void addCompressedValue(int oct, int &indis, int &point, uint16 *strData) {
+ // Write out the part of the value that fits into the current word
+ if (point < 5)
+ strData[indis] |= oct >> (5 - point);
+ else
+ strData[indis] |= oct << (point - 5);
+
+ // Handling of there's any overlap into the next word
+ if (point < 5) {
+ // Overlapping into next word
+ ++indis;
+
+ // Get the bits that fall into the next word and set it
+ int remainder = oct & ((1 << (5 - point)) - 1);
+ strData[indis] |= remainder << (16 - (5 - point));
+
+ point += -5 + 16;
+ } else {
+ point -= 5;
+ if (point == 0) {
+ point = 16;
+ ++indis;
+ }
+ }
+}
+
+/**
+ * Compresses a single passed character and stores it in the compressed strings buffer
+ */
+static void compressCharacter(unsigned char ch, int &indis, int &point, uint16 *strData) {
+ if (ch == '$') {
+ // End of string
+ addCompressedValue(11, indis, point, strData);
+ return;
+ }
+
+ // Scan through the tabdr array for a match
+ for (int idx = 0; idx < 30; ++idx) {
+ if ((idx != 11) && (tabdr[idx] == ch)) {
+ addCompressedValue(idx, indis, point, strData);
+ return;
+ }
+ }
+
+ // Scan through the tab30 array
+ for (int idx = 0; idx < 32; ++idx) {
+ if (tab30[idx] == ch) {
+ addCompressedValue(30, indis, point, strData);
+ addCompressedValue(idx, indis, point, strData);
+ return;
+ }
+ }
+
+ // Scan through the tab31 array
+ for (int idx = 0; idx < 32; ++idx) {
+ if (tab31[idx] == ch) {
+ addCompressedValue(31, indis, point, strData);
+ addCompressedValue(idx, indis, point, strData);
+ return;
+ }
+ }
+
+ printf("Encountered invalid character '%c' when compressing strings\n", ch);
+ exit(1);
+}
+
+/**
+ * string extractor
+ */
+static void export_strings(const char *textFilename) {
+ char buffer[BUFFER_SIZE];
+ uint16 *strData;
+
+ // Open input and output files
+ if (!txxInp.open("TXX.INP", kFileReadMode)) {
+ if (!txxInp.open("TXX.MOR", kFileReadMode)) {
+ printf("Missing TXX.INP/MOR");
+ exit(-1);
+ }
+ }
+ if (!txxNtp.open("TXX.NTP", kFileReadMode)) {
+ if (!txxNtp.open("TXX.IND", kFileReadMode)) {
+ printf("Missing TXX.NTP/IND");
+ exit(-1);
+ }
+ }
+ textFile.open(textFilename, kFileWriteMode);
+
+ // Read all the compressed string data into a buffer
+ printf("%d %d", txxInp.size(), txxNtp.size());
+ strData = (uint16 *)malloc(txxInp.size());
+ txxInp.read(strData, txxInp.size());
+
+ // Loop through getting each string
+ for (unsigned int strIndex = 0; strIndex < (txxNtp.size() / 3); ++strIndex) {
+ uint indis = txxNtp.readWord();
+ uint point = txxNtp.readByte();
+
+ // Extract the string
+ int charIndex = 0;
+ unsigned char ch;
+ bool endFlag = false;
+ do {
+ extractCharacter(ch, indis, point, endFlag, strData);
+ buffer[charIndex++] = ch;
+ if (charIndex == BUFFER_SIZE) {
+ printf("Extracted string exceeded allowed buffer size.\n");
+ exit(1);
+ }
+
+ if (indis >= (txxInp.size() / 2))
+ endFlag = true;
+ } while (!endFlag);
+
+ // Write out the string
+ buffer[charIndex++] = '\n';
+ buffer[charIndex] = '\0';
+ textFile.writeString(buffer);
+ }
+
+ // Close the files and free the buffer
+ free(strData);
+ txxInp.close();
+ txxNtp.close();
+ textFile.close();
+}
+
+/**
+ * string importer
+ */
+static void import_strings(const char *textFilename) {
+ // Open input and output files
+ if (!txxInp.open("TXX.INP", kFileWriteMode)) {
+ printf("Missing TXX data file");
+ exit(-1);
+ }
+ if (!txxNtp.open("TXX.NTP", kFileWriteMode)) {
+ printf("Missing TXX index file");
+ exit(-1);
+ }
+ textFile.open(textFilename, kFileReadMode);
+
+ // Set up a buffer for the output compressed strings
+ uint16 strData[BUFFER_SIZE];
+ memset(strData, 0, BUFFER_SIZE);
+ char sLine[BUFFER_SIZE];
+
+ int indis = 0;
+ int point = 16;
+
+ while (textFile.pos() < textFile.size()) {
+ // Read in the next source line
+ textFile.readString(sLine);
+
+ // Write out the index entry for the string
+ txxNtp.writeWord(indis);
+ txxNtp.writeByte(point);
+
+ // Loop through writing out the characters to the compressed data buffer
+ char *s = sLine;
+ while (*s) {
+ compressCharacter(*s, indis, point, strData);
+ ++s;
+ }
+ }
+
+ // Write out the compressed data
+ if (point != 16)
+ ++indis;
+ txxInp.write(strData, indis * 2);
+
+ // Close the files
+ txxInp.close();
+ txxNtp.close();
+ textFile.close();
+}
+
+
+int main(int argc, char *argv[]) {
+ if (argc != 4) {
+ printf("Format: %s export|import v1|v2 output_file\n", argv[0]);
+ printf("where:\nv1: French DOS version\nv2: German DOS version\n");
+ printf("The program must be run from the directory with the Mortville Manor game files.\n");
+ exit(0);
+ }
+
+ if (!strcmp(argv[2], "v1")) {
+ tab30 = tab30Fr;
+ tab31 = tab31Fr;
+ tabdr = tabdrFr;
+ ctrlChar = 11;
+ } else if (!strcmp(argv[2], "v2")) {
+ tab30 = tab30De;
+ tab31 = tab31De;
+ tabdr = tabdrDe;
+ ctrlChar = 10;
+ } else {
+ printf("Unknown version");
+ exit(-1);
+ }
+
+ // Do the processing
+ if (!strcmp(argv[1], "export"))
+ export_strings(argv[3]);
+ else if (!strcmp(argv[1], "import"))
+ import_strings(argv[3]);
+ else
+ printf("Unknown operation specified\n");
+}
diff --git a/devtools/extract_mort/module.mk b/devtools/extract_mort/module.mk
new file mode 100644
index 0000000000..cbdcd251d9
--- /dev/null
+++ b/devtools/extract_mort/module.mk
@@ -0,0 +1,11 @@
+
+MODULE := devtools/extract_mort
+
+MODULE_OBJS := \
+ extract_mort.o \
+
+# Set the name of the executable
+TOOL_EXECUTABLE := extract_mort
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/devtools/scumm-md5.txt b/devtools/scumm-md5.txt
index 6e3bae1d7e..450860b587 100644
--- a/devtools/scumm-md5.txt
+++ b/devtools/scumm-md5.txt
@@ -654,6 +654,7 @@ pajama2 Pajama Sam 2: Thunder and Lightning Aren't so Frightening
e5563c8358443c4352fcddf7402a5e0a -1 fr Windows HE 98.5 - - gist974
c6907d44f1166941d982864cd42cdc89 -1 de All HE 99 - - nachbarnebenan
f8be685007a8b425ba2a455da732f59f -1 fr Mac HE 99 - - alamaz
+ 7477bc23d0383516c5e310cd8771dcc9 -1 fr Windows HE 99 - - Strangerke
32709cbeeb3044b34129950860a83f14 -1 ru Windows HE 99 - - sev
1af4eb581a33d808707d66d50e084dca -1 he Windows HE 99 - - Matan Bareket
diff --git a/devtools/skycpt/cptcompiler.cpp b/devtools/skycpt/cptcompiler.cpp
index 2c7d33c73b..657f51b8a0 100644
--- a/devtools/skycpt/cptcompiler.cpp
+++ b/devtools/skycpt/cptcompiler.cpp
@@ -376,6 +376,7 @@ void doCompile(FILE *inf, FILE *debOutf, FILE *resOutf, TextFile *cptDef, FILE *
uint32 asciiSize = (uint32)(asciiPos - asciiBuf);
fwrite(&asciiSize, 1, 4, debOutf);
fwrite(asciiBuf, 1, asciiSize, debOutf);
+ free(asciiBuf);
// the direct links...
fwrite(&dlinkCount, 2, 1, debOutf);
@@ -438,6 +439,8 @@ void doCompile(FILE *inf, FILE *debOutf, FILE *resOutf, TextFile *cptDef, FILE *
diffNo++;
}
}
+ fclose(dif);
+ free(resCpts);
assert(diffDest <= 8192);
fwrite(&diffNo, 1, 2, debOutf);
fwrite(&diffDest, 1, 2, debOutf);
diff --git a/dists/engine-data/README b/dists/engine-data/README
index c9c4bd4817..9bbb006d17 100644
--- a/dists/engine-data/README
+++ b/dists/engine-data/README
@@ -16,6 +16,11 @@ scripts, from.
lure.dat
TODO
+mort.dat:
+File created partially by extracting font data from the French executable. It
+also contains the French and German translation, as well as a custom-made
+English translation.
+
queen.tbl:
'queen.tbl' contains a list of filenames, filesizes and offsets for the
individual files saved in QUEEN.1. This data was originally included in the
diff --git a/dists/engine-data/mort.dat b/dists/engine-data/mort.dat
new file mode 100644
index 0000000000..fca30ab238
--- /dev/null
+++ b/dists/engine-data/mort.dat
Binary files differ
diff --git a/dists/msvc10/create_msvc10.bat b/dists/msvc10/create_msvc10.bat
index 5616c2cc8b..be0434fc50 100644
--- a/dists/msvc10/create_msvc10.bat
+++ b/dists/msvc10/create_msvc10.bat
@@ -10,6 +10,8 @@ if "%~1"=="/all" goto all
if "%~1"=="/ALL" goto all
if "%~1"=="/tools" goto tools
if "%~1"=="/TOOLS" goto tools
+if "%~1"=="/tests" goto tests
+if "%~1"=="/TESTS" goto tests
if "%~1"=="/clean" goto clean_check
if "%~1"=="/CLEAN" goto clean_check
if "%~1"=="/help" goto command_help
@@ -70,6 +72,13 @@ echo.
create_project ..\.. --tools --msvc --msvc-version 10
goto done
+:tests
+echo.
+echo Creating tests project files
+echo.
+create_project ..\.. --tests --msvc --msvc-version 10
+goto done
+
:clean_check
echo.
set cleananswer=N
@@ -88,6 +97,7 @@ del /Q *.props > NUL 2>&1
del /Q *.sln* > NUL 2>&1
del /Q scummvm* > NUL 2>&1
del /Q devtools* > NUL 2>&1
+del /Q test_runner.cpp > NUL 2>&1
goto done
:done
diff --git a/dists/msvc11/create_msvc11.bat b/dists/msvc11/create_msvc11.bat
index b6a5413e3b..fc5471f46f 100644
--- a/dists/msvc11/create_msvc11.bat
+++ b/dists/msvc11/create_msvc11.bat
@@ -10,6 +10,8 @@ if "%~1"=="/all" goto all
if "%~1"=="/ALL" goto all
if "%~1"=="/tools" goto tools
if "%~1"=="/TOOLS" goto tools
+if "%~1"=="/tests" goto tests
+if "%~1"=="/TESTS" goto tests
if "%~1"=="/clean" goto clean_check
if "%~1"=="/CLEAN" goto clean_check
if "%~1"=="/help" goto command_help
@@ -70,6 +72,13 @@ echo.
create_project ..\.. --tools --msvc --msvc-version 11
goto done
+:tests
+echo.
+echo Creating tests project files
+echo.
+create_project ..\.. --tests --msvc --msvc-version 11
+goto done
+
:clean_check
echo.
set cleananswer=N
@@ -88,6 +97,7 @@ del /Q *.props > NUL 2>&1
del /Q *.sln* > NUL 2>&1
del /Q scummvm* > NUL 2>&1
del /Q devtools* > NUL 2>&1
+del /Q test_runner.cpp > NUL 2>&1
goto done
:done
diff --git a/dists/msvc12/create_msvc12.bat b/dists/msvc12/create_msvc12.bat
new file mode 100644
index 0000000000..d99001edb1
--- /dev/null
+++ b/dists/msvc12/create_msvc12.bat
@@ -0,0 +1,105 @@
+@echo off
+
+echo.
+echo Automatic creation of the MSVC12 project files
+echo.
+
+if "%~1"=="/stable" goto stable
+if "%~1"=="/STABLE" goto stable
+if "%~1"=="/all" goto all
+if "%~1"=="/ALL" goto all
+if "%~1"=="/tools" goto tools
+if "%~1"=="/TOOLS" goto tools
+if "%~1"=="/tests" goto tests
+if "%~1"=="/TESTS" goto tests
+if "%~1"=="/clean" goto clean_check
+if "%~1"=="/CLEAN" goto clean_check
+if "%~1"=="/help" goto command_help
+if "%~1"=="/HELP" goto command_help
+if "%~1"=="/?" goto command_help
+
+if "%~1"=="" goto check_tool
+
+echo Invalid command parameter: %~1
+echo.
+
+:command_help
+echo Valid command parameters are:
+echo stable Generated stable engines project files
+echo all Generate all engines project files
+echo tools Generate project files for the devtools
+echo clean Clean generated project files
+echo help Show help message
+goto done
+
+:check_tool
+if not exist create_project.exe goto no_tool
+
+:question
+echo.
+set batchanswer=S
+set /p batchanswer="Enable stable engines only, or all engines? (S/a)"
+if "%batchanswer%"=="s" goto stable
+if "%batchanswer%"=="S" goto stable
+if "%batchanswer%"=="a" goto all
+if "%batchanswer%"=="A" goto all
+goto question
+
+:no_tool
+echo create_project.exe not found in the current folder.
+echo You need to build it first and copy it in this
+echo folder
+goto done
+
+:all
+echo.
+echo Creating project files with all engines enabled (stable and unstable)
+echo.
+create_project ..\.. --enable-all-engines --msvc --msvc-version 12 --build-events
+goto done
+
+:stable
+echo.
+echo Creating normal project files, with only the stable engines enabled
+echo.
+create_project ..\.. --msvc --msvc-version 12
+goto done
+
+:tools
+echo.
+echo Creating tools project files
+echo.
+create_project ..\.. --tools --msvc --msvc-version 12
+goto done
+
+:tests
+echo.
+echo Creating tests project files
+echo.
+create_project ..\.. --tests --msvc --msvc-version 12
+goto done
+
+:clean_check
+echo.
+set cleananswer=N
+set /p cleananswer="This will remove all project files. Are you sure you want to continue? (N/y)"
+if "%cleananswer%"=="n" goto done
+if "%cleananswer%"=="N" goto done
+if "%cleananswer%"=="y" goto clean
+if "%cleananswer%"=="Y" goto clean
+goto clean_check
+
+:clean
+echo.
+echo Removing all project files
+del /Q *.vcxproj* > NUL 2>&1
+del /Q *.props > NUL 2>&1
+del /Q *.sln* > NUL 2>&1
+del /Q scummvm* > NUL 2>&1
+del /Q devtools* > NUL 2>&1
+del /Q test_runner.cpp > NUL 2>&1
+goto done
+
+:done
+echo.
+pause
diff --git a/dists/msvc12/readme.txt b/dists/msvc12/readme.txt
new file mode 100644
index 0000000000..760f9ff601
--- /dev/null
+++ b/dists/msvc12/readme.txt
@@ -0,0 +1,6 @@
+The Visual Studio project files can now be created automatically from the GCC
+files using the create_project tool inside the /devtools/create_project folder.
+
+To create the default project files, build create_project.exe, copy it inside
+this folder and run the create_msvc12.bat file for a default build. You can run
+create_project.exe with no parameters to check the possible command-line options
diff --git a/dists/msvc8/create_msvc8.bat b/dists/msvc8/create_msvc8.bat
index 2261c9bcec..1e0d339001 100644
--- a/dists/msvc8/create_msvc8.bat
+++ b/dists/msvc8/create_msvc8.bat
@@ -10,6 +10,8 @@ if "%~1"=="/all" goto all
if "%~1"=="/ALL" goto all
if "%~1"=="/tools" goto tools
if "%~1"=="/TOOLS" goto tools
+if "%~1"=="/tests" goto tests
+if "%~1"=="/TESTS" goto tests
if "%~1"=="/clean" goto clean_check
if "%~1"=="/CLEAN" goto clean_check
if "%~1"=="/help" goto command_help
@@ -70,6 +72,13 @@ echo.
create_project ..\.. --tools --msvc --msvc-version 8
goto done
+:tests
+echo.
+echo Creating tests project files
+echo.
+create_project ..\.. --tests --msvc --msvc-version 8
+goto done
+
:clean_check
echo.
set cleananswer=N
@@ -88,6 +97,7 @@ del /Q *.vsprops > NUL 2>&1
del /Q *.sln* > NUL 2>&1
del /Q scummvm* > NUL 2>&1
del /Q devtools* > NUL 2>&1
+del /Q test_runner.cpp
goto done
:done
diff --git a/dists/msvc9/create_msvc9.bat b/dists/msvc9/create_msvc9.bat
index 1622cd9037..34bcccdd7b 100644
--- a/dists/msvc9/create_msvc9.bat
+++ b/dists/msvc9/create_msvc9.bat
@@ -10,6 +10,8 @@ if "%~1"=="/all" goto all
if "%~1"=="/ALL" goto all
if "%~1"=="/tools" goto tools
if "%~1"=="/TOOLS" goto tools
+if "%~1"=="/tests" goto tests
+if "%~1"=="/TESTS" goto tests
if "%~1"=="/clean" goto clean_check
if "%~1"=="/CLEAN" goto clean_check
if "%~1"=="/help" goto command_help
@@ -70,6 +72,13 @@ echo.
create_project ..\.. --tools --msvc --msvc-version 9
goto done
+:tests
+echo.
+echo Creating tests project files
+echo.
+create_project ..\.. --tests --msvc --msvc-version 9
+goto done
+
:clean_check
echo.
set cleananswer=N
@@ -88,6 +97,7 @@ del /Q *.vsprops > NUL 2>&1
del /Q *.sln* > NUL 2>&1
del /Q scummvm* > NUL 2>&1
del /Q devtools* > NUL 2>&1
+del /Q test_runner.cpp
goto done
:done
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index f3fa14c95a..037db3ef62 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -32,6 +32,9 @@ kyra.dat FILE "dists/engine-data/kyra.dat"
#if ENABLE_LURE == STATIC_PLUGIN
lure.dat FILE "dists/engine-data/lure.dat"
#endif
+#if ENABLE_MORTEVIELLE == STATIC_PLUGIN
+mort.dat FILE "dists/engine-data/mort.dat"
+#endif
#if ENABLE_NEVERHOOD == STATIC_PLUGIN
neverhood.dat FILE "dists/engine-data/neverhood.dat"
#endif
diff --git a/dists/scummvm.rc.in b/dists/scummvm.rc.in
index b7a87f4e3d..c18c18ef63 100644
--- a/dists/scummvm.rc.in
+++ b/dists/scummvm.rc.in
@@ -32,6 +32,9 @@ kyra.dat FILE "dists/engine-data/kyra.dat"
#if ENABLE_LURE == STATIC_PLUGIN
lure.dat FILE "dists/engine-data/lure.dat"
#endif
+#if ENABLE_MORTEVIELLE == STATIC_PLUGIN
+mort.dat FILE "dists/engine-data/mort.dat"
+#endif
#if ENABLE_NEVERHOOD == STATIC_PLUGIN
neverhood.dat FILE "dists/engine-data/neverhood.dat"
#endif
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index b1d1008b60..fd0c8dc2da 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -29,7 +29,7 @@
#include "common/system.h"
#include "common/textconsole.h"
#include "common/translation.h"
-
+#include "gui/EventRecorder.h"
#include "engines/advancedDetector.h"
#include "engines/obsolete.h"
@@ -301,6 +301,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine)
return Common::kUserCanceled;
debug(2, "Running %s", gameDescriptor.description().c_str());
+ initSubSystems(agdDesc);
if (!createInstance(syst, engine, agdDesc))
return Common::kNoGameDataFoundError;
else
@@ -606,3 +607,11 @@ AdvancedMetaEngine::AdvancedMetaEngine(const void *descs, uint descItemSize, con
_maxScanDepth = 1;
_directoryGlobs = NULL;
}
+
+void AdvancedMetaEngine::initSubSystems(const ADGameDescription *gameDesc) const {
+#ifdef ENABLE_EVENTRECORDER
+ if (gameDesc) {
+ g_eventRec.processGameDescription(gameDesc);
+ }
+#endif
+}
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 3eec33abe5..71d2c4a446 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -280,6 +280,9 @@ protected:
return 0;
}
+private:
+ void initSubSystems(const ADGameDescription *gameDesc) const;
+
protected:
/**
* Detect games in specified directory.
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 1c342183cd..57561c00ee 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -598,8 +598,8 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_console = NULL;
_egoHoldKey = false;
-
-
+
+
}
void AgiEngine::initialize() {
diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp
index b7d2801076..17d980dfd8 100644
--- a/engines/agi/preagi_troll.cpp
+++ b/engines/agi/preagi_troll.cpp
@@ -190,6 +190,7 @@ void TrollEngine::inventory() {
break;
case IDI_TRO_MAX_TREASURE:
drawStr(3, 17, kColorDefault, IDS_TRO_TREASURE_2);
+ break;
default:
sprintf(tmp, IDS_TRO_TREASURE_4, _treasuresLeft);
drawStr(20, 10, kColorDefault, tmp);
@@ -219,6 +220,7 @@ void TrollEngine::waitAnyKeyIntro() {
switch (iMsg) {
case 200:
iMsg = 0;
+ // fall through
case 0:
drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_2);
_gfx->doUpdate();
diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp
index bbe9ddd0c6..1be385be37 100644
--- a/engines/agi/preagi_winnie.cpp
+++ b/engines/agi/preagi_winnie.cpp
@@ -985,6 +985,7 @@ void WinnieEngine::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
}
break;
}
+ break;
default:
if (!event.kbd.flags) { // if the control/alt/shift keys are not pressed
keyHelp();
diff --git a/engines/cge/cge.cpp b/engines/cge/cge.cpp
index 6cc0c45963..af7e91f7eb 100644
--- a/engines/cge/cge.cpp
+++ b/engines/cge/cge.cpp
@@ -25,7 +25,6 @@
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/error.h"
-#include "common/EventRecorder.h"
#include "common/file.h"
#include "common/fs.h"
#include "engines/advancedDetector.h"
diff --git a/engines/cge/detection.cpp b/engines/cge/detection.cpp
index d29c1224fd..3b01421903 100644
--- a/engines/cge/detection.cpp
+++ b/engines/cge/detection.cpp
@@ -121,7 +121,7 @@ static const CgeGameDescription gameDescriptions[] = {
"sfinx", "Sfinx Freeware",
{
{"vol.cat", 0, "21197b287d397c53261b6616bf0dd880", 129024},
- {"vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844},
+ {"vol.dat", 0, "de14291869a8eb7c2732ab783c7542ef", 34180844},
AD_LISTEND
},
Common::PL_POL, Common::kPlatformDOS, ADGF_NO_FLAGS, GUIO0()
diff --git a/engines/cge/snail.cpp b/engines/cge/snail.cpp
index edb8972040..b9030efb4d 100644
--- a/engines/cge/snail.cpp
+++ b/engines/cge/snail.cpp
@@ -494,7 +494,7 @@ void CGEEngine::snGame(Sprite *spr, int num) {
_sprK3->step(newRandom(6));
// check the ALT key as it's the solution of the puzzle
- // the test has been restricted to some specific OSes
+ // the test has been restricted to some specific OSes
// in order to avoid some obvious issues (like Android, iOS, NDS, N64...)
// Not perfect, but at least better than nothing.
#if defined(WIN32) || defined(UNIX) || defined(MACOSX) || defined(MOTOEZX) || defined(LINUPY) || defined(LINUXMOTO_SDL)
diff --git a/engines/configure.engines b/engines/configure.engines
index 15aa11d0ef..963b9f774f 100644
--- a/engines/configure.engines
+++ b/engines/configure.engines
@@ -25,6 +25,7 @@ add_engine lastexpress "The Last Express" no "" "" "16bit"
add_engine lure "Lure of the Temptress" yes
add_engine made "MADE" yes
add_engine mohawk "Mohawk" yes "cstime myst riven" "Living Books"
+add_engine mortevielle "Mortevielle" no
add_engine cstime "Where in Time is Carmen Sandiego?" no
add_engine riven "Riven: The Sequel to Myst" no "" "" "16bit"
add_engine myst "Myst" no "" "" "16bit"
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
index e547503bee..c4d1c4c761 100644
--- a/engines/drascula/drascula.h
+++ b/engines/drascula/drascula.h
@@ -661,7 +661,7 @@ public:
void animation_3_1(); // John talks with the bartender to book a room
void animation_4_1(); // John talks with the pianist
//
- void animation_2_2(); // John enters the chapel via the window
+ void animation_2_2(); // John enters the chapel via the window
void animation_4_2(); // John talks with the blind man (closeup)
void animation_5_2(); // John breaks the chapel window with the pike
void animation_6_2(); // The blind man (closeup) thanks John for giving him money and hands him the sickle
diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp
index c3ede46df2..08838a784a 100644
--- a/engines/dreamweb/dreamweb.cpp
+++ b/engines/dreamweb/dreamweb.cpp
@@ -23,7 +23,6 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/events.h"
-#include "common/EventRecorder.h"
#include "common/file.h"
#include "common/func.h"
#include "common/system.h"
diff --git a/engines/dreamweb/monitor.cpp b/engines/dreamweb/monitor.cpp
index 1f9fa8d24f..108f9d2b60 100644
--- a/engines/dreamweb/monitor.cpp
+++ b/engines/dreamweb/monitor.cpp
@@ -104,7 +104,7 @@ void DreamWebEngine::useMon() {
redrawMainScrn();
workToScreenM();
}
-
+
int DreamWebEngine::findCommand(const char *const cmdList[]) {
// Loop over all commands in the list and see if we get a match
int cmd = 0;
@@ -135,7 +135,7 @@ bool DreamWebEngine::execCommand() {
"KEYS",
NULL
};
-
+
static const char *const comlistFR[] = {
"SORTIR",
"AIDE",
@@ -145,7 +145,7 @@ bool DreamWebEngine::execCommand() {
"TOUCHES", // should be CLES but it is translated as TOUCHES in the game...
NULL
};
-
+
static const char *const comlistDE[] = {
"ENDE",
"HILF",
@@ -155,7 +155,7 @@ bool DreamWebEngine::execCommand() {
"DATEN",
NULL
};
-
+
static const char *const comlistIT[] = {
"ESCI",
"AIUTO",
@@ -165,7 +165,7 @@ bool DreamWebEngine::execCommand() {
"CHIAVI",
NULL
};
-
+
static const char *const comlistES[] = {
"SALIR",
"AYUDA",
diff --git a/engines/dreamweb/print.cpp b/engines/dreamweb/print.cpp
index bc75b97e71..bec58322d5 100644
--- a/engines/dreamweb/print.cpp
+++ b/engines/dreamweb/print.cpp
@@ -67,7 +67,7 @@ void DreamWebEngine::printChar(const GraphicsFile &charSet, uint16* x, uint16 y,
// characters (0 - 31).
if (c < 32 || c == 255)
return;
-
+
uint8 dummyWidth, dummyHeight;
if (width == NULL)
width = &dummyWidth;
diff --git a/engines/engines.mk b/engines/engines.mk
index b905a288c9..f58dba0d6d 100644
--- a/engines/engines.mk
+++ b/engines/engines.mk
@@ -135,6 +135,11 @@ DEFINES += -DENABLE_NEVERHOOD=$(ENABLE_NEVERHOOD)
MODULES += engines/neverhood
endif
+ifdef ENABLE_MORTEVIELLE
+DEFINES += -DENABLE_MORTEVIELLE=$(ENABLE_MORTEVIELLE)
+MODULES += engines/mortevielle
+endif
+
ifdef ENABLE_PARALLACTION
DEFINES += -DENABLE_PARALLACTION=$(ENABLE_PARALLACTION)
MODULES += engines/parallaction
diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp
index 6b65eb6ab9..839378a412 100644
--- a/engines/gob/surface.cpp
+++ b/engines/gob/surface.cpp
@@ -45,7 +45,7 @@ static void plotPixel(int x, int y, int color, void *data) {
Pixel::Pixel(byte *vidMem, uint8 bpp, byte *min, byte *max) :
_vidMem(vidMem), _bpp(bpp), _min(min), _max(max) {
- assert((_bpp == 1) || (_bpp == 2));
+ assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4));
assert(_vidMem >= _min);
assert(_vidMem < _max);
}
@@ -91,6 +91,8 @@ uint32 Pixel::get() const {
return *((byte *) _vidMem);
if (_bpp == 2)
return *((uint16 *) _vidMem);
+ if (_bpp == 4)
+ return *((uint32 *) _vidMem);
return 0;
}
@@ -103,6 +105,8 @@ void Pixel::set(uint32 p) {
*((byte *) _vidMem) = (byte) p;
if (_bpp == 2)
*((uint16 *) _vidMem) = (uint16) p;
+ if (_bpp == 4)
+ *((uint32 *) _vidMem) = (uint32) p;
}
bool Pixel::isValid() const {
@@ -113,7 +117,7 @@ bool Pixel::isValid() const {
ConstPixel::ConstPixel(const byte *vidMem, uint8 bpp, const byte *min, const byte *max) :
_vidMem(vidMem), _bpp(bpp), _min(min), _max(max) {
- assert((_bpp == 1) || (_bpp == 2));
+ assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4));
assert(_vidMem >= _min);
assert(_vidMem < _max);
}
@@ -159,6 +163,8 @@ uint32 ConstPixel::get() const {
return *((const byte *) _vidMem);
if (_bpp == 2)
return *((const uint16 *) _vidMem);
+ if (_bpp == 4)
+ return *((const uint32 *) _vidMem);
return 0;
}
@@ -172,7 +178,7 @@ Surface::Surface(uint16 width, uint16 height, uint8 bpp, byte *vidMem) :
_width(width), _height(height), _bpp(bpp), _vidMem(vidMem) {
assert((_width > 0) && (_height > 0));
- assert((_bpp == 1) || (_bpp == 2));
+ assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4));
if (!_vidMem) {
_vidMem = new byte[_bpp * _width * _height];
@@ -187,7 +193,7 @@ Surface::Surface(uint16 width, uint16 height, uint8 bpp, const byte *vidMem) :
_width(width), _height(height), _bpp(bpp), _vidMem(0) {
assert((_width > 0) && (_height > 0));
- assert((_bpp == 1) || (_bpp == 2));
+ assert((_bpp == 1) || (_bpp == 2) || (_bpp == 4));
_vidMem = new byte[_bpp * _width * _height];
_ownVidMem = true;
@@ -504,7 +510,7 @@ void Surface::fillRect(uint16 left, uint16 top, uint16 right, uint16 bottom, uin
return;
}
- assert(_bpp == 2);
+ assert((_bpp == 2) || (_bpp == 4));
// Otherwise, we have to fill by pixel
diff --git a/engines/groovie/stuffit.cpp b/engines/groovie/stuffit.cpp
index 37f12585e7..60a57a0129 100644
--- a/engines/groovie/stuffit.cpp
+++ b/engines/groovie/stuffit.cpp
@@ -249,7 +249,7 @@ void StuffItArchive::update14(uint16 first, uint16 last, byte *code, uint16 *fre
do {
while (++i < last && code[first] > code[i])
;
-
+
while (--j > first && code[first] < code[j])
;
diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp
index f7b923badf..82e0dd0a06 100644
--- a/engines/hopkins/computer.cpp
+++ b/engines/hopkins/computer.cpp
@@ -58,7 +58,7 @@ ComputerManager::ComputerManager(HopkinsEngine *vm) {
_minBreakoutMoveSpeed = 0;
_maxBreakoutMoveSpeed = 0;
_lastBreakoutMoveSpeed = 0;
- _breakoutHiscore = 0;
+ _lowestHiScore = 0;
}
/**
@@ -578,27 +578,28 @@ void ComputerManager::displayGamesSubMenu() {
* Load Highscore from file
*/
void ComputerManager::loadHiscore() {
- byte *ptr = _vm->_globals->allocMemory(100);
- _vm->_saveLoad->load("HISCORE.DAT", ptr);
+ const byte *ptr = _vm->_globals->_highScoreData;
for (int scoreIndex = 0; scoreIndex < 6; ++scoreIndex) {
- for (int i = 0; i < 5; ++i) {
+ _score[scoreIndex]._name = " ";
+ _score[scoreIndex]._score = " ";
+
+ for (int i = 0; i < 6; ++i) {
char nextChar = ptr[(16 * scoreIndex) + i];
if (!nextChar)
nextChar = ' ';
- _score[scoreIndex]._name += nextChar;
+ _score[scoreIndex]._name.setChar(nextChar, i);
}
for (int i = 0; i < 9; ++i) {
char nextChar = ptr[(scoreIndex * 16) + 6 + i];
if (!nextChar)
nextChar = '0';
- _score[scoreIndex]._score += nextChar;
+ _score[scoreIndex]._score.setChar(nextChar, i);
}
}
- _vm->_globals->freeMemory(ptr);
- _breakoutHiscore = atol(_score[5]._score.c_str());
+ _lowestHiScore = atol(_score[5]._score.c_str());
}
/**
@@ -779,7 +780,7 @@ void ComputerManager::playBreakout() {
_vm->_events->mouseOn();
_vm->_objectsMan->removeSprite(0);
_vm->_objectsMan->removeSprite(1);
- if (_breakoutScore > _breakoutHiscore)
+ if (_breakoutScore > _lowestHiScore)
getScoreName();
if (displayHiscores() != 1)
break;
@@ -823,11 +824,11 @@ int ComputerManager::displayHiscores() {
yp += 46;
// Display the characters of the name
- for (int i = 0; i <= 5; i++)
+ for (int i = 0; i < 6; i++)
displayHiscoreLine(ptr, 9 * i + 69, yp, _score[scoreIndex]._name[i]);
// Display the digits of the score
- for (int i = 0; i <= 8; i++)
+ for (int i = 0; i < 9; i++)
displayHiscoreLine(ptr, 9 * i + 199, yp, _score[scoreIndex]._score[i]);
}
@@ -864,6 +865,19 @@ void ComputerManager::getScoreName() {
_vm->_graphicsMan->setColorPercentage(254, 0, 0, 0);
byte *ptr = _vm->_fileIO->loadFile("ALPHA.SPR");
_vm->_graphicsMan->fadeInBreakout();
+
+ // Figure out the line to put the new high score on
+ int scoreLine = 0;
+ while (scoreLine < 5 && _breakoutScore < atol(_score[scoreLine]._score.c_str()))
+ ++scoreLine;
+
+ // If it's not the lasat line, move the lines down
+ for (int line = 5; line > scoreLine; --line) {
+ _score[line]._name = _score[line - 1]._name;
+ _score[line]._score = _score[line - 1]._score;
+ }
+
+ // Get the name for the new high score
for (int strPos = 0; strPos <= 4; strPos++) {
displayHiscoreLine(ptr, 9 * strPos + 140, 78, 1);
@@ -873,13 +887,15 @@ void ComputerManager::getScoreName() {
if ((curChar > '9') && (curChar < 'A'))
curChar = ' ';
- _score[5]._name.setChar(curChar, strPos);
+ _score[scoreLine]._name.setChar(curChar, strPos);
displayHiscoreLine(ptr, 9 * strPos + 140, 78, curChar);
for (int idx = 0; idx < 12; ++idx)
_vm->_events->refreshScreenAndEvents();
}
- _score[5]._score = " ";
+
+ // Set up the new score
+ _score[scoreLine]._score = " ";
char score[16];
sprintf(score, "%d", _breakoutScore);
@@ -888,8 +904,8 @@ void ComputerManager::getScoreName() {
++scoreLen;
while (score[scoreLen]);
- for (int i = scoreLen, scorePos = 8; i >= 0; i--) {
- _score[5]._score.setChar(score[i], scorePos--);
+ for (int i = scoreLen - 1, scorePos = 8; i >= 0; i--) {
+ _score[scoreLine]._score.setChar(score[i], scorePos--);
}
_vm->_graphicsMan->fadeOutBreakout();
_vm->_globals->freeMemory(ptr);
@@ -969,11 +985,11 @@ void ComputerManager::saveScore() {
}
}
- byte *ptr = _vm->_globals->allocMemory(100);
+ byte *ptr = _vm->_globals->_highScoreData;
memset(ptr, 0, 99);
for (int scorePlaceIdx = 0; scorePlaceIdx <= 5; scorePlaceIdx++) {
int curBufPtr = 16 * scorePlaceIdx;
- for (int namePos = 0; namePos <= 4; namePos++) {
+ for (int namePos = 0; namePos < 6; namePos++) {
char curChar = _score[scorePlace[scorePlaceIdx]]._name[namePos];
if (!curChar)
curChar = ' ';
@@ -990,9 +1006,6 @@ void ComputerManager::saveScore() {
};
ptr[curBufPtr + 15] = 0;
}
-
- _vm->_saveLoad->saveFile("HISCORE.DAT", ptr, 100);
- _vm->_globals->freeMemory(ptr);
}
/**
diff --git a/engines/hopkins/computer.h b/engines/hopkins/computer.h
index cdd653f793..1771bba7d6 100644
--- a/engines/hopkins/computer.h
+++ b/engines/hopkins/computer.h
@@ -63,7 +63,7 @@ private:
bool _ballUpFl;
int _breakoutLevelNbr;
int _padPositionX;
- int _breakoutHiscore;
+ int _lowestHiScore;
int _minBreakoutMoveSpeed;
int _maxBreakoutMoveSpeed;
int _lastBreakoutMoveSpeed;
diff --git a/engines/hopkins/dialogs.cpp b/engines/hopkins/dialogs.cpp
index 6cdfbf47d1..ab672d4c48 100644
--- a/engines/hopkins/dialogs.cpp
+++ b/engines/hopkins/dialogs.cpp
@@ -505,7 +505,7 @@ void DialogsManager::inventAnim() {
return;
if (_vm->_objectsMan->_eraseVisibleCounter && !_vm->_objectsMan->_visibleFl) {
- _vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, _oldInventX, 27, 48, 38,
+ _vm->_graphicsMan->copySurface(_vm->_graphicsMan->_backBuffer, _oldInventX, 27, 48, 38,
_vm->_graphicsMan->_frontBuffer, _oldInventX, 27);
_vm->_graphicsMan->addDirtyRect(_oldInventX, 27, _oldInventX + 48, 65);
--_vm->_objectsMan->_eraseVisibleCounter;
diff --git a/engines/hopkins/globals.cpp b/engines/hopkins/globals.cpp
index 28f22ed99e..97d6c4046c 100644
--- a/engines/hopkins/globals.cpp
+++ b/engines/hopkins/globals.cpp
@@ -70,6 +70,8 @@ Globals::Globals(HopkinsEngine *vm) {
for (int i = 0; i < 36; ++i)
_inventory[i] = 0;
+ Common::fill(&_highScoreData[0], &_highScoreData[100], 0);
+
// Initialize fields
_language = LANG_EN;
@@ -134,7 +136,7 @@ Globals::~Globals() {
void Globals::setConfig() {
// CHECKME: Should be in Globals() but it doesn't work
// The Polish version is a translation of the English version. The filenames are the same.
- // The Russian version looks like a translation of the English version, based on the filenames.
+ // The Russian version looks like a translation of the English version, based on the filenames.
switch (_vm->getLanguage()) {
case Common::EN_ANY:
case Common::PL_POL:
diff --git a/engines/hopkins/globals.h b/engines/hopkins/globals.h
index 94512c3d26..a76323bb50 100644
--- a/engines/hopkins/globals.h
+++ b/engines/hopkins/globals.h
@@ -206,6 +206,7 @@ public:
Common::String _zoneFilename;
Common::String _textFilename;
byte *_levelSpriteBuf;
+ byte _highScoreData[100];
EventMode _eventMode;
diff --git a/engines/hopkins/graphics.cpp b/engines/hopkins/graphics.cpp
index ebc5cfa8da..b83371d65f 100644
--- a/engines/hopkins/graphics.cpp
+++ b/engines/hopkins/graphics.cpp
@@ -1179,7 +1179,7 @@ void GraphicsManager::displayZones() {
Common::Rect r(_vm->_objectsMan->_bob[bobId]._oldX, _vm->_objectsMan->_bob[bobId]._oldY,
_vm->_objectsMan->_bob[bobId]._oldX + _vm->_objectsMan->_bob[bobId]._oldWidth,
_vm->_objectsMan->_bob[bobId]._oldY + _vm->_objectsMan->_bob[bobId]._oldHeight);
-
+
displayDebugRect(screenSurface, r, 0xff0000);
}
}
@@ -1204,7 +1204,7 @@ void GraphicsManager::displayLines() {
uint16* pixels = (uint16*)screenSurface->pixels;
- for (int lineIndex = 0; lineIndex < _vm->_linesMan->_linesNumb; lineIndex++) {
+ for (int lineIndex = 0; lineIndex < _vm->_linesMan->_linesNumb; lineIndex++) {
int i = 0;
do {
int x = _vm->_linesMan->_lineItem[lineIndex]._lineData[i] - _scrollPosX;
@@ -1230,7 +1230,7 @@ void GraphicsManager::displayDebugRect(Graphics::Surface *surface, const Common:
r.top = MAX(r.top, (int16)0);
r.right = MIN(r.right, (int16)SCREEN_WIDTH);
r.bottom = MIN(r.bottom, (int16)SCREEN_HEIGHT);
-
+
// If there's an on-screen portion, display it
if (r.isValidRect())
surface->frameRect(r, color);
diff --git a/engines/hopkins/graphics.h b/engines/hopkins/graphics.h
index 268db7fc2b..8767f5ec4d 100644
--- a/engines/hopkins/graphics.h
+++ b/engines/hopkins/graphics.h
@@ -125,7 +125,7 @@ public:
public:
GraphicsManager(HopkinsEngine *vm);
~GraphicsManager();
-
+
void clearPalette();
void clearScreen();
void clearVesaScreen();
diff --git a/engines/hopkins/hopkins.cpp b/engines/hopkins/hopkins.cpp
index b773808c50..96131f2968 100644
--- a/engines/hopkins/hopkins.cpp
+++ b/engines/hopkins/hopkins.cpp
@@ -92,7 +92,7 @@ bool HopkinsEngine::canLoadGameStateCurrently() {
* Returns true if it is currently okay to save the game
*/
bool HopkinsEngine::canSaveGameStateCurrently() {
- return !_globals->_exitId && !_globals->_cityMapEnabledFl && _events->_mouseFl
+ return !_globals->_exitId && !_globals->_cityMapEnabledFl && _events->_mouseFl
&& _globals->_curRoomNum != 0 && !isUnderwaterSubScene();
}
@@ -111,8 +111,6 @@ Common::Error HopkinsEngine::saveGameState(int slot, const Common::String &desc)
}
Common::Error HopkinsEngine::run() {
- _saveLoad->initSaves();
-
_globals->setConfig();
_fileIO->initCensorship();
initializeSystem();
diff --git a/engines/hopkins/saveload.cpp b/engines/hopkins/saveload.cpp
index 98fb15046e..14b166294d 100644
--- a/engines/hopkins/saveload.cpp
+++ b/engines/hopkins/saveload.cpp
@@ -60,14 +60,6 @@ bool SaveLoadManager::saveFile(const Common::String &file, const void *buf, size
return save(file, buf, n);
}
-void SaveLoadManager::initSaves() {
- Common::String dataFilename = "HISCORE.DAT";
- byte data[100];
- Common::fill(&data[0], &data[100], 0);
-
- saveFile(dataFilename, data, 100);
-}
-
void SaveLoadManager::load(const Common::String &file, byte *buf) {
Common::InSaveFile *savefile = g_system->getSavefileManager()->openForLoading(file);
if (savefile == NULL)
@@ -259,6 +251,10 @@ void SaveLoadManager::createThumbnail(Graphics::Surface *s) {
}
void SaveLoadManager::syncSavegameData(Common::Serializer &s, int version) {
+ if (version >= 3)
+ // Sync embedded Breakout game high score data
+ s.syncBytes(&_vm->_globals->_highScoreData[0], 100);
+
s.syncBytes(&_vm->_globals->_saveData->_data[0], 2050);
syncCharacterLocation(s, _vm->_globals->_saveData->_cloneHopkins);
syncCharacterLocation(s, _vm->_globals->_saveData->_realHopkins);
diff --git a/engines/hopkins/saveload.h b/engines/hopkins/saveload.h
index 6fee814180..e4ee3aaeda 100644
--- a/engines/hopkins/saveload.h
+++ b/engines/hopkins/saveload.h
@@ -35,7 +35,7 @@ namespace Hopkins {
class HopkinsEngine;
-#define HOPKINS_SAVEGAME_VERSION 2
+#define HOPKINS_SAVEGAME_VERSION 3
struct hopkinsSavegameHeader {
uint8 _version;
@@ -56,7 +56,6 @@ private:
public:
SaveLoadManager(HopkinsEngine *vm);
- void initSaves();
bool save(const Common::String &file, const void *buf, size_t n);
bool saveFile(const Common::String &file, const void *buf, size_t n);
void load(const Common::String &file, byte *buf);
diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp
index bcf06055f8..b140cfdba2 100644
--- a/engines/hugo/hugo.cpp
+++ b/engines/hugo/hugo.cpp
@@ -66,7 +66,7 @@ HugoEngine::HugoEngine(OSystem *syst, const HugoGameDescription *gd) : Engine(sy
_console = new HugoConsole(this);
_rnd = 0;
-
+
_screen = NULL;
_mouse = NULL;
_inventory = NULL;
diff --git a/engines/kyra/kyra_rpg.cpp b/engines/kyra/kyra_rpg.cpp
index f8eb7d00cd..4f7adcc6e5 100644
--- a/engines/kyra/kyra_rpg.cpp
+++ b/engines/kyra/kyra_rpg.cpp
@@ -213,7 +213,7 @@ void KyraRpgEngine::drawDialogueButtons() {
screen()->printText(_dialogueButtonString[i], (x + 37 - (screen()->getTextWidth(_dialogueButtonString[i])) / 2) & ~3,
((_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2) & ~7, _dialogueHighlightedButton == i ? 0xC1 : 0xE1, 0);
} else {
- int sjisYOffset = (_flags.lang == Common::JA_JPN && _dialogueButtonString[i][0] < 0) ? 2 : 0;
+ int sjisYOffset = (_flags.lang == Common::JA_JPN && (_dialogueButtonString[i][0] & 0x80)) ? 2 : 0;
gui_drawBox(x, (_dialogueButtonYoffs + _dialogueButtonPosY[i]), _dialogueButtonWidth, guiSettings()->buttons.height, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
screen()->printText(_dialogueButtonString[i], x + (_dialogueButtonWidth >> 1) - (screen()->getTextWidth(_dialogueButtonString[i])) / 2,
(_dialogueButtonYoffs + _dialogueButtonPosY[i]) + 2 - sjisYOffset, _dialogueHighlightedButton == i ? _dialogueButtonLabelColor1 : _dialogueButtonLabelColor2, 0);
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 419b630714..054397a34a 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -1256,7 +1256,7 @@ int Screen::getTextWidth(const char *str) {
while (1) {
if (_sjisMixedFontMode)
- setFont(*str < 0 ? FID_SJIS_FNT : curFont);
+ setFont((*str & 0x80) ? FID_SJIS_FNT : curFont);
uint c = fetchChar(str);
@@ -1296,7 +1296,7 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2
while (1) {
if (_sjisMixedFontMode)
- setFont(*str < 0 ? FID_SJIS_FNT : curFont);
+ setFont((*str & 0x80) ? FID_SJIS_FNT : curFont);
uint8 charHeightFnt = getFontHeight();
diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp
index 7fab4521f7..efd4051eba 100644
--- a/engines/lure/hotspots.cpp
+++ b/engines/lure/hotspots.cpp
@@ -4006,6 +4006,7 @@ void HotspotTickHandlers::rackSerfAnimHandler(Hotspot &h) {
h.setActionCtr(4);
h.setLayer(2);
+ // Deliberate fall-through
case 4:
if (HotspotScript::execute(&h)) {
h.setLayer(255);
diff --git a/engines/mortevielle/actions.cpp b/engines/mortevielle/actions.cpp
new file mode 100644
index 0000000000..5738a8fd3a
--- /dev/null
+++ b/engines/mortevielle/actions.cpp
@@ -0,0 +1,1640 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+#include "mortevielle/dialogs.h"
+#include "mortevielle/menu.h"
+#include "mortevielle/mouse.h"
+#include "mortevielle/outtext.h"
+#include "mortevielle/speech.h"
+
+#include "common/scummsys.h"
+
+namespace Mortevielle {
+
+/**
+ * Engine function - Move
+ * @remarks Originally called 'taller'
+ */
+void MortevielleEngine::fctMove() {
+ int oldMenu = (_menu._moveMenu[6]._menuId << 8) | _menu._moveMenu[6]._actionId;
+ if ((_coreVar._currPlace == ROOM26) && (_currAction == oldMenu)) {
+ _coreVar._currPlace = LANDING;
+ _caff = _coreVar._currPlace;
+ drawPictureWithText();
+ handleDescriptionText(2, _coreVar._currPlace);
+ }
+ if ((_coreVar._currPlace == LANDING) && (_currAction == oldMenu)) {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_GO_TO));
+ displayStatusArrow();
+
+ if (_keyPressedEsc)
+ _destinationOk = false;
+
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+
+ setCoordinates(1);
+
+ if (_num == 0)
+ return;
+
+ if (_num == 1) {
+ _coreVar._currPlace = OWN_ROOM;
+ _menu.setDestinationText(OWN_ROOM);
+ } else if (_num == 7) {
+ _coreVar._currPlace = ATTIC;
+ _menu.setDestinationText(ATTIC);
+ } else if (_num != 6)
+ _coreVar._currPlace = ROOM26;
+
+ if ((_num > 1) && (_num < 6))
+ _roomDoorId = _num - 1;
+ else if (_num > 7)
+ _roomDoorId = _num - 3;
+
+ if (_num != 6)
+ prepareDisplayText();
+ else
+ showMoveMenuAlert();
+ return;
+ }
+ exitRoom();
+ int menuChoice = 1;
+ oldMenu = (_menu._moveMenu[menuChoice]._menuId << 8) | _menu._moveMenu[menuChoice]._actionId;
+ while (oldMenu != _currAction) {
+ ++menuChoice;
+ oldMenu = (_menu._moveMenu[menuChoice]._menuId << 8) | _menu._moveMenu[menuChoice]._actionId;
+ }
+
+ if (_coreVar._currPlace == MOUNTAIN) {
+ if (menuChoice == 1)
+ gotoManorFront();
+ else if (menuChoice == 2)
+ checkManorDistance();
+ _menu.setDestinationText(_coreVar._currPlace);
+ return;
+ } else if (_coreVar._currPlace == INSIDE_WELL) {
+ if (menuChoice == 1)
+ floodedInWell();
+ else if (menuChoice == 2)
+ gotoManorBack();
+ _menu.setDestinationText(_coreVar._currPlace);
+ return;
+ } else if ((_coreVar._currPlace == BUREAU) && (menuChoice == 1))
+ menuChoice = 6;
+ else if (_coreVar._currPlace == KITCHEN) {
+ if (menuChoice == 2)
+ menuChoice = 6;
+ else if (menuChoice == 5)
+ menuChoice = 16;
+ } else if ((_coreVar._currPlace == CELLAR) && (menuChoice == 3))
+ menuChoice = 6;
+ else if (((_coreVar._currPlace == LANDING) || (_coreVar._currPlace == ROOM26)) && (menuChoice == 4))
+ menuChoice = 6;
+
+ if ((_coreVar._currPlace > MOUNTAIN) && (_coreVar._currPlace != ROOM26))
+ menuChoice += 10;
+
+ if ((_coreVar._currPlace == CHAPEL) && (menuChoice == 13))
+ menuChoice = 16;
+ else if (_coreVar._currPlace == MANOR_FRONT) {
+ if (menuChoice == 12)
+ menuChoice = 16;
+ else if (menuChoice > 13)
+ menuChoice = 15;
+ } else if ((_coreVar._currPlace == MANOR_BACK) && (menuChoice > 14))
+ menuChoice = 15;
+ else if ((_coreVar._currPlace == WELL) && (menuChoice > 13) && (menuChoice != 17))
+ menuChoice = 15;
+
+ if (menuChoice == 1)
+ _coreVar._currPlace = BUREAU;
+ else if (menuChoice == 2)
+ _coreVar._currPlace = KITCHEN;
+ else if (menuChoice == 3)
+ _coreVar._currPlace = CELLAR;
+ else if (menuChoice == 4)
+ _coreVar._currPlace = LANDING;
+ else if (menuChoice == 5)
+ menuChoice = 12;
+ else if (menuChoice == 6)
+ menuChoice = 11;
+
+ if (menuChoice == 11)
+ gotoDiningRoom();
+ else if (menuChoice == 12)
+ gotoManorFront();
+ else if (menuChoice == 13)
+ _coreVar._currPlace = CHAPEL;
+ else if (menuChoice == 14)
+ _coreVar._currPlace = WELL;
+ else if (menuChoice == 15)
+ checkManorDistance();
+ else if (menuChoice == 16)
+ gotoManorBack();
+ else if (menuChoice == 17) {
+ if ((_coreVar._wellObjectId != 120) && (_coreVar._wellObjectId != 140))
+ _crep = 997;
+ else if (_coreVar._wellObjectId == 120)
+ _crep = 181;
+ else if (_coreVar._faithScore > 80) {
+ _crep = 1505;
+ loseGame();
+ } else {
+ _coreVar._currPlace = INSIDE_WELL;
+ prepareDisplayText();
+ }
+ }
+ if ((menuChoice < 5) || (menuChoice == 13) || (menuChoice == 14))
+ prepareDisplayText();
+ resetRoomVariables(_coreVar._currPlace);
+ _menu.setDestinationText(_coreVar._currPlace);
+}
+
+/**
+ * Engine function - Take
+ * @remarks Originally called 'tprendre'
+ */
+void MortevielleEngine::fctTake() {
+ if (_caff > 99) {
+ int cx = _caff;
+ putInHand(cx);
+ if (_crep != 139) {
+ if (_currBitIndex > 0)
+ _coreVar._faithScore += 3;
+ if (_obpart) {
+ if (_coreVar._currPlace == PURPLE_ROOM)
+ _coreVar._purpleRoomObjectId = 0;
+ if (_coreVar._currPlace == ATTIC) {
+ if (_coreVar._atticBallHoleObjectId == _caff)
+ _coreVar._atticBallHoleObjectId = 0;
+ if (_coreVar._atticRodHoleObjectId == _caff)
+ _coreVar._atticRodHoleObjectId = 0;
+ }
+ if (_coreVar._currPlace == CELLAR)
+ _coreVar._cellarObjectId = 0;
+ if (_coreVar._currPlace == CRYPT)
+ _coreVar._cryptObjectId = 0;
+ if (_coreVar._currPlace == SECRET_PASSAGE)
+ _coreVar._secretPassageObjectId = 0;
+ if (_coreVar._currPlace == WELL)
+ _coreVar._wellObjectId = 0;
+ _menu.unsetSearchMenu();
+ _obpart = false;
+ prepareDisplayText();
+ } else {
+ _tabdon[kAcha + ((_mchai - 1) * 10) + _searchCount - 1] = 0;
+ tsuiv();
+ ++_takeObjCount;
+ if (_takeObjCount > 6) {
+ _coreVar._faithScore += 2;
+ _takeObjCount = 0;
+ }
+ }
+ }
+ return;
+ }
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_TAKE));
+ displayStatusArrow();
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+ if (_caff == 3) {
+ setCoordinates(2);
+ if (_num == 1) {
+ _crep = 152;
+ return;
+ }
+ }
+ setCoordinates(5);
+ if ((_num == 0) || ((_num == 1) && (_coreVar._currPlace == CRYPT))) {
+ setCoordinates(8);
+ if (_num != 0) {
+ if (_currBitIndex > 0)
+ _coreVar._faithScore += 3;
+ _crep = 997;
+ if ((_coreVar._currPlace == PURPLE_ROOM) && (_coreVar._purpleRoomObjectId != 0))
+ putInHand(_coreVar._purpleRoomObjectId);
+ if ((_coreVar._currPlace == ATTIC) && (_num == 1) && (_coreVar._atticBallHoleObjectId != 0)) {
+ putInHand(_coreVar._atticBallHoleObjectId);
+ if ((_crep != 997) && (_crep != 139))
+ displayAnimFrame(2, 7);
+ }
+ if ((_coreVar._currPlace == ATTIC) && (_num == 2) && (_coreVar._atticRodHoleObjectId != 0)) {
+ putInHand(_coreVar._atticRodHoleObjectId);
+ if ((_crep != 997) && (_crep != 139))
+ displayAnimFrame(2, 6);
+ }
+ if ((_coreVar._currPlace == CELLAR) && (_coreVar._cellarObjectId != 0)) {
+ putInHand(_coreVar._cellarObjectId);
+ if ((_crep != 997) && (_crep != 139))
+ displayAnimFrame(2, 2);
+ }
+ if ((_coreVar._currPlace == CRYPT) && (_coreVar._cryptObjectId != 0))
+ putInHand(_coreVar._cryptObjectId);
+
+ if ((_coreVar._currPlace == SECRET_PASSAGE) && (_coreVar._secretPassageObjectId != 0)) {
+ putInHand(_coreVar._secretPassageObjectId);
+ if ((_crep != 997) && (_crep != 139)) {
+ _crep = 182;
+ displayAnimFrame(2, 1);
+ }
+ }
+ if ((_coreVar._currPlace == WELL) && (_coreVar._wellObjectId != 0)) {
+ putInHand(_coreVar._wellObjectId);
+ if ((_crep != 997) && (_crep != 139))
+ displayAnimFrame(2, 1);
+ }
+ if ((_crep != 997) && (_crep != 182) && (_crep != 139))
+ _crep = 999;
+ }
+ } else {
+ if ( ((_coreVar._currPlace == OWN_ROOM) && (_num == 3))
+ || ((_coreVar._currPlace == GREEN_ROOM) && (_num == 4))
+ || ((_coreVar._currPlace == PURPLE_ROOM) && (_num == 1))
+ || ((_coreVar._currPlace == DARKBLUE_ROOM) && (_num == 3))
+ || ((_coreVar._currPlace == BLUE_ROOM) && (_num == 6))
+ || ((_coreVar._currPlace == RED_ROOM) && (_num == 2))
+ || ((_coreVar._currPlace == BATHROOM) && (_num == 6))
+ || ((_coreVar._currPlace == GREEN_ROOM2) && (_num == 4))
+ || ((_coreVar._currPlace == ROOM9) && (_num == 4))
+ || ((_coreVar._currPlace == DINING_ROOM) && (_num > 2))
+ || ((_coreVar._currPlace == BUREAU) && (_num == 7))
+ || ((_coreVar._currPlace == KITCHEN) && (_num == 6))
+ || ((_coreVar._currPlace == ATTIC) && (_num > 4))
+ || ((_coreVar._currPlace > ATTIC) && (_coreVar._currPlace != INSIDE_WELL)) )
+ _crep = 997;
+ else if (_coreVar._currPlace == INSIDE_WELL) {
+ _crep = 1504;
+ loseGame();
+ } else
+ _crep = 120;
+ }
+}
+/**
+ * Engine function - Inventory / Take
+ * @remarks Originally called 'tsprendre'
+ */
+void MortevielleEngine::fctInventoryTake() {
+ int inventIndex = 0;
+ int oldMenu = 0;
+ do {
+ ++inventIndex;
+ oldMenu = (_menu._inventoryMenu[inventIndex]._menuId << 8) | _menu._inventoryMenu[inventIndex]._actionId;
+ } while (oldMenu != _currAction);
+ int cz = 0;
+ int cy = 0;
+ do {
+ ++cy;
+ if (_coreVar._inventory[cy] != 0)
+ ++cz;
+ } while (cz != inventIndex);
+ cz = _coreVar._inventory[cy];
+ _coreVar._inventory[cy] = 0;
+ _menu.setInventoryText();
+ putInHand(cz);
+ _crep = 998;
+ clearDescriptionBar();
+}
+
+/**
+ * Engine function - Lift
+ * @remarks Originally called 'tsoulever'
+ */
+void MortevielleEngine::fctLift() {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_LIFT));
+ displayStatusArrow();
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+ setCoordinates(3);
+ if (_num == 0) {
+ setCoordinates(8);
+ if (_num != 0) {
+ if (_currBitIndex > 0)
+ ++_coreVar._faithScore;
+ _crep = 997;
+ if ((_coreVar._currPlace == PURPLE_ROOM) && (_coreVar._purpleRoomObjectId != 0))
+ treg(_coreVar._purpleRoomObjectId);
+ }
+ return;
+ }
+ if (_currBitIndex > 0)
+ ++_coreVar._faithScore;
+ int tmpPlace = _coreVar._currPlace;
+ if (_coreVar._currPlace == CRYPT)
+ tmpPlace = 14;
+ else if (_coreVar._currPlace == MOUNTAIN)
+ tmpPlace = 15;
+ _crep = _tabdon[kAsoul + (tmpPlace << 3) + (_num - 1)];
+ if (_crep == 255)
+ _crep = 997;
+}
+
+/**
+ * Engine function - Read
+ * @remarks Originally called 'tlire'
+ */
+void MortevielleEngine::fctRead() {
+ if (_caff > 99)
+ getReadDescription(_caff);
+ else {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_READ));
+ displayStatusArrow();
+ if (!(_anyone) && !(_keyPressedEsc)) {
+ setCoordinates(4);
+ if (_num != 0)
+ _crep = 107;
+ }
+ }
+}
+
+/**
+ * Engine function - Self / Read
+ * @remarks Originally called 'tslire'
+ */
+void MortevielleEngine::fctSelfRead() {
+ if (_coreVar._selectedObjectId == 0)
+ _crep = 186;
+ else
+ getReadDescription(_coreVar._selectedObjectId);
+}
+
+/**
+ * Engine function - Look
+ * @remarks Originally called 'tregarder'
+ */
+void MortevielleEngine::fctLook() {
+ if (_caff > 99) {
+ _crep = 103;
+ return;
+ }
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_LOOK));
+ displayStatusArrow();
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+ setCoordinates(5);
+ if (_num == 0) {
+ setCoordinates(8);
+ _crep = 131;
+ if (_num != 0) {
+ if (_coreVar._currPlace == ATTIC) {
+ if (_num == 1) {
+ _crep = 164;
+ if (_coreVar._atticRodHoleObjectId != 0)
+ treg(_coreVar._atticRodHoleObjectId);
+ else if (_coreVar._atticBallHoleObjectId != 0)
+ treg(_coreVar._atticBallHoleObjectId);
+ } else {
+ _crep = 193;
+ if (_coreVar._atticRodHoleObjectId != 0)
+ treg(_coreVar._atticRodHoleObjectId);
+ }
+ }
+ if (_coreVar._currPlace == CELLAR) {
+ _crep = 164;
+ if (_coreVar._cellarObjectId != 0)
+ treg(_coreVar._cellarObjectId);
+ }
+ if (_coreVar._currPlace == SECRET_PASSAGE) {
+ _crep = 174;
+ if (_coreVar._secretPassageObjectId != 0)
+ treg(_coreVar._secretPassageObjectId);
+ }
+ if (_coreVar._currPlace == WELL) {
+ _crep = 131;
+ if (_coreVar._wellObjectId != 0)
+ treg(_coreVar._wellObjectId);
+ }
+ }
+ return;
+ }
+ int cx = _coreVar._currPlace;
+ if (_coreVar._currPlace == CHAPEL)
+ cx = 17;
+ if ((_coreVar._currPlace > MANOR_FRONT) && (_coreVar._currPlace < DOOR))
+ cx -= 4;
+ if (_coreVar._currPlace == ROOM26)
+ cx = 21;
+ _crep = _tabdon[kArega + (cx * 7) + _num - 1];
+ if ((_coreVar._currPlace == ATTIC) && (_num == 8))
+ _crep = 126;
+ if (_coreVar._currPlace == MOUNTAIN)
+ _crep = 103;
+ if (_crep == 255)
+ _crep = 131;
+ if ((_coreVar._currPlace == GREEN_ROOM) && (_num == 1))
+ treg(144);
+ if ((_coreVar._currPlace == BLUE_ROOM) && (_num == 3))
+ treg(147);
+ if ((_coreVar._currPlace == GREEN_ROOM2) && (_num == 3))
+ treg(149);
+ if ((_coreVar._currPlace == ROOM9) && (_num == 2))
+ treg(30);
+ if ((_coreVar._currPlace == DINING_ROOM) && (_num == 3))
+ treg(31);
+}
+
+/**
+ * Engine function - Self / Look
+ * @remarks Originally called 'tsregarder'
+ */
+void MortevielleEngine::fctSelftLook() {
+ if (_coreVar._selectedObjectId != 0)
+ treg(_coreVar._selectedObjectId);
+ else
+ _crep = 186;
+}
+
+/**
+ * Engine function - Search
+ * @remarks Originally called 'tfouiller'
+ */
+void MortevielleEngine::fctSearch() {
+ static const byte answerArr[14] = {123, 104, 123, 131, 131, 123, 104, 131, 123, 123, 106, 123, 123, 107};
+
+ if (_caff > 99) {
+ getSearchDescription(_caff);
+ return;
+ }
+
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_SEARCH));
+
+ displayStatusArrow();
+ if (_anyone || _keyPressedEsc)
+ return;
+
+ if (_coreVar._currPlace == INSIDE_WELL) {
+ _crep = 1504;
+ loseGame();
+ return;
+ }
+
+ setCoordinates(6);
+ if (_num == 0) {
+ setCoordinates(7);
+ if (_num != 0) {
+ int cx = 0;
+ do {
+ ++cx;
+ } while ((cx <= 6) && (_num != _openObjects[cx]));
+ if (_num != _openObjects[cx])
+ _crep = 187;
+ else {
+ if (_currBitIndex > 0)
+ _coreVar._faithScore += 3;
+
+ _mchai = rechai();
+ if (_mchai != 0) {
+ _searchCount = 0;
+ _heroSearching = true;
+ _menu.setSearchMenu();
+ tsuiv();
+ } else
+ _crep = 997;
+ }
+ } else {
+ setCoordinates(8);
+ _crep = 997;
+ if (_num != 0) {
+ if (_currBitIndex > 0)
+ _coreVar._faithScore += 3;
+ if ((_coreVar._currPlace != WELL) && (_coreVar._currPlace != SECRET_PASSAGE) && (_coreVar._currPlace != ATTIC)) {
+ if (_coreVar._currPlace == PURPLE_ROOM) {
+ _crep = 123;
+ if (_coreVar._purpleRoomObjectId != 0)
+ treg(_coreVar._purpleRoomObjectId);
+ }
+ if (_coreVar._currPlace == CRYPT) {
+ _crep = 123;
+ if (_coreVar._cryptObjectId != 0)
+ treg(_coreVar._cryptObjectId);
+ }
+ }
+ }
+ }
+ } else {
+ if (_currBitIndex > 0)
+ _coreVar._faithScore += 3;
+ _crep = 997;
+ if (_coreVar._currPlace < CELLAR)
+ _crep = answerArr[_coreVar._currPlace];
+
+ if ((_coreVar._currPlace == TOILETS) && (_num == 2))
+ _crep = 162;
+
+ if (_coreVar._currPlace == KITCHEN) {
+ if ((_num == 3) || (_num == 4))
+ _crep = 162;
+ else if (_num == 5)
+ _crep = 159;
+ }
+
+ if (_coreVar._currPlace == MOUNTAIN)
+ _crep = 104;
+ else if (_coreVar._currPlace == CRYPT)
+ _crep = 155;
+ }
+}
+
+/**
+ * Engine function - Self / Search
+ * @remarks Originally called 'tsfouiller'
+ */
+void MortevielleEngine::fctSelfSearch() {
+ if (_coreVar._selectedObjectId != 0)
+ getSearchDescription(_coreVar._selectedObjectId);
+ else
+ _crep = 186;
+}
+
+/**
+ * Engine function - Open
+ * @remarks Originally called 'touvrir'
+ */
+void MortevielleEngine::fctOpen() {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_OPEN));
+
+ if (_caff == ROOM26) {
+ if (_roomDoorId != OWN_ROOM) {
+ _currAction = OPCODE_ENTER;
+ _syn = true;
+ } else
+ _crep = 997;
+ return;
+ }
+
+ if (_caff == LANDING) {
+ showMoveMenuAlert();
+ return;
+ }
+
+ displayStatusArrow();
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+
+ setCoordinates(7);
+ if (_num != 0) {
+ if (_currBitIndex > 0)
+ _coreVar._faithScore += 2;
+ ++_openObjCount;
+ int tmpPlace = 0;
+ do {
+ ++tmpPlace;
+ } while (!((tmpPlace > 6) || (_openObjects[tmpPlace] == 0) || (_openObjects[tmpPlace] == _num)));
+ if (_openObjects[tmpPlace] != _num) {
+ if (!( ((_num == 3) && ((_coreVar._currPlace == OWN_ROOM)
+ || (_coreVar._currPlace == ROOM9)
+ || (_coreVar._currPlace == BLUE_ROOM)
+ || (_coreVar._currPlace == BATHROOM)))
+ || ((_num == 4) && ((_coreVar._currPlace == GREEN_ROOM)
+ || (_coreVar._currPlace == PURPLE_ROOM)
+ || (_coreVar._currPlace == RED_ROOM)))
+ || ((_coreVar._currPlace == DARKBLUE_ROOM) && (_num == 5))
+ || ((_num == 6) && ((_coreVar._currPlace == BATHROOM)
+ || (_coreVar._currPlace == DINING_ROOM)
+ || (_coreVar._currPlace == GREEN_ROOM2)
+ || (_coreVar._currPlace == ATTIC)))
+ || ((_coreVar._currPlace == GREEN_ROOM2) && (_num == 2))
+ || ((_coreVar._currPlace == KITCHEN) && (_num == 7))) ) {
+ if ( ((_coreVar._currPlace > DINING_ROOM) && (_coreVar._currPlace < CELLAR))
+ || ((_coreVar._currPlace > RED_ROOM) && (_coreVar._currPlace < DINING_ROOM))
+ || (_coreVar._currPlace == OWN_ROOM)
+ || (_coreVar._currPlace == PURPLE_ROOM)
+ || (_coreVar._currPlace == BLUE_ROOM)) {
+ if (getRandomNumber(1, 4) == 3)
+ _speechManager.startSpeech(7, 9, 1);
+ }
+ _openObjects[tmpPlace] = _num;
+ displayAnimFrame(1, _num);
+ }
+ tmpPlace = _coreVar._currPlace;
+ if (_coreVar._currPlace == CRYPT)
+ tmpPlace = CELLAR;
+ _crep = _tabdon[kAouvr + (tmpPlace * 7) + _num - 1];
+ if (_crep == 254)
+ _crep = 999;
+ } else
+ // display "Already Opened"
+ _crep = 18;
+ }
+}
+
+/**
+ * Engine function - Place
+ * @remarks Originally called 'tmettre'
+ */
+void MortevielleEngine::fctPlace() {
+ if (_coreVar._selectedObjectId == 0) {
+ _crep = 186;
+ return;
+ }
+
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_PUT));
+
+ displayStatusArrow();
+ if (_keyPressedEsc)
+ _crep = 998;
+
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+
+ setCoordinates(8);
+ if (_num != 0) {
+ _crep = 999;
+ if (_caff == ATTIC) {
+ if (_num == 1) {
+ if (_coreVar._atticBallHoleObjectId != 0) {
+ _crep = 188;
+ } else {
+ _coreVar._atticBallHoleObjectId = _coreVar._selectedObjectId;
+ if (_coreVar._selectedObjectId == 141)
+ displayAnimFrame(1, 7);
+ }
+ } else if (_coreVar._atticRodHoleObjectId != 0) {
+ _crep = 188;
+ } else {
+ _coreVar._atticRodHoleObjectId = _coreVar._selectedObjectId;
+ if (_coreVar._selectedObjectId == 159)
+ displayAnimFrame(1, 6);
+ }
+ }
+
+ if (_caff == CELLAR) {
+ if (_coreVar._cellarObjectId != 0) {
+ _crep = 188;
+ } else {
+ _coreVar._cellarObjectId = _coreVar._selectedObjectId;
+ if (_coreVar._selectedObjectId == 151) {
+ // Open hidden passage
+ displayAnimFrame(1, 2);
+ displayAnimFrame(1, 1);
+ handleDescriptionText(2, 165);
+ displayEmptyHand();
+ _speechManager.startSpeech(6, -9, 1);
+
+ // Do you want to enter the hidden passage?
+ int answer = _dialogManager.show(getEngineString(S_YES_NO), 1);
+ if (answer == 1) {
+ Common::String alertTxt = getString(582);
+ _dialogManager.show(alertTxt, 1);
+
+ bool enterPassageFl = _dialogManager.showKnowledgeCheck();
+ _mouse.hideMouse();
+ hirs();
+ drawRightFrame();
+ clearDescriptionBar();
+ clearVerbBar();
+ _mouse.showMouse();
+ prepareRoom();
+ drawClock();
+ if (_currBitIndex != 0)
+ showPeoplePresent(_currBitIndex);
+ else
+ displayAloneText();
+
+ _menu.displayMenu();
+ if (enterPassageFl) {
+ _coreVar._currPlace = SECRET_PASSAGE;
+ _menu.setDestinationText(SECRET_PASSAGE);
+ } else {
+ _menu.setDestinationText(_coreVar._currPlace);
+ setPal(14);
+ drawPicture();
+ displayAnimFrame(1, 2);
+ displayAnimFrame(1, 1);
+ alertTxt = getString(577);
+ _dialogManager.show(alertTxt, 1);
+ displayAnimFrame(2, 1);
+ _crep = 166;
+ }
+ prepareDisplayText();
+ } else {
+ displayAnimFrame(2, 1);
+ _crep = 166;
+ }
+ return;
+ }
+ }
+ }
+
+ if (_caff == CRYPT) {
+ if (_coreVar._cryptObjectId == 0)
+ _coreVar._cryptObjectId = _coreVar._selectedObjectId;
+ else
+ _crep = 188;
+ }
+
+ if (_caff == SECRET_PASSAGE) {
+ if (_coreVar._secretPassageObjectId != 0) {
+ _crep = 188;
+ } else if (_coreVar._selectedObjectId == 143) {
+ _coreVar._secretPassageObjectId = 143;
+ displayAnimFrame(1, 1);
+ } else {
+ _crep = 1512;
+ loseGame();
+ }
+ }
+
+ if (_caff == WELL) {
+ if (_coreVar._wellObjectId != 0) {
+ _crep = 188;
+ } else if ((_coreVar._selectedObjectId == 140) || (_coreVar._selectedObjectId == 120)) {
+ _coreVar._wellObjectId = _coreVar._selectedObjectId;
+ displayAnimFrame(1, 1);
+ } else {
+ _crep = 185;
+ }
+ }
+
+ if (_crep != 188)
+ displayEmptyHand();
+ }
+}
+
+/**
+ * Engine function - Turn
+ * @remarks Originally called 'ttourner'
+ */
+void MortevielleEngine::fctTurn() {
+ if (_caff > 99) {
+ _crep = 149;
+ return;
+ }
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_TURN));
+ displayStatusArrow();
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+ setCoordinates(9);
+ if (_num != 0) {
+ _crep = 997;
+ if ((_coreVar._currPlace == ATTIC) && (_coreVar._atticRodHoleObjectId == 159) && (_coreVar._atticBallHoleObjectId == 141)) {
+ handleDescriptionText(2, 167);
+ _speechManager.startSpeech(7, 9, 1);
+ int answer = _dialogManager.show(getEngineString(S_YES_NO), 1);
+ if (answer == 1)
+ _endGame = true;
+ else
+ _crep = 168;
+ }
+ if ((_coreVar._currPlace == SECRET_PASSAGE) && (_coreVar._secretPassageObjectId == 143)) {
+ handleDescriptionText(2, 175);
+ clearVerbBar();
+ _speechManager.startSpeech(6, -9, 1);
+ int answer = _dialogManager.show(getEngineString(S_YES_NO), 1);
+ if (answer == 1) {
+ _coreVar._currPlace = CRYPT;
+ prepareDisplayText();
+ } else
+ _crep = 176;
+ }
+ }
+}
+
+/**
+ * Engine function - Hide Self
+ * @remarks Originally called 'tcacher'
+ */
+void MortevielleEngine::fctSelfHide() {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_HIDE_SELF));
+ displayStatusArrow();
+ if (!(_anyone) && !(_keyPressedEsc)) {
+ setCoordinates(10);
+ if (_num == 0)
+ _hiddenHero = false;
+ else {
+ _hiddenHero = true;
+ _crep = 999;
+ }
+ }
+}
+
+/**
+ * Engine function - Attach
+ * @remarks Originally called 'tattacher'
+ */
+void MortevielleEngine::fctAttach() {
+ if (_coreVar._selectedObjectId == 0)
+ _crep = 186;
+ else {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_TIE));
+ displayStatusArrow();
+ if (!(_anyone) && !(_keyPressedEsc)) {
+ setCoordinates(8);
+ _crep = 997;
+ if ((_num != 0) && (_coreVar._currPlace == WELL)) {
+ _crep = 999;
+ if ((_coreVar._selectedObjectId == 120) || (_coreVar._selectedObjectId == 140)) {
+ _coreVar._wellObjectId = _coreVar._selectedObjectId;
+ displayAnimFrame(1, 1);
+ } else
+ _crep = 185;
+ displayEmptyHand();
+ }
+ }
+ }
+}
+
+/**
+ * Engine function - Close
+ * @remarks Originally called 'tfermer'
+ */
+void MortevielleEngine::fctClose() {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_CLOSE));
+
+ if (_caff < ROOM26) {
+ displayStatusArrow();
+ if (_keyPressedEsc)
+ _crep = 998;
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+ setCoordinates(7);
+ if (_num != 0) {
+ int cx = 0;
+ do {
+ ++cx;
+ } while ((cx <= 6) && (_num != _openObjects[cx]));
+ if (_num == _openObjects[cx]) {
+ displayAnimFrame(2, _num);
+ _crep = 998;
+ _openObjects[cx] = 0;
+ --_openObjCount;
+ if (_openObjCount < 0)
+ _openObjCount = 0;
+ int chai = rechai();
+ if (_mchai == chai)
+ _mchai = 0;
+ } else {
+ _crep = 187;
+ }
+ }
+ }
+ if (_caff == ROOM26)
+ _crep = 999;
+}
+
+/**
+ * Engine function - Knock
+ * @remarks Originally called 'tfrapper'
+ */
+void MortevielleEngine::fctKnock() {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_HIT));
+
+ if (_coreVar._currPlace == LANDING) {
+ _dialogManager.show(getEngineString(S_BEFORE_USE_DEP_MENU), 1);
+ return;
+ }
+
+ if (_coreVar._currPlace < DOOR) {
+ displayStatusArrow();
+ if (!(_anyone) && !(_keyPressedEsc)) {
+ if ((_coreVar._currPlace < MOUNTAIN) && (_coreVar._currPlace != LANDING))
+ _crep = 133;
+ else
+ _crep = 997;
+ }
+
+ return;
+ }
+
+ if (_coreVar._currPlace == ROOM26) {
+ int rand = (getRandomNumber(0, 8)) - 4;
+ _speechManager.startSpeech(11, rand, 1);
+ int p = getPresenceStats(rand, _coreVar._faithScore, _roomDoorId);
+ int l = _roomDoorId;
+ if (l != OWN_ROOM) {
+ if (p != -500) {
+ if (rand > p)
+ _crep = 190;
+ else {
+ setPresenceFlags(l);
+ getKnockAnswer();
+ }
+ } else
+ getKnockAnswer();
+ }
+
+ if (_roomDoorId == GREEN_ROOM2)
+ _crep = 190;
+ }
+}
+
+/**
+ * Engine function - Self / Put
+ * @remarks Originally called 'tposer'
+ */
+void MortevielleEngine::fctSelfPut() {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_POSE));
+ if (_coreVar._selectedObjectId == 0)
+ _crep = 186;
+ else {
+ if (_caff > 99) {
+ _crep = 999;
+ ajchai();
+ if (_crep != 192)
+ displayEmptyHand();
+ return;
+ }
+ displayStatusArrow();
+ if ((_anyone) || (_keyPressedEsc))
+ return;
+ setCoordinates(7);
+ _crep = 124;
+ if (_num != 0) {
+ int chai = rechai();
+ if (chai == 0)
+ _crep = 997;
+ else {
+ int cx = 0;
+ do {
+ ++cx;
+ } while ((cx <= 6) && (_num != _openObjects[cx]));
+ if (_num != _openObjects[cx])
+ _crep = 187;
+ else {
+ _mchai = chai;
+ _crep = 999;
+ }
+ }
+ } else {
+ setCoordinates(8);
+ if (_num != 0) {
+ _crep = 998;
+ if (_caff == PURPLE_ROOM) {
+ if (_coreVar._purpleRoomObjectId != 0)
+ _crep = 188;
+ else
+ _coreVar._purpleRoomObjectId = _coreVar._selectedObjectId;
+ }
+
+ if (_caff == ATTIC) {
+ if (_num == 1) {
+ if (_coreVar._atticBallHoleObjectId != 0)
+ _crep = 188;
+ else
+ _coreVar._atticBallHoleObjectId = _coreVar._selectedObjectId;
+ } else if (_coreVar._atticRodHoleObjectId != 0) {
+ _crep = 188;
+ } else {
+ _coreVar._atticRodHoleObjectId = _coreVar._selectedObjectId;
+ }
+ }
+
+ if (_caff == CRYPT) {
+ if (_coreVar._cryptObjectId != 0)
+ _crep = 188;
+ else
+ _coreVar._cryptObjectId = _coreVar._selectedObjectId;
+ }
+
+ if (_caff == WELL)
+ _crep = 185;
+ if ((_caff == CELLAR) || (_caff == SECRET_PASSAGE))
+ _crep = 124;
+ } else {
+ _crep = 124;
+ if (_caff == WELL) {
+ setCoordinates(5);
+ if (_num != 0)
+ _crep = 185;
+ }
+ }
+ }
+ if (_caff == INSIDE_WELL)
+ _crep = 185;
+ if ((_crep == 999) || (_crep == 185) || (_crep == 998)) {
+ if (_crep == 999)
+ ajchai();
+ if (_crep != 192)
+ displayEmptyHand();
+ }
+ }
+}
+
+/**
+ * Engine function - Listen
+ * @remarks Originally called 'tecouter'
+ */
+void MortevielleEngine::fctListen() {
+ if (_coreVar._currPlace != ROOM26)
+ _crep = 101;
+ else {
+ if (_currBitIndex != 0)
+ ++_coreVar._faithScore;
+ int rand;
+ int p = getPresenceStats(rand, _coreVar._faithScore, _roomDoorId);
+ int l = _roomDoorId;
+ if (l != OWN_ROOM) {
+ if (p != -500) {
+ if (rand > p)
+ _crep = 101;
+ else {
+ setPresenceFlags(l);
+ int j, h, m;
+ updateHour(j, h, m);
+ rand = getRandomNumber(1, 100);
+ if ((h >= 0) && (h < 8)) {
+ if (rand > 30)
+ _crep = 101;
+ else
+ _crep = 178;
+ } else if (rand > 70)
+ _crep = 101;
+ else
+ _crep = 178;
+ }
+ } else
+ _crep = 178;
+ }
+ }
+}
+
+/**
+ * Engine function - Eat
+ * @remarks Originally called 'tmanger'
+ */
+void MortevielleEngine::fctEat() {
+ if ((_coreVar._currPlace > LANDING) && (_coreVar._currPlace < ROOM26)) {
+ _crep = 148;
+ } else {
+ exitRoom();
+ _coreVar._currPlace = DINING_ROOM;
+ _caff = DINING_ROOM;
+ resetRoomVariables(_coreVar._currPlace);
+ _menu.setDestinationText(_coreVar._currPlace);
+
+ int j, h, m;
+ updateHour(j, h, m);
+ if ((h == 12) || (h == 13) || (h == 19)) {
+ _coreVar._faithScore -= (_coreVar._faithScore / 7);
+ if (h == 12) {
+ if (m == 0)
+ h = 4;
+ else
+ h = 3;
+ }
+
+ if ((h == 13) || (h == 19)) {
+ if (m == 0)
+ h = 2;
+ else
+ h = 1;
+ }
+
+ _currentHourCount += h;
+ _crep = 135;
+ prepareRoom();
+ } else {
+ _crep = 134;
+ }
+ }
+}
+
+/**
+ * Engine function - Enter
+ * @remarks Originally called 'tentrer'
+ */
+void MortevielleEngine::fctEnter() {
+ if ((_coreVar._currPlace == MANOR_FRONT) || (_coreVar._currPlace == MANOR_BACK)) {
+ gotoDiningRoom();
+ _menu.setDestinationText(_coreVar._currPlace);
+ } else if (_coreVar._currPlace == LANDING)
+ showMoveMenuAlert();
+ else if (_roomDoorId == OWN_ROOM)
+ _crep = 997;
+ else if ((_roomDoorId == ROOM9) && (_coreVar._selectedObjectId != 136)) {
+ _crep = 189;
+ _coreVar._availableQuestion[8] = '*';
+ } else {
+ int z = 0;
+ if (!_blo)
+ z = getPresence(_roomDoorId);
+ if (z != 0) {
+ if ((_roomDoorId == TOILETS) || (_roomDoorId == BATHROOM))
+ _crep = 179;
+ else {
+ int randVal = (getRandomNumber(0, 10)) - 5;
+ _speechManager.startSpeech(7, randVal, 1);
+ displayAnimFrame(1, 1);
+
+ int charIndex = convertBitIndexToCharacterIndex(z);
+ ++_coreVar._faithScore;
+ _coreVar._currPlace = LANDING;
+ _currMenu = MENU_DISCUSS;
+ _currAction = (_menu._discussMenu[charIndex]._menuId << 8) | _menu._discussMenu[charIndex]._actionId;
+ _syn = true;
+ if (_roomDoorId == ROOM9) {
+ _col = true;
+ _caff = 70;
+ drawPictureWithText();
+ handleDescriptionText(2, _caff);
+ } else
+ _col = false;
+ resetRoomVariables(_roomDoorId);
+ _roomDoorId = OWN_ROOM;
+ }
+ } else {
+ int randVal = (getRandomNumber(0, 10)) - 5;
+ _speechManager.startSpeech(7, randVal, 1);
+ displayAnimFrame(1, 1);
+
+ _coreVar._currPlace = _roomDoorId;
+ prepareDisplayText();
+ resetRoomVariables(_coreVar._currPlace);
+ _menu.setDestinationText(_coreVar._currPlace);
+ _roomDoorId = OWN_ROOM;
+ _savedBitIndex = 0;
+ _currBitIndex = 0;
+ }
+ }
+}
+
+/**
+ * Engine function - Sleep
+ * @remarks Originally called 'tdormir'
+ */
+void MortevielleEngine::fctSleep() {
+ int j, h, m;
+
+ if ((_coreVar._currPlace > LANDING) && (_coreVar._currPlace < ROOM26)) {
+ _crep = 148;
+ return;
+ }
+ if (_coreVar._currPlace != OWN_ROOM) {
+ exitRoom();
+ _coreVar._currPlace = OWN_ROOM;
+ prepareDisplayText();
+ drawPictureWithText();
+ resetRoomVariables(_coreVar._currPlace);
+ _menu.setDestinationText(_coreVar._currPlace);
+ }
+ clearVerbBar();
+ clearDescriptionBar();
+ prepareScreenType2();
+ ecr2(getEngineString(S_WANT_TO_WAKE_UP));
+ updateHour(j, h, m);
+
+ int answer;
+ do {
+ if (h < 8) {
+ _coreVar._faithScore -= (_coreVar._faithScore / 20);
+ int z = (7 - h) * 2;
+ if (m == 30)
+ --z;
+ _currentHourCount += z;
+ h = 7;
+ }
+ _currentHourCount += 2;
+ ++h;
+ if (h > 23)
+ h = 0;
+ prepareRoom();
+ answer = _dialogManager.show(getEngineString(S_YES_NO), 1);
+ _anyone = false;
+ } while (answer != 1);
+ _crep = 998;
+ _num = 0;
+}
+
+/**
+ * Engine function - Force
+ * @remarks Originally called 'tdefoncer'
+ */
+void MortevielleEngine::fctForce() {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_SMASH));
+ if (_caff < DOOR)
+ displayStatusArrow();
+
+ if ((!_anyone) && (!_keyPressedEsc)) {
+ if (_coreVar._currPlace != ROOM26)
+ _crep = 997;
+ else {
+ _crep = 143;
+ _coreVar._faithScore += 2;
+ }
+ }
+}
+
+/**
+ * Engine function - Leave
+ * @remarks Originally called 'tsortir'
+ */
+void MortevielleEngine::fctLeave() {
+ exitRoom();
+ _crep = 0;
+ if ((_coreVar._currPlace == MOUNTAIN) || (_coreVar._currPlace == MANOR_FRONT) || (_coreVar._currPlace == MANOR_BACK) || (_coreVar._currPlace == WELL))
+ _crep = 997;
+ else {
+ int nextPlace = OWN_ROOM;
+
+ if ((_coreVar._currPlace < CRYPT) || (_coreVar._currPlace == ROOM26))
+ nextPlace = DINING_ROOM;
+ else if ((_coreVar._currPlace == DINING_ROOM) || (_coreVar._currPlace == CHAPEL))
+ nextPlace = MANOR_FRONT;
+ else if ((_coreVar._currPlace < DINING_ROOM) || (_coreVar._currPlace == ATTIC))
+ nextPlace = LANDING;
+ else if (_coreVar._currPlace == CRYPT) {
+ nextPlace = SECRET_PASSAGE;
+ _crep = 176;
+ } else if (_coreVar._currPlace == SECRET_PASSAGE)
+ nextPlace = checkLeaveSecretPassage();
+ else if (_coreVar._currPlace == INSIDE_WELL)
+ nextPlace = WELL;
+
+ if (_crep != 997)
+ _coreVar._currPlace = nextPlace;
+
+ _caff = nextPlace;
+ if (_crep == 0)
+ _crep = nextPlace;
+ resetRoomVariables(nextPlace);
+ _menu.setDestinationText(nextPlace);
+ }
+}
+
+/**
+ * Engine function - Wait
+ * @remarks Originally called 'tattendre'
+ */
+void MortevielleEngine::fctWait() {
+ _savedBitIndex = 0;
+ clearVerbBar();
+
+ int answer;
+ do {
+ ++_currentHourCount;
+ prepareRoom();
+ if (!_blo)
+ getPresence(_coreVar._currPlace);
+ if ((_currBitIndex != 0) && (_savedBitIndex == 0)) {
+ _crep = 998;
+ if ((_coreVar._currPlace == ATTIC) || (_coreVar._currPlace == CELLAR))
+ initCaveOrCellar();
+ if ((_coreVar._currPlace > OWN_ROOM) && (_coreVar._currPlace < DINING_ROOM))
+ _anyone = true;
+ _savedBitIndex = _currBitIndex;
+ if (!_anyone)
+ prepareRoom();
+ return;
+ }
+ handleDescriptionText(2, 102);
+ answer = _dialogManager.show(getEngineString(S_YES_NO), 1);
+ } while (answer != 2);
+ _crep = 998;
+ if (!_anyone)
+ prepareRoom();
+}
+
+/**
+ * Engine function - Sound
+ * @remarks Originally called 'tsonder'
+ */
+void MortevielleEngine::fctSound() {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_PROBE2));
+ if (_caff < 27) {
+ displayStatusArrow();
+ if (!(_anyone) && (!_keyPressedEsc))
+ _crep = 145;
+ _num = 0;
+ }
+}
+
+/**
+ * Engine function - Discuss
+ * @remarks Originally called 'tparler'
+ */
+void MortevielleEngine::fctDiscuss() {
+ bool questionAsked[47];
+ int cy, cx;
+ int x, y;
+ Common::String lib[47];
+
+ int choice;
+ int displId;
+
+ endSearch();
+ if (_col)
+ displId = 128;
+ else {
+ cx = 0;
+ int oldMenu;
+ do {
+ ++cx;
+ oldMenu = (_menu._discussMenu[cx]._menuId << 8) | _menu._discussMenu[cx]._actionId;
+ } while (oldMenu != _currAction);
+ _caff = 69 + cx;
+ drawPictureWithText();
+ handleDescriptionText(2, _caff);
+ displId = _caff + 60;
+ }
+ testKey(false);
+ mennor();
+ _mouse.hideMouse();
+ hirs();
+ premtet();
+ startDialog(displId);
+ hirs();
+ for (int ix = 1; ix <= 46; ++ix)
+ questionAsked[ix] = false;
+ for (int ix = 1; ix <= 45; ++ix) {
+ lib[ix] = getString(ix + kQuestionStringIndex);
+ for (int i = lib[ix].size(); i <= 40; ++i)
+ lib[ix] = lib[ix] + ' ';
+ }
+ lib[46] = lib[45];
+ lib[45] = ' ';
+ _mouse.showMouse();
+ do {
+ choice = 0;
+ int posX = 0;
+ int posY = 0;
+ for (int icm = 1; icm < 43; icm++) {
+ _screenSurface.putxy(posX, posY);
+ if (_coreVar._availableQuestion[icm] == '*') {
+ // If question already asked, write it in reverse video
+ if (questionAsked[icm])
+ displayQuestionText(lib[icm], 1);
+ else
+ displayQuestionText(lib[icm], 0);
+ }
+
+ if (icm == 23) {
+ posY = 0;
+ posX = 320;
+ } else
+ posY += 8;
+ }
+ _screenSurface.putxy(320, 176);
+ displayQuestionText(lib[46], 0);
+ char retKey = '\0';
+ bool click;
+ do {
+ bool dummyFl;
+ _mouse.moveMouse(dummyFl, retKey);
+ if (shouldQuit())
+ return;
+
+ _mouse.getMousePosition(x, y, click);
+ x *= (3 - _resolutionScaler);
+ if (x > 319)
+ cx = 41;
+ else
+ cx = 1;
+ cy = ((uint)y >> 3) + 1; // 0-199 => 1-25
+ if ((cy > 23) || ((cx == 41) && ((cy >= 20) && (cy <= 22)))) {
+ if (choice != 0) {
+ posY = ((choice - 1) % 23) << 3;
+ if (choice > 23)
+ posX = 320;
+ else
+ posX = 0;
+ _screenSurface.putxy(posX, posY);
+ if (questionAsked[choice])
+ displayQuestionText(lib[choice], 0);
+ else
+ displayQuestionText(lib[choice], 1);
+ questionAsked[choice] = !questionAsked[choice];
+ choice = 0;
+ }
+ } else {
+ int ix = cy;
+ if (cx == 41)
+ ix += 23;
+ if (ix != choice) {
+ if (choice != 0) {
+ posY = ((choice - 1) % 23) << 3;
+ if (choice > 23)
+ posX = 320;
+ else
+ posX = 0;
+ _screenSurface.putxy(posX, posY);
+ if (questionAsked[choice])
+ displayQuestionText(lib[choice], 0);
+ else
+ displayQuestionText(lib[choice], 1);
+ questionAsked[choice] = ! questionAsked[choice];
+ }
+ if ((_coreVar._availableQuestion[ix] == '*') || (ix == 46)) {
+ posY = ((ix - 1) % 23) << 3;
+ if (ix > 23)
+ posX = 320;
+ else
+ posX = 0;
+ _screenSurface.putxy(posX, posY);
+ if (questionAsked[ix])
+ displayQuestionText(lib[ix], 0);
+ else
+ displayQuestionText(lib[ix], 1);
+ questionAsked[ix] = ! questionAsked[ix];
+ choice = ix;
+ } else
+ choice = 0;
+ }
+ }
+ } while (!((retKey == '\15') || (((click != 0) || getMouseClick()) && (choice != 0))));
+ setMouseClick(false);
+
+ // If choice is not "End of Conversation"
+ if (choice != 46) {
+ int ix = choice - 1;
+ if (_col) {
+ _col = false;
+ _coreVar._currPlace = 15;
+ int maxRandVal;
+ if (_openObjCount > 0)
+ maxRandVal = 8;
+ else
+ maxRandVal = 4;
+ if (getRandomNumber(1, maxRandVal) == 2)
+ displId = 129;
+ else {
+ displId = 138;
+ _coreVar._faithScore += (3 * (_coreVar._faithScore / 10));
+ }
+ } else if (_charAnswerCount[_caff - 69] < _charAnswerMax[_caff - 69]) {
+ displId = _tabdon[kArep + (ix << 3) + (_caff - 70)];
+ _coreVar._faithScore += _tabdon[kArcf + ix];
+ ++_charAnswerCount[_caff - 69];
+ } else {
+ _coreVar._faithScore += 3;
+ displId = 139;
+ }
+ _mouse.hideMouse();
+ hirs();
+ premtet();
+ startDialog(displId);
+ _mouse.showMouse();
+ if ((displId == 84) || (displId == 86)) {
+ _coreVar._pctHintFound[5] = '*';
+ _coreVar._availableQuestion[7] = '*';
+ }
+ if ((displId == 106) || (displId == 108) || (displId == 94)) {
+ for (int indx = 29; indx <= 31; ++indx)
+ _coreVar._availableQuestion[indx] = '*';
+ _coreVar._pctHintFound[7] = '*';
+ }
+ if (displId == 70) {
+ _coreVar._pctHintFound[8] = '*';
+ _coreVar._availableQuestion[32] = '*';
+ }
+ _mouse.hideMouse();
+ hirs();
+ _mouse.showMouse();
+ }
+ } while ((choice != 46) && (displId != 138));
+ if (_col) {
+ _coreVar._faithScore += (3 * (_coreVar._faithScore / 10));
+ _mouse.hideMouse();
+ hirs();
+ premtet();
+ startDialog(138);
+ _mouse.showMouse();
+ _col = false;
+ _coreVar._currPlace = LANDING;
+ }
+ _controlMenu = 0;
+ _mouse.hideMouse();
+ hirs();
+ drawRightFrame();
+ _mouse.showMouse();
+ showPeoplePresent(_currBitIndex);
+ prepareRoom();
+ drawClock();
+ prepareDisplayText();
+ /* chech;*/
+ _menu.setDestinationText(_coreVar._currPlace);
+ clearVerbBar();
+}
+
+/**
+ * Engine function - Smell
+ * @remarks Originally called 'tsentir'
+ */
+void MortevielleEngine::fctSmell() {
+ _crep = 119;
+ if (_caff < ROOM26) {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_SMELL));
+ displayStatusArrow();
+ if (!(_anyone) && !(_keyPressedEsc))
+ if (_caff == CRYPT)
+ _crep = 153;
+ } else if (_caff == 123)
+ _crep = 110;
+ _num = 0;
+}
+
+/**
+ * Engine function - Scratch
+ * @remarks Originally called 'tgratter'
+ */
+void MortevielleEngine::fctScratch() {
+ _crep = 155;
+ if (_caff < 27) {
+ if (!_syn)
+ displayTextInVerbBar(getEngineString(S_SCRATCH));
+ displayStatusArrow();
+ }
+ _num = 0;
+}
+
+/**
+ * The game is over
+ * @remarks Originally called 'tmaj1'
+ */
+void MortevielleEngine::endGame() {
+ _quitGame = true;
+ tlu(13, 152);
+ displayEmptyHand();
+ clearUpperLeftPart();
+ clearDescriptionBar();
+ clearVerbBar();
+ handleDescriptionText(9, 1509);
+ testKey(false);
+ _mouse.hideMouse();
+ _caff = 70;
+ _text.taffich();
+ hirs();
+ premtet();
+ startDialog(141);
+ _mouse.showMouse();
+ clearUpperLeftPart();
+ handleDescriptionText(9, 1509);
+ handleDescriptionText(2, 142);
+ testKey(false);
+ _caff = 32;
+ drawPictureWithText();
+ handleDescriptionText(6, 34);
+ handleDescriptionText(2, 35);
+ startMusicOrSpeech(0);
+ testKey(false);
+ // A wait message was displayed.
+ // testKey (aka tkey1) was called before and after.
+ // This double call is useless, thus removed
+ resetVariables();
+}
+
+/**
+ * You lost!
+ * @remarks Originally called 'tencore'
+ */
+void MortevielleEngine::askRestart() {
+ clearDescriptionBar();
+ startMusicOrSpeech(0);
+ testKey(false);
+ displayEmptyHand();
+ resetVariables();
+ initGame();
+ _currHour = 10;
+ _currHalfHour = 0;
+ _currDay = 0;
+ _minute = 0;
+ _hour = 10;
+ _day = 0;
+ handleDescriptionText(2, 180);
+
+ int answer = _dialogManager.show(getEngineString(S_YES_NO), 1);
+ _quitGame = (answer != 1);
+}
+
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/debugger.cpp b/engines/mortevielle/debugger.cpp
new file mode 100644
index 0000000000..4ef5151c81
--- /dev/null
+++ b/engines/mortevielle/debugger.cpp
@@ -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.
+ *
+ */
+
+#include "mortevielle/mortevielle.h"
+#include "mortevielle/debugger.h"
+
+namespace Mortevielle {
+
+Debugger::Debugger() : GUI::Debugger() {
+ DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
+ DCmd_Register("show_questions", WRAP_METHOD(Debugger, Cmd_showAllQuestions));
+ DCmd_Register("reset_parano", WRAP_METHOD(Debugger, Cmd_resetParano));
+}
+
+bool Debugger::Cmd_showAllQuestions(int argc, const char **argv) {
+ for (int i = 1; i <= 10; ++i)
+ _vm->_coreVar._pctHintFound[i] = '*';
+
+ for (int i = 1; i <= 42; ++i)
+ _vm->_coreVar._availableQuestion[i] = '*';
+
+ for (int i = 0; i < 9; i++) {
+ _vm->_charAnswerCount[i] = 0;
+ _vm->_charAnswerMax[i] = 999;
+ }
+
+ return true;
+}
+
+bool Debugger::Cmd_resetParano(int argc, const char **argv) {
+ _vm->_coreVar._faithScore = 0;
+
+ return true;
+}
+
+void Debugger::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+
+} // End of namespace Mortevielle
diff --git a/backends/platform/bada/application.h b/engines/mortevielle/debugger.h
index 2b0d37f1ef..9041d90110 100644
--- a/backends/platform/bada/application.h
+++ b/engines/mortevielle/debugger.h
@@ -8,47 +8,42 @@
* 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 BADA_APPLICATION_H
-#define BADA_APPLICATION_H
+#ifndef MORTEVIELLE_DEBUGGER_H
+#define MORTEVIELLE_DEBUGGER_H
-#include <FBase.h>
-#include <FApp.h>
-#include <FGraphics.h>
-#include <FUi.h>
-#include <FSystem.h>
+#include "common/scummsys.h"
+#include "gui/debugger.h"
-#include "backends/platform/bada/system.h"
+namespace Mortevielle {
-class BadaScummVM : public Osp::App::Application {
-public:
- BadaScummVM();
- ~BadaScummVM();
+class MortevielleEngine;
- static Osp::App::Application *createInstance(void);
+class Debugger : public GUI::Debugger {
+private:
+ MortevielleEngine *_vm;
- bool OnAppInitializing(Osp::App::AppRegistry &appRegistry);
- bool OnAppTerminating(Osp::App::AppRegistry &appRegistry, bool forcedTermination = false);
- void OnForeground(void);
- void OnBackground(void);
- void OnLowMemory(void);
- void OnBatteryLevelChanged(Osp::System::BatteryLevel batteryLevel);
- void OnUserEventReceivedN(RequestId requestId, Osp::Base::Collection::IList *pArgs);
+protected:
+ bool Cmd_showAllQuestions(int argc, const char **argv);
+ bool Cmd_resetParano(int argc, const char **argv);
-private:
- void pauseGame(bool pause);
- BadaAppForm *_appForm;
+public:
+ Debugger();
+ virtual ~Debugger() {}
+ void setParent(MortevielleEngine *vm);
};
+} // End of namespace Mortevielle
+
#endif
diff --git a/engines/mortevielle/detection.cpp b/engines/mortevielle/detection.cpp
new file mode 100644
index 0000000000..28cbc77b8b
--- /dev/null
+++ b/engines/mortevielle/detection.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 "base/plugins.h"
+#include "engines/advancedDetector.h"
+
+#include "mortevielle/mortevielle.h"
+#include "mortevielle/detection_tables.h"
+#include "mortevielle/saveload.h"
+
+namespace Mortevielle {
+uint32 MortevielleEngine::getGameFlags() const { return _gameDescription->flags; }
+
+Common::Language MortevielleEngine::getLanguage() const { return _gameDescription->language; }
+
+}
+
+static const PlainGameDescriptor MortevielleGame[] = {
+ {"mortevielle", "Mortville Manor"},
+ {0, 0}
+};
+
+class MortevielleMetaEngine : public AdvancedMetaEngine {
+public:
+ MortevielleMetaEngine() : AdvancedMetaEngine(Mortevielle::MortevielleGameDescriptions, sizeof(ADGameDescription),
+ MortevielleGame) {
+ _md5Bytes = 512;
+ _singleid = "mortevielle";
+ }
+ virtual const char *getName() const {
+ return "Mortevielle";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "Mortville Manor (C) 1987-89 Lankhor";
+ }
+
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual bool hasFeature(MetaEngineFeature f) const;
+ virtual int getMaximumSaveSlot() const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+};
+
+bool MortevielleMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ if (desc) {
+ *engine = new Mortevielle::MortevielleEngine(syst, desc);
+ }
+ return desc != 0;
+}
+
+bool MortevielleMetaEngine::hasFeature(MetaEngineFeature f) const {
+ switch (f) {
+ case kSupportsListSaves:
+ case kSupportsDeleteSave:
+ case kSupportsLoadingDuringStartup:
+ case kSavesSupportMetaInfo:
+ case kSavesSupportThumbnail:
+ case kSavesSupportCreationDate:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int MortevielleMetaEngine::getMaximumSaveSlot() const { return 99; }
+
+SaveStateList MortevielleMetaEngine::listSaves(const char *target) const {
+ return Mortevielle::SavegameManager::listSaves(target);
+}
+
+SaveStateDescriptor MortevielleMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+ Common::String filename = Mortevielle::MortevielleEngine::generateSaveFilename(target, slot);
+ return Mortevielle::SavegameManager::querySaveMetaInfos(filename);
+}
+
+
+#if PLUGIN_ENABLED_DYNAMIC(MORTEVIELLE)
+ REGISTER_PLUGIN_DYNAMIC(MORTEVIELLE, PLUGIN_TYPE_ENGINE, MortevielleMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(MORTEVIELLE, PLUGIN_TYPE_ENGINE, MortevielleMetaEngine);
+#endif
diff --git a/engines/mortevielle/detection_tables.h b/engines/mortevielle/detection_tables.h
new file mode 100644
index 0000000000..689fee1222
--- /dev/null
+++ b/engines/mortevielle/detection_tables.h
@@ -0,0 +1,88 @@
+/* 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 Mortevielle {
+
+static const ADGameDescription MortevielleGameDescriptions[] = {
+ // French
+ {
+ "mortevielle",
+ "",
+ {
+ {"menufr.mor", 0, "e413f36b9e14eef16130adc347a9391f", 144},
+ {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+ AD_LISTEND
+ },
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ // French
+ {
+ "mortevielle",
+ "",
+ {
+ {"menu.mor", 0, "3fef0a3f8fca99fdcb6dbca8cbcef46f", 160},
+ {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+ AD_LISTEND
+ },
+ Common::FR_FRA,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+ // German
+ {
+ "mortevielle",
+ "",
+ {
+ {"menual.mor", 0, "792aea282b07a1d74c4a4abeabc90c19", 144},
+ {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+ AD_LISTEND
+ },
+ Common::DE_DEU,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+
+ // English. Note that this is technically the French version, but English strings in mort.dat
+ // will automatically replace all the French strings
+ {
+ "mortevielle",
+ "",
+ {
+ {"menufr.mor", 0, "e413f36b9e14eef16130adc347a9391f", 144},
+ {"dxx.mor", 0, "949e68e829ecd5ad29e36a00347a9e7e", 207744},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO0()
+ },
+
+ AD_TABLE_END_MARKER
+};
+
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/dialogs.cpp b/engines/mortevielle/dialogs.cpp
new file mode 100644
index 0000000000..ba5d984886
--- /dev/null
+++ b/engines/mortevielle/dialogs.cpp
@@ -0,0 +1,494 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+
+#include "mortevielle/dialogs.h"
+#include "mortevielle/mouse.h"
+#include "mortevielle/outtext.h"
+#include "mortevielle/speech.h"
+
+#include "common/str.h"
+
+namespace Mortevielle {
+
+/**
+ * Alert function - Show
+ * @remarks Originally called 'do_alert'
+ */
+int DialogManager::show(const Common::String &msg, int n) {
+ // Make a copy of the current screen surface for later restore
+ _vm->_backgroundSurface.copyFrom(_vm->_screenSurface);
+
+ _vm->_mouse.hideMouse();
+ while (_vm->keyPressed())
+ _vm->getChar();
+
+ _vm->setMouseClick(false);
+
+ int colNumb = 0;
+ int lignNumb = 0;
+ int caseNumb = 0;
+ Common::String alertStr = "";
+ Common::String caseStr;
+
+ decodeAlertDetails(msg, caseNumb, lignNumb, colNumb, alertStr, caseStr);
+
+ int i = 0;
+ Common::Point curPos;
+ if (alertStr == "") {
+ drawAlertBox(10, 5, colNumb);
+ } else {
+ drawAlertBox(8, 7, colNumb);
+ i = 0;
+ _vm->_screenSurface._textPos.y = 70;
+ do {
+ curPos.x = 320;
+ Common::String displayStr = "";
+ while ((alertStr[i + 1] != '\174') && (alertStr[i + 1] != '\135')) {
+ ++i;
+ displayStr += alertStr[i];
+ if (_vm->_resolutionScaler == 2)
+ curPos.x -= 3;
+ else
+ curPos.x -= 5;
+ }
+ _vm->_screenSurface.putxy(curPos.x, _vm->_screenSurface._textPos.y);
+ _vm->_screenSurface._textPos.y += 6;
+ _vm->_screenSurface.drawString(displayStr, 4);
+ ++i;
+ } while (alertStr[i] != ']');
+ }
+ int esp;
+ if (caseNumb == 1)
+ esp = colNumb - 40;
+ else
+ esp = (uint)(colNumb - caseNumb * 40) / 2;
+
+ int coldep = 320 - ((uint)colNumb / 2) + ((uint)esp / 2);
+ Common::String buttonStr[3];
+ setButtonText(caseStr, coldep, caseNumb, &buttonStr[0], esp);
+
+ int limit[3][3];
+ memset(&limit[0][0], 0, sizeof(int) * 3 * 3);
+
+ limit[1][1] = ((uint)(coldep) / 2) * _vm->_resolutionScaler;
+ limit[1][2] = limit[1][1] + 40;
+ if (caseNumb == 1) {
+ limit[2][1] = limit[2][2];
+ } else {
+ limit[2][1] = ((uint)(320 + ((uint)esp >> 1)) / 2) * _vm->_resolutionScaler;
+ limit[2][2] = (limit[2][1]) + 40;
+ }
+ _vm->_mouse.showMouse();
+ int id = 0;
+ bool dummyFl = false;
+ bool test3;
+ do {
+ char dummyKey = '\377';
+ _vm->_mouse.moveMouse(dummyFl, dummyKey);
+ if (_vm->shouldQuit())
+ return 0;
+
+ curPos = _vm->_mouse._pos;
+ bool newaff = false;
+ if ((curPos.y > 95) && (curPos.y < 105)) {
+ bool test1 = (curPos.x > limit[1][1]) && (curPos.x < limit[1][2]);
+ bool test2 = test1;
+ if (caseNumb > 1)
+ test2 |= ((curPos.x > limit[2][1]) && (curPos.x < limit[2][2]));
+ if (test2) {
+ newaff = true;
+
+ int ix;
+ if (test1)
+ ix = 1;
+ else
+ ix = 2;
+ if (ix != id) {
+ _vm->_mouse.hideMouse();
+ if (id != 0) {
+ setPosition(id, coldep, esp);
+
+ Common::String tmpStr(" ");
+ tmpStr += buttonStr[id];
+ tmpStr += " ";
+ _vm->_screenSurface.drawString(tmpStr, 0);
+ }
+ setPosition(ix, coldep, esp);
+
+ Common::String tmp2 = " ";
+ tmp2 += buttonStr[ix];
+ tmp2 += " ";
+ _vm->_screenSurface.drawString(tmp2, 1);
+
+ id = ix;
+ _vm->_mouse.showMouse();
+ }
+ }
+ }
+ if ((id != 0) && !newaff) {
+ _vm->_mouse.hideMouse();
+ setPosition(id, coldep, esp);
+
+ Common::String tmp3(" ");
+ tmp3 += buttonStr[id];
+ tmp3 += " ";
+ _vm->_screenSurface.drawString(tmp3, 0);
+
+ id = 0;
+ _vm->_mouse.showMouse();
+ }
+ test3 = (curPos.y > 95) && (curPos.y < 105) && (((curPos.x > limit[1][1]) && (curPos.x < limit[1][2]))
+ || ((curPos.x > limit[2][1]) && (curPos.x < limit[2][2])));
+ } while (!_vm->getMouseClick());
+ _vm->setMouseClick(false);
+ _vm->_mouse.hideMouse();
+ if (!test3) {
+ id = n;
+ setPosition(n, coldep, esp);
+ Common::String tmp4(" ");
+ tmp4 += buttonStr[n];
+ tmp4 += " ";
+ _vm->_screenSurface.drawString(tmp4, 1);
+ }
+ _vm->_mouse.showMouse();
+
+ /* Restore the background area */
+ _vm->_screenSurface.copyFrom(_vm->_backgroundSurface, 0, 0);
+
+ return id;
+}
+
+/**
+ * Alert function - Decode Alert Details
+ * @remarks Originally called 'decod'
+ */
+void DialogManager::decodeAlertDetails(Common::String inputStr, int &choiceNumb, int &lineNumb, int &col, Common::String &choiceStr, Common::String &choiceListStr) {
+ // The second character of the string contains the number of choices
+ choiceNumb = atoi(inputStr.c_str() + 1);
+
+ choiceStr = "";
+ col = 0;
+ lineNumb = 0;
+
+ // Originally set to 5, decreased to 4 because strings are 0 based, and not 1 based as in Pascal
+ int i = 4;
+ int k = 0;
+ bool empty = true;
+
+ for (; inputStr[i] != ']'; ++i) {
+ choiceStr += inputStr[i];
+ if ((inputStr[i] == '|') || (inputStr[i + 1] == ']')) {
+ if (k > col)
+ col = k;
+ k = 0;
+ ++lineNumb;
+ } else if (inputStr[i] != ' ')
+ empty = false;
+ ++k;
+ }
+
+ if (empty) {
+ choiceStr = "";
+ col = 20;
+ } else {
+ choiceStr += ']';
+ col += 6;
+ }
+
+ choiceListStr = Common::String(inputStr.c_str() + i);
+ if (_vm->_resolutionScaler == 2)
+ col *= 6;
+ else
+ col *= 10;
+}
+
+void DialogManager::setPosition(int ji, int coldep, int esp) {
+ _vm->_screenSurface.putxy(coldep + (40 + esp) * (ji - 1), 98);
+}
+
+/**
+ * Alert function - Draw Alert Box
+ * @remarks Originally called 'fait_boite'
+ */
+void DialogManager::drawAlertBox(int lidep, int nli, int tx) {
+ if (tx > 640)
+ tx = 640;
+ int x = 320 - ((uint)tx / 2);
+ int y = (lidep - 1) * 8;
+ int xx = x + tx;
+ int yy = y + (nli * 8);
+ _vm->_screenSurface.fillRect(15, Common::Rect(x, y, xx, yy));
+ _vm->_screenSurface.fillRect(0, Common::Rect(x, y + 2, xx, y + 4));
+ _vm->_screenSurface.fillRect(0, Common::Rect(x, yy - 4, xx, yy - 2));
+}
+
+/**
+ * Alert function - Set Button Text
+ * @remarks Originally called 'fait_choix'
+ */
+void DialogManager::setButtonText(Common::String c, int coldep, int nbcase, Common::String *str, int esp) {
+ int i = 1;
+ int x = coldep;
+ for (int l = 1; l <= nbcase; ++l) {
+ str[l] = "";
+ do {
+ ++i;
+ char ch = c[i];
+ str[l] += ch;
+ } while (c[i + 1] != ']');
+ i += 2;
+
+ while (str[l].size() < 3)
+ str[l] += ' ';
+
+ _vm->_screenSurface.putxy(x, 98);
+
+ Common::String tmp(" ");
+ tmp += str[l];
+ tmp += " ";
+
+ _vm->_screenSurface.drawString(tmp, 0);
+ x += esp + 40;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+/**
+ * Questions asked before entering the hidden passage
+ */
+bool DialogManager::showKnowledgeCheck() {
+ const int textIndexArr[10] = {511, 516, 524, 531, 545, 552, 559, 563, 570, 576};
+ const int correctAnswerArr[10] = {4, 7, 1, 6, 4, 4, 2, 5, 3, 1 };
+
+ Hotspot coor[kMaxHotspots+1];
+
+ for (int i = 0; i <= kMaxHotspots; ++i) {
+ coor[i]._rect = Common::Rect();
+ coor[i]._enabled = false;
+ }
+
+ Common::String choiceArray[15];
+
+ int currChoice, prevChoice;
+ int correctCount = 0;
+
+ for (int indx = 0; indx < 10; ++indx) {
+ _vm->_mouse.hideMouse();
+ _vm->hirs();
+ _vm->_mouse.showMouse();
+ int dialogHeight;
+ if (_vm->_resolutionScaler == 1)
+ dialogHeight = 29;
+ else
+ dialogHeight = 23;
+ _vm->_screenSurface.fillRect(15, Common::Rect(0, 14, 630, dialogHeight));
+ Common::String tmpStr = _vm->getString(textIndexArr[indx]);
+ _vm->_text.displayStr(tmpStr, 20, 15, 100, 2, 0);
+
+ int firstOption;
+ int lastOption;
+
+ if (indx != 9) {
+ firstOption = textIndexArr[indx] + 1;
+ lastOption = textIndexArr[indx + 1] - 1;
+ } else {
+ firstOption = 503;
+ lastOption = 510;
+ }
+ int optionPosY = 35;
+ int maxLength = 0;
+
+ prevChoice = 1;
+ for (int j = firstOption; j <= lastOption; ++j, ++prevChoice) {
+ tmpStr = _vm->getString(j);
+ if ((int) tmpStr.size() > maxLength)
+ maxLength = tmpStr.size();
+ _vm->_text.displayStr(tmpStr, 100, optionPosY, 100, 1, 0);
+ choiceArray[prevChoice] = tmpStr;
+ optionPosY += 8;
+ }
+
+ for (int j = 1; j <= lastOption - firstOption + 1; ++j) {
+ coor[j]._rect = Common::Rect(45 * _vm->_resolutionScaler, 27 + j * 8, (maxLength * 3 + 55) * _vm->_resolutionScaler, 34 + j * 8);
+ coor[j]._enabled = true;
+
+ while ((int)choiceArray[j].size() < maxLength) {
+ choiceArray[j] += ' ';
+ }
+ }
+ coor[lastOption - firstOption + 2]._enabled = false;
+ int rep;
+ if (_vm->_resolutionScaler == 1)
+ rep = 10;
+ else
+ rep = 6;
+ _vm->_screenSurface.drawBox(80, 33, 40 + (maxLength * rep), (lastOption - firstOption) * 8 + 16, 15);
+ rep = 0;
+
+ prevChoice = 0;
+ warning("Expected answer: %d", correctAnswerArr[indx]);
+ do {
+ _vm->setMouseClick(false);
+ bool flag;
+ char key;
+ _vm->_mouse.moveMouse(flag, key);
+ if (_vm->shouldQuit())
+ return false;
+
+ currChoice = 1;
+ while (coor[currChoice]._enabled && !_vm->_mouse.isMouseIn(coor[currChoice]._rect))
+ ++currChoice;
+ if (coor[currChoice]._enabled) {
+ if ((prevChoice != 0) && (prevChoice != currChoice)) {
+ tmpStr = choiceArray[prevChoice] + '$';
+ _vm->_text.displayStr(tmpStr, 100, 27 + (prevChoice * 8), 100, 1, 0);
+ }
+ if (prevChoice != currChoice) {
+ tmpStr = choiceArray[currChoice] + '$';
+ _vm->_text.displayStr(tmpStr, 100, 27 + (currChoice * 8), 100, 1, 1);
+ prevChoice = currChoice;
+ }
+ } else if (prevChoice != 0) {
+ tmpStr = choiceArray[prevChoice] + '$';
+ _vm->_text.displayStr(tmpStr, 100, 27 + (prevChoice * 8), 100, 1, 0);
+ prevChoice = 0;
+ }
+ } while (!((prevChoice != 0) && _vm->getMouseClick()));
+
+ if (prevChoice == correctAnswerArr[indx])
+ // Answer is correct
+ ++correctCount;
+ else {
+ // Skip questions that may give hints on previous wrong answer
+ if (indx == 4)
+ ++indx;
+ else if ((indx == 6) || (indx == 7))
+ indx = 9;
+ }
+ }
+
+ return (correctCount == 10);
+}
+
+/*------------------------------------------------------------------------*/
+
+/**
+ * Draw the F3/F8 dialog
+ */
+void DialogManager::drawF3F8() {
+ Common::String f3 = _vm->getEngineString(S_F3);
+ Common::String f8 = _vm->getEngineString(S_F8);
+
+ // Write the F3 and F8 text strings
+ _vm->_screenSurface.putxy(3, 44);
+ _vm->_screenSurface.drawString(f3, 5);
+ _vm->_screenSurface._textPos.y = 51;
+ _vm->_screenSurface.drawString(f8, 5);
+
+ // Get the width of the written text strings
+ int f3Width = _vm->_screenSurface.getStringWidth(f3);
+ int f8Width = _vm->_screenSurface.getStringWidth(f8);
+
+ // Write out the bounding box
+ _vm->_screenSurface.drawBox(0, 42, MAX(f3Width, f8Width) + 6, 18, 7);
+}
+
+/**
+ * Alert function - Loop until F8 is pressed, update
+ * Graphical Device if modified
+ * @remarks Originally called 'diver'
+ */
+void DialogManager::checkForF8(int SpeechNum, bool drawFrame2Fl) {
+ _vm->testKeyboard();
+ do {
+ _vm->_speechManager.startSpeech(SpeechNum, 0, 0);
+ _vm->_key = waitForF3F8();
+ if (_vm->shouldQuit())
+ return;
+
+ if (_vm->_newGraphicalDevice != _vm->_currGraphicalDevice) {
+ _vm->_currGraphicalDevice = _vm->_newGraphicalDevice;
+ _vm->hirs();
+ displayIntroScreen(drawFrame2Fl);
+ }
+ } while (_vm->_key != 66); // keycode for F8
+}
+
+/**
+ * Alert function - Loop until F3 or F8 is pressed
+ * @remarks Originally called 'atf3f8'
+ */
+int DialogManager::waitForF3F8() {
+ int key;
+
+ do {
+ key = _vm->gettKeyPressed();
+ if (_vm->shouldQuit())
+ return key;
+ } while ((key != 61) && (key != 66));
+
+ return key;
+}
+
+/**
+ * Intro function - display intro screen
+ * @remarks Originally called 'aff50'
+ */
+void DialogManager::displayIntroScreen(bool drawFrame2Fl) {
+ _vm->_caff = 50;
+ _vm->_maff = 0;
+ _vm->_text.taffich();
+ _vm->draw(63, 12);
+ if (drawFrame2Fl)
+ displayIntroFrame2();
+ else
+ _vm->handleDescriptionText(2, kDialogStringIndex + 142);
+
+ // Draw the f3/f8 dialog
+ drawF3F8();
+}
+
+/**
+ * Intro function - display 2nd frame of intro
+ * @remarks Originally called 'ani50'
+ */
+void DialogManager::displayIntroFrame2() {
+ _vm->_crep = _vm->getAnimOffset(1, 1);
+ _vm->displayPicture(&_vm->_curAnim[_vm->_crep], 63, 12);
+ _vm->_crep = _vm->getAnimOffset(2, 1);
+ _vm->displayPicture(&_vm->_curAnim[_vm->_crep], 63, 12);
+ _vm->_largestClearScreen = (_vm->_resolutionScaler == 1);
+ _vm->handleDescriptionText(2, kDialogStringIndex + 143);
+}
+
+void DialogManager::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/dialogs.h b/engines/mortevielle/dialogs.h
new file mode 100644
index 0000000000..af667e40c5
--- /dev/null
+++ b/engines/mortevielle/dialogs.h
@@ -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.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#ifndef MORTEVIELLE_ALERT_H
+#define MORTEVIELLE_ALERT_H
+
+#include "common/rect.h"
+#include "common/str.h"
+
+namespace Mortevielle {
+class MortevielleEngine;
+
+static const int NUM_LINES = 7;
+const int kMaxHotspots = 14;
+
+struct Hotspot {
+ Common::Rect _rect;
+ bool _enabled;
+};
+
+class DialogManager {
+private:
+ MortevielleEngine *_vm;
+
+ void decodeAlertDetails(Common::String inputStr, int &choiceNumb, int &lineNumb, int &col, Common::String &choiceStr, Common::String &choiceListStr);
+ void setPosition(int ji, int coldep, int esp);
+ void drawAlertBox(int lidep, int nli, int tx);
+ void setButtonText(Common::String c, int coldep, int nbcase, Common::String *str, int esp);
+public:
+ void setParent(MortevielleEngine *vm);
+ int show(const Common::String &msg, int n);
+ void drawF3F8();
+ void checkForF8(int SpeechNum, bool drawFrame2Fl);
+ int waitForF3F8();
+ void displayIntroScreen(bool drawFrame2Fl);
+ void displayIntroFrame2();
+ bool showKnowledgeCheck();
+};
+
+} // End of namespace Mortevielle
+#endif
diff --git a/engines/mortevielle/graphics.cpp b/engines/mortevielle/graphics.cpp
new file mode 100644
index 0000000000..c066114e8d
--- /dev/null
+++ b/engines/mortevielle/graphics.cpp
@@ -0,0 +1,1187 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+#include "mortevielle/graphics.h"
+#include "mortevielle/mouse.h"
+
+#include "common/endian.h"
+#include "common/system.h"
+#include "graphics/palette.h"
+
+namespace Mortevielle {
+
+/*-------------------------------------------------------------------------*
+ * Palette Manager
+ *
+ *-------------------------------------------------------------------------*/
+
+/**
+ * Set palette entries from the 64 color available EGA palette
+ */
+void PaletteManager::setPalette(const int *palette, uint idx, uint size) {
+ assert((idx + size) <= 16);
+
+ // Build up the EGA palette
+ byte egaPalette[64 * 3];
+
+ byte *p = &egaPalette[0];
+ for (int i = 0; i < 64; ++i) {
+ *p++ = (i >> 2 & 1) * 0xaa + (i >> 5 & 1) * 0x55;
+ *p++ = (i >> 1 & 1) * 0xaa + (i >> 4 & 1) * 0x55;
+ *p++ = (i & 1) * 0xaa + (i >> 3 & 1) * 0x55;
+ }
+
+ // Loop through setting palette colors based on the passed indexes
+ for (; size > 0; --size, ++idx) {
+ int palIndex = palette[idx];
+ assert(palIndex < 64);
+
+ const byte *pRgb = (const byte *)&egaPalette[palIndex * 3];
+ g_system->getPaletteManager()->setPalette(pRgb, idx, 1);
+ }
+}
+
+/**
+ * Set the default EGA palette
+ */
+void PaletteManager::setDefaultPalette() {
+ const int defaultPalette[16] = { 0, 1, 2, 3, 4, 5, 20, 7, 56, 57, 58, 59, 60, 61, 62, 63 };
+ setPalette(defaultPalette, 0, 16);
+}
+
+/*-------------------------------------------------------------------------*
+ * Image decoding
+ *
+ * The code in this section is responsible for decoding image resources.
+ * Images are broken down into rectangular sections, which can use one
+ * of 18 different encoding methods.
+ *-------------------------------------------------------------------------*/
+
+#define INCR_XSIZE { if (_xSize & 1) ++_xSize; }
+#define DEFAULT_WIDTH (SCREEN_WIDTH / 2)
+#define BUFFER_SIZE 40000
+
+void GfxSurface::decode(const byte *pSrc) {
+ w = h = 0;
+ // If no transparency, use invalid (for EGA) palette index of 16. Otherwise get index to use
+ _transparency = (*pSrc == 0) ? 16 : *(pSrc + 2);
+ bool offsetFlag = *pSrc++ == 0;
+ int entryCount = *pSrc++;
+ pSrc += 2;
+
+ if (offsetFlag)
+ pSrc += 30;
+
+ // First run through the data to calculate starting offsets
+ const byte *p = pSrc;
+ _offset.x = _offset.y = 999;
+
+ assert(entryCount > 0);
+ for (int idx = 0; idx < entryCount; ++idx) {
+ _xp = READ_BE_UINT16(p + 4);
+ if (_xp < _offset.x)
+ _offset.x = _xp;
+
+ _yp = READ_BE_UINT16(p + 6);
+ if (_yp < _offset.y)
+ _offset.y = _yp;
+
+ // Move to next entry
+ int size = READ_BE_UINT16(p) + READ_BE_UINT16(p + 2);
+ if ((size % 2) == 1)
+ ++size;
+
+ p += size + 14;
+ }
+
+ // Temporary output buffer
+ byte *outputBuffer = (byte *)malloc(sizeof(byte) * 65536);
+ memset(outputBuffer, _transparency, 65536);
+
+ byte *pDest = &outputBuffer[0];
+ const byte *pSrcStart = pSrc;
+ const byte *pLookup = NULL;
+
+ byte *lookupTable = (byte *)malloc(sizeof(byte) * BUFFER_SIZE);
+ byte *srcBuffer = (byte *)malloc(sizeof(byte) * BUFFER_SIZE);
+
+ // Main processing loop
+ for (int entryIndex = 0; entryIndex < entryCount; ++entryIndex) {
+ int lookupBytes = READ_BE_UINT16(pSrc);
+ int srcSize = READ_BE_UINT16(pSrc + 2);
+ _xp = READ_BE_UINT16(pSrc + 4) - _offset.x;
+ _yp = READ_BE_UINT16(pSrc + 6) - _offset.y;
+ assert((_xp >= 0) && (_yp >= 0) && (_xp < SCREEN_WIDTH) && (_yp < SCREEN_ORIG_HEIGHT));
+ pSrc += 8;
+
+ int decomCode = READ_BE_UINT16(pSrc);
+ _xSize = READ_BE_UINT16(pSrc + 2) + 1;
+ _ySize = READ_BE_UINT16(pSrc + 4) + 1;
+ majTtxTty();
+
+ pSrc += 6;
+ pDest = &outputBuffer[0];
+
+ _lookupIndex = 0;
+ _nibbleFlag = false;
+
+ int decomIndex = 0;
+ if (decomCode >> 8) {
+ // Build up reference table
+ int tableOffset = 0;
+
+ if (decomCode & 1) {
+ // Handle decompression of the pattern lookup table
+ do {
+ int outerCount = desanalyse(pSrc);
+ int innerCount = desanalyse(pSrc);
+
+ const byte *pSrcSaved = pSrc;
+ bool savedNibbleFlag = _nibbleFlag;
+ int savedLookupIndex = _lookupIndex;
+
+ do {
+ pSrc = pSrcSaved;
+ _nibbleFlag = savedNibbleFlag;
+ _lookupIndex = savedLookupIndex;
+
+ for (int idx = 0; idx < innerCount; ++idx, ++tableOffset) {
+ assert(tableOffset < BUFFER_SIZE);
+ lookupTable[tableOffset] = nextNibble(pSrc);
+ }
+ } while (--outerCount > 0);
+ } while (_lookupIndex < (lookupBytes - 1));
+
+ } else {
+ assert(lookupBytes < BUFFER_SIZE);
+ for (int idx = 0; idx < (lookupBytes * 2); ++idx)
+ lookupTable[idx] = nextNibble(pSrc);
+ }
+
+ if (_nibbleFlag) {
+ ++pSrc;
+ _nibbleFlag = false;
+ }
+ if ((lookupBytes + srcSize) & 1)
+ ++pSrc;
+
+ tableOffset = 0;
+ _lookupIndex = 0;
+
+ if (decomCode & 2) {
+ // Handle decompression of the temporary source buffer
+ do {
+ int outerCount = desanalyse(pSrc);
+ int innerCount = desanalyse(pSrc);
+ _lookupIndex += innerCount;
+
+ if (_nibbleFlag) {
+ ++pSrc;
+ ++_lookupIndex;
+ _nibbleFlag = false;
+ }
+
+ const byte *pStart = pSrc;
+ do {
+ pSrc = pStart;
+ for (int idx = 0; idx < innerCount; ++idx) {
+ assert(tableOffset < BUFFER_SIZE);
+ srcBuffer[tableOffset++] = *pSrc++;
+ }
+ } while (--outerCount > 0);
+ } while (_lookupIndex < (srcSize - 1));
+ } else {
+ assert(srcSize < BUFFER_SIZE);
+ for (int idx = 0; idx < srcSize; ++idx)
+ srcBuffer[idx] = *pSrc++;
+ }
+
+ if (_nibbleFlag)
+ ++pSrc;
+
+ // Switch over to using the decompressed source and lookup buffers
+ pSrcStart = pSrc;
+ pDest = &outputBuffer[_yp * DEFAULT_WIDTH + _xp];
+ pSrc = &srcBuffer[0];
+ pLookup = &lookupTable[0] - 1;
+
+ _lookupValue = _lookupIndex = 0;
+ _nibbleFlag = false;
+ decomIndex = decomCode >> 8;
+ }
+
+ // Main decompression switch
+ switch (decomIndex) {
+ case 0:
+ // Draw rect at pos
+ pDest = &outputBuffer[_yp * DEFAULT_WIDTH + _xp];
+ pSrcStart = pSrc;
+ INCR_XSIZE;
+
+ for (int yCtr = 0; yCtr < _ySize; ++yCtr, pDest += DEFAULT_WIDTH) {
+ byte *pDestLine = pDest;
+ for (int xCtr = 0; xCtr < _xSize; ++xCtr) {
+ *pDestLine++ = nextNibble(pSrc);
+ }
+ }
+
+ pSrcStart += lookupBytes + ((lookupBytes & 1) ? 1 : 0);
+ break;
+
+ case 1:
+ // Draw rect using horizontal lines alternating left to right, then right to left
+ INCR_XSIZE;
+ for (int yCtr = 0; yCtr < _ySize; ++yCtr) {
+ if ((yCtr % 2) == 0) {
+ for (int xCtr = 0; xCtr < _xSize; ++xCtr) {
+ *pDest++ = nextByte(pSrc, pLookup);
+ }
+ } else {
+ for (int xCtr = 0; xCtr < _xSize; ++xCtr) {
+ *--pDest = nextByte(pSrc, pLookup);
+ }
+ }
+ pDest += DEFAULT_WIDTH;
+ }
+ break;
+
+ case 2:
+ // Draw rect alternating top to bottom, bottom to top
+ for (int xCtr = 0; xCtr < _xSize; ++xCtr) {
+ if ((xCtr % 2) == 0) {
+ for (int yCtr = 0; yCtr < _ySize; ++yCtr, pDest += DEFAULT_WIDTH) {
+ *pDest = nextByte(pSrc, pLookup);
+ }
+ } else {
+ for (int yCtr = 0; yCtr < _ySize; ++yCtr) {
+ pDest -= DEFAULT_WIDTH;
+ *pDest = nextByte(pSrc, pLookup);
+ }
+ }
+ ++pDest;
+ }
+ break;
+
+ case 3:
+ // Draw horizontal area?
+ _thickness = 2;
+ horizontal(pSrc, pDest, pLookup);
+ break;
+
+ case 4:
+ // Draw vertical area?
+ _thickness = 2;
+ vertical(pSrc, pDest, pLookup);
+ break;
+
+ case 5:
+ _thickness = 3;
+ horizontal(pSrc, pDest, pLookup);
+ break;
+
+ case 6:
+ _thickness = 4;
+ vertical(pSrc, pDest, pLookup);
+ break;
+
+ case 7:
+ // Draw rect using horizontal lines left to right
+ INCR_XSIZE;
+ for (int yCtr = 0; yCtr < _ySize; ++yCtr, pDest += DEFAULT_WIDTH) {
+ byte *pDestLine = pDest;
+ for (int xCtr = 0; xCtr < _xSize; ++xCtr)
+ *pDestLine++ = nextByte(pSrc, pLookup);
+ }
+ break;
+
+ case 8:
+ // Draw box
+ for (int xCtr = 0; xCtr < _xSize; ++xCtr, ++pDest) {
+ byte *pDestLine = pDest;
+ for (int yCtr = 0; yCtr < _ySize; ++yCtr, pDestLine += DEFAULT_WIDTH)
+ *pDestLine = nextByte(pSrc, pLookup);
+ }
+ break;
+
+ case 9:
+ _thickness = 4;
+ horizontal(pSrc, pDest, pLookup);
+ break;
+
+ case 10:
+ _thickness = 6;
+ horizontal(pSrc, pDest, pLookup);
+ break;
+
+ case 11:
+ decom11(pSrc, pDest, pLookup);
+ break;
+
+ case 12:
+ INCR_XSIZE;
+ _thickness = _xInc = 1;
+ _yInc = DEFAULT_WIDTH;
+ _yEnd = _ySize;
+ _xEnd = _xSize;
+ diag(pSrc, pDest, pLookup);
+ break;
+
+ case 13:
+ INCR_XSIZE;
+ _thickness = _xSize;
+ _yInc = 1;
+ _yEnd = _xSize;
+ _xInc = DEFAULT_WIDTH;
+ _xEnd = _ySize;
+ diag(pSrc, pDest, pLookup);
+ break;
+
+ case 14:
+ _thickness = _yInc = 1;
+ _yEnd = _xSize;
+ _xInc = DEFAULT_WIDTH;
+ _xEnd = _ySize;
+ diag(pSrc, pDest, pLookup);
+ break;
+
+ case 15:
+ INCR_XSIZE;
+ _thickness = 2;
+ _yInc = DEFAULT_WIDTH;
+ _yEnd = _ySize;
+ _xInc = 1;
+ _xEnd = _xSize;
+ diag(pSrc, pDest, pLookup);
+ break;
+
+ case 16:
+ _thickness = 3;
+ _yInc = 1;
+ _yEnd = _xSize;
+ _xInc = DEFAULT_WIDTH;
+ _xEnd = _ySize;
+ diag(pSrc, pDest, pLookup);
+ break;
+
+ case 17:
+ INCR_XSIZE;
+ _thickness = 3;
+ _yInc = DEFAULT_WIDTH;
+ _yEnd = _ySize;
+ _xInc = 1;
+ _xEnd = _xSize;
+ diag(pSrc, pDest, pLookup);
+ break;
+
+ case 18:
+ INCR_XSIZE;
+ _thickness = 5;
+ _yInc = DEFAULT_WIDTH;
+ _yEnd = _ySize;
+ _xInc = 1;
+ _xEnd = _xSize;
+ diag(pSrc, pDest, pLookup);
+ break;
+
+ default:
+ error("Unknown decompression block type %d", decomIndex);
+ }
+
+ pSrc = pSrcStart;
+ debugC(2, kMortevielleGraphics, "Decoding image block %d position %d,%d size %d,%d method %d",
+ entryIndex + 1, _xp, _yp, w, h, decomIndex);
+ }
+
+ // At this point, the outputBuffer has the data for the image. Initialize the surface
+ // with the calculated size, and copy the lines to the surface
+ create(w, h, Graphics::PixelFormat::createFormatCLUT8());
+
+ for (int yCtr = 0; yCtr < h; ++yCtr) {
+ const byte *copySrc = &outputBuffer[yCtr * DEFAULT_WIDTH];
+ byte *copyDest = (byte *)getBasePtr(0, yCtr);
+
+ Common::copy(copySrc, copySrc + w, copyDest);
+ }
+
+ ::free(outputBuffer);
+ ::free(lookupTable);
+ ::free(srcBuffer);
+}
+
+void GfxSurface::majTtxTty() {
+ if (!_yp)
+ w += _xSize;
+
+ if (!_xp)
+ h += _ySize;
+}
+
+/**
+ * Decompression Function - get next nibble
+ * @remarks Originally called 'suiv'
+ */
+byte GfxSurface::nextNibble(const byte *&pSrc) {
+ int v = *pSrc;
+ if (_nibbleFlag) {
+ ++pSrc;
+ ++_lookupIndex;
+ _nibbleFlag = false;
+ return v & 0xf;
+ } else {
+ _nibbleFlag = !_nibbleFlag;
+ return v >> 4;
+ }
+}
+
+/**
+ * Decompression Function - get next byte
+ * @remarks Originally called 'csuiv'
+ */
+byte GfxSurface::nextByte(const byte *&pSrc, const byte *&pLookup) {
+ assert(pLookup);
+
+ while (!_lookupValue) {
+ int v;
+ do {
+ v = nextNibble(pSrc) & 0xff;
+ _lookupValue += v;
+ } while (v == 0xf);
+ ++pLookup;
+ }
+
+ --_lookupValue;
+ return *pLookup;
+}
+
+int GfxSurface::desanalyse(const byte *&pSrc) {
+ int total = 0;
+ int v = nextNibble(pSrc);
+ if (v == 0xf) {
+ int v2;
+ do {
+ v2 = nextNibble(pSrc);
+ total += v2;
+ } while (v2 == 0xf);
+
+ total *= 15;
+ v = nextNibble(pSrc);
+ }
+
+ total += v;
+ return total;
+}
+
+void GfxSurface::horizontal(const byte *&pSrc, byte *&pDest, const byte *&pLookup) {
+ INCR_XSIZE;
+ byte *pDestEnd = pDest + (_ySize - 1) * DEFAULT_WIDTH + _xSize;
+
+ for (;;) {
+ // If position is past end point, then skip this line
+ if (((_thickness - 1) * DEFAULT_WIDTH) + pDest >= pDestEnd) {
+ if (--_thickness == 0)
+ break;
+ continue;
+ }
+
+ bool continueFlag = false;
+ do {
+ for (int xIndex = 0; xIndex < _xSize; ++xIndex) {
+ if ((xIndex % 2) == 0) {
+ if (xIndex != 0)
+ ++pDest;
+
+ // Write out vertical slice top to bottom
+ for (int yIndex = 0; yIndex < _thickness; ++yIndex, pDest += DEFAULT_WIDTH)
+ *pDest = nextByte(pSrc, pLookup);
+
+ ++pDest;
+ } else {
+ // Write out vertical slice bottom to top
+ for (int yIndex = 0; yIndex < _thickness; ++yIndex) {
+ pDest -= DEFAULT_WIDTH;
+ *pDest = nextByte(pSrc, pLookup);
+ }
+ }
+ }
+
+ if ((_xSize % 2) == 0) {
+ int blockSize = _thickness * DEFAULT_WIDTH;
+ pDest += blockSize;
+ blockSize -= DEFAULT_WIDTH;
+
+ if (pDestEnd < (pDest + blockSize)) {
+ do {
+ if (--_thickness == 0)
+ return;
+ } while ((pDest + (_thickness - 1) * DEFAULT_WIDTH) >= pDestEnd);
+ }
+ } else {
+ while ((pDest + (_thickness - 1) * DEFAULT_WIDTH) >= pDestEnd) {
+ if (--_thickness == 0)
+ return;
+ }
+ }
+
+ for (int xIndex = 0; xIndex < _xSize; ++xIndex, --pDest) {
+ if ((xIndex % 2) == 0) {
+ // Write out vertical slice top to bottom
+ for (int yIndex = 0; yIndex < _thickness; ++yIndex, pDest += DEFAULT_WIDTH)
+ *pDest = nextByte(pSrc, pLookup);
+ } else {
+ // Write out vertical slice top to bottom
+ for (int yIndex = 0; yIndex < _thickness; ++yIndex) {
+ pDest -= DEFAULT_WIDTH;
+ *pDest = nextByte(pSrc, pLookup);
+ }
+ }
+ }
+
+ if ((_xSize % 2) == 1) {
+ ++pDest;
+
+ if ((pDest + (_thickness - 1) * DEFAULT_WIDTH) < pDestEnd) {
+ continueFlag = true;
+ break;
+ }
+ } else {
+ pDest += _thickness * DEFAULT_WIDTH + 1;
+ continueFlag = true;
+ break;
+ }
+
+ ++pDest;
+ } while (((_thickness - 1) * DEFAULT_WIDTH + pDest) < pDestEnd);
+
+ if (continueFlag)
+ continue;
+
+ // Move to next line
+ if (--_thickness == 0)
+ break;
+ }
+}
+
+void GfxSurface::vertical(const byte *&pSrc, byte *&pDest, const byte *&pLookup) {
+ int drawIndex = 0;
+
+ for (;;) {
+ // Reduce thickness as necessary
+ while ((drawIndex + _thickness) > _xSize) {
+ if (--_thickness == 0)
+ return;
+ }
+
+ // Loop
+ for (int yCtr = 0; yCtr < _ySize; ++yCtr) {
+ if ((yCtr % 2) == 0) {
+ if (yCtr > 0)
+ pDest += DEFAULT_WIDTH;
+
+ drawIndex += _thickness;
+ for (int xCtr = 0; xCtr < _thickness; ++xCtr)
+ *pDest++ = nextByte(pSrc, pLookup);
+ } else {
+ pDest += DEFAULT_WIDTH;
+ drawIndex -= _thickness;
+ for (int xCtr = 0; xCtr < _thickness; ++xCtr)
+ *--pDest = nextByte(pSrc, pLookup);
+ }
+ }
+ if ((_ySize % 2) == 0) {
+ pDest += _thickness;
+ drawIndex += _thickness;
+ }
+
+ while (_xSize < (drawIndex + _thickness)) {
+ if (--_thickness == 0)
+ return;
+ }
+
+ // Loop
+ for (int yCtr = 0; yCtr < _ySize; ++yCtr) {
+ if ((yCtr % 2) == 0) {
+ if (yCtr > 0)
+ pDest -= DEFAULT_WIDTH;
+
+ drawIndex += _thickness;
+
+ for (int xCtr = 0; xCtr < _thickness; ++xCtr)
+ *pDest++ = nextByte(pSrc, pLookup);
+ } else {
+ pDest -= DEFAULT_WIDTH;
+ drawIndex -= _thickness;
+
+ for (int xCtr = 0; xCtr < _thickness; ++xCtr)
+ *--pDest = nextByte(pSrc, pLookup);
+ }
+ }
+ if ((_ySize % 2) == 0) {
+ pDest += _thickness;
+ drawIndex += _thickness;
+ }
+ }
+}
+
+void GfxSurface::decom11(const byte *&pSrc, byte *&pDest, const byte *&pLookup) {
+ int yPos = 0, drawIndex = 0;
+ _yInc = DEFAULT_WIDTH;
+ _xInc = -1;
+ --_xSize;
+ --_ySize;
+
+ int areaNum = 0;
+ while (areaNum != -1) {
+ switch (areaNum) {
+ case 0:
+ *pDest = nextByte(pSrc, pLookup);
+ areaNum = 1;
+ break;
+
+ case 1:
+ nextDecompPtr(pDest);
+
+ if (!drawIndex) {
+ negXInc();
+ negYInc();
+
+ if (yPos == _ySize) {
+ nextDecompPtr(pDest);
+ ++drawIndex;
+ } else {
+ ++yPos;
+ }
+
+ *++pDest = nextByte(pSrc, pLookup);
+ areaNum = 2;
+ } else if (yPos != _ySize) {
+ ++yPos;
+ --drawIndex;
+ areaNum = 0;
+ } else {
+ negXInc();
+ negYInc();
+ nextDecompPtr(pDest);
+ ++drawIndex;
+
+ *++pDest = nextByte(pSrc, pLookup);
+
+ if (drawIndex == _xSize) {
+ areaNum = -1;
+ } else {
+ areaNum = 2;
+ }
+ }
+ break;
+
+ case 2:
+ nextDecompPtr(pDest);
+
+ if (!yPos) {
+ negXInc();
+ negYInc();
+
+ if (drawIndex == _xSize) {
+ nextDecompPtr(pDest);
+ ++yPos;
+ } else {
+ ++drawIndex;
+ }
+
+ pDest += DEFAULT_WIDTH;
+ areaNum = 0;
+ } else if (drawIndex != _xSize) {
+ ++drawIndex;
+ --yPos;
+
+ *pDest = nextByte(pSrc, pLookup);
+ areaNum = 2;
+ } else {
+ pDest += DEFAULT_WIDTH;
+ ++yPos;
+ negXInc();
+ negYInc();
+ nextDecompPtr(pDest);
+
+ *pDest = nextByte(pSrc, pLookup);
+
+ if (yPos == _ySize)
+ areaNum = -1;
+ else
+ areaNum = 1;
+ }
+ break;
+ }
+ }
+}
+
+void GfxSurface::diag(const byte *&pSrc, byte *&pDest, const byte *&pLookup) {
+ int diagIndex = 0, drawIndex = 0;
+ --_xEnd;
+
+ while (!TFP(diagIndex)) {
+ for (;;) {
+ negXInc();
+ for (int idx = 0; idx <= _thickness; ++idx) {
+ *pDest = nextByte(pSrc, pLookup);
+ negXInc();
+ nextDecompPtr(pDest);
+ }
+
+ negYInc();
+ pDest += _yInc;
+
+ for (int idx = 0; idx <= _thickness; ++idx) {
+ *pDest = nextByte(pSrc, pLookup);
+ negXInc();
+ nextDecompPtr(pDest);
+ }
+
+ negXInc();
+ negYInc();
+ nextDecompPtr(pDest);
+
+ ++drawIndex;
+ if (_xEnd < (drawIndex + 1)) {
+ TF1(pDest, diagIndex);
+ break;
+ }
+
+ pDest += _xInc;
+ ++drawIndex;
+ if (_xEnd < (drawIndex + 1)) {
+ TF2(pSrc, pDest, pLookup, diagIndex);
+ break;
+ }
+ }
+
+ if (TFP(diagIndex))
+ break;
+
+ for (;;) {
+ for (int idx = 0; idx <= _thickness; ++idx) {
+ *pDest = nextByte(pSrc, pLookup);
+ negXInc();
+ nextDecompPtr(pDest);
+ }
+
+ negYInc();
+ pDest += _yInc;
+
+ for (int idx = 0; idx <= _thickness; ++idx) {
+ *pDest = nextByte(pSrc, pLookup);
+ negXInc();
+ nextDecompPtr(pDest);
+ }
+
+ negXInc();
+ negYInc();
+ nextDecompPtr(pDest);
+
+ if (--drawIndex == 0) {
+ TF1(pDest, diagIndex);
+ negXInc();
+ break;
+ } else {
+ pDest += _xInc;
+
+ if (--drawIndex == 0) {
+ TF2(pSrc, pDest, pLookup, diagIndex);
+ negXInc();
+ break;
+ }
+ }
+
+ negXInc();
+ }
+ }
+}
+
+/**
+ * Decompression Function - Move pDest ptr to next value to uncompress
+ * @remarks Originally called 'increments'
+ */
+void GfxSurface::nextDecompPtr(byte *&pDest) {
+ pDest += _xInc + _yInc;
+}
+
+/**
+ * Decompression Function - set xInc to its opposite value
+ * @remarks Originally called 'NIH'
+ */
+void GfxSurface::negXInc() {
+ _xInc = -_xInc;
+}
+
+/**
+ * Decompression Function - set yInc to its opposite value
+ * @remarks Originally called 'NIV'
+ */
+void GfxSurface::negYInc() {
+ _yInc = -_yInc;
+}
+
+bool GfxSurface::TFP(int v) {
+ int diff = _yEnd - v;
+ if (!diff)
+ // Time to finish loop in outer method
+ return true;
+
+ if (diff < (_thickness + 1))
+ _thickness = diff - 1;
+
+ return false;
+}
+
+void GfxSurface::TF1(byte *&pDest, int &v) {
+ v += _thickness + 1;
+ pDest += (_thickness + 1) * _yInc;
+}
+
+void GfxSurface::TF2(const byte *&pSrc, byte *&pDest, const byte *&pLookup, int &v) {
+ v += _thickness + 1;
+
+ for (int idx = 0; idx <= _thickness; ++idx) {
+ *pDest = nextByte(pSrc, pLookup);
+ pDest += _yInc;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+GfxSurface::~GfxSurface() {
+ free();
+}
+
+/*-------------------------------------------------------------------------*
+ * Screen surface
+ *-------------------------------------------------------------------------*/
+
+/**
+ * Called to populate the font data from the passed file
+ */
+void ScreenSurface::readFontData(Common::File &f, int dataSize) {
+ assert(dataSize == (FONT_NUM_CHARS * FONT_HEIGHT));
+ f.read(_fontData, FONT_NUM_CHARS * FONT_HEIGHT);
+}
+
+/**
+ * Returns a graphics surface representing a subset of the screen. The affected area
+ * is also marked as dirty
+ */
+Graphics::Surface ScreenSurface::lockArea(const Common::Rect &bounds) {
+ _dirtyRects.push_back(bounds);
+
+ Graphics::Surface s;
+ s.format = format;
+ s.pixels = getBasePtr(bounds.left, bounds.top);
+ s.pitch = pitch;
+ s.w = bounds.width();
+ s.h = bounds.height();
+
+ return s;
+}
+
+/**
+ * Updates the affected areas of the surface to the underlying physical screen
+ */
+void ScreenSurface::updateScreen() {
+ // Iterate through copying dirty areas to the screen
+ for (Common::List<Common::Rect>::iterator i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
+ Common::Rect r = *i;
+ g_system->copyRectToScreen((const byte *)getBasePtr(r.left, r.top), pitch,
+ r.left, r.top, r.width(), r.height());
+ }
+ _dirtyRects.clear();
+
+ // Update the screen
+ g_system->updateScreen();
+}
+
+/**
+ * Draws a decoded picture on the screen
+ * @remarks - Because the ScummVM surface is using a double height 640x400 surface to
+ * simulate the original 640x400 surface, all Y values have to be doubled.
+ * - Image resources are stored at 320x200, so when drawn onto the screen a single pixel
+ * from the source image is drawn using the two pixels at the given index in the palette map
+ * - Because the original game supported 320 width resolutions, the X coordinate
+ * also needs to be doubled for EGA mode
+ */
+void ScreenSurface::drawPicture(GfxSurface &surface, int x, int y) {
+ // Adjust the draw position by the draw offset
+ x += surface._offset.x;
+ y += surface._offset.y;
+
+ // Lock the affected area of the surface to write to
+ Graphics::Surface destSurface = lockArea(Common::Rect(x * 2, y * 2,
+ (x + surface.w) * 2, (y + surface.h) * 2));
+
+ // Get a lookup for the palette mapping
+ const byte *paletteMap = &_vm->_curPict[2];
+
+ // Loop through writing
+ for (int yp = 0; yp < surface.h; ++yp) {
+ if (((y + yp) < 0) || ((y + yp) >= 200))
+ continue;
+
+ const byte *pSrc = (const byte *)surface.getBasePtr(0, yp);
+ byte *pDest = (byte *)destSurface.getBasePtr(0, yp * 2);
+
+ for (int xp = 0; xp < surface.w; ++xp, ++pSrc) {
+ if (*pSrc == surface._transparency) {
+ // Transparent point, so skip pixels
+ pDest += 2;
+ } else {
+ // Draw the pixel using the specified index in the palette map
+ *pDest = paletteMap[*pSrc * 2];
+ *(pDest + SCREEN_WIDTH) = paletteMap[*pSrc * 2];
+ ++pDest;
+
+ // Use the secondary mapping value to draw the secondary column pixel
+ *pDest = paletteMap[*pSrc * 2 + 1];
+ *(pDest + SCREEN_WIDTH) = paletteMap[*pSrc * 2 + 1];
+ ++pDest;
+ }
+ }
+ }
+}
+
+/**
+ * Copys a given surface to the given position
+ */
+void ScreenSurface::copyFrom(Graphics::Surface &src, int x, int y) {
+ lockArea(Common::Rect(x, y, x + src.w, y + src.h));
+
+ // Loop through writing
+ for (int yp = 0; yp < src.h; ++yp) {
+ if (((y + yp) < 0) || ((y + yp) >= SCREEN_HEIGHT))
+ continue;
+
+ const byte *pSrc = (const byte *)src.getBasePtr(0, yp);
+ byte *pDest = (byte *)getBasePtr(0, yp);
+ Common::copy(pSrc, pSrc + src.w, pDest);
+ }
+}
+
+/**
+ * Draws a character at the specified co-ordinates
+ * @remarks Because the ScummVM surface is using a double height 640x400 surface to
+ * simulate the original 640x400 surface, all Y values have to be doubled
+ */
+void ScreenSurface::writeCharacter(const Common::Point &pt, unsigned char ch, int palIndex) {
+ Graphics::Surface destSurface = lockArea(Common::Rect(pt.x, pt.y * 2,
+ pt.x + FONT_WIDTH, (pt.y + FONT_HEIGHT) * 2));
+
+ // Get the start of the character to use
+ assert((ch >= ' ') && (ch <= (unsigned char)(32 + FONT_NUM_CHARS)));
+ const byte *charData = &_fontData[((int)ch - 32) * FONT_HEIGHT];
+
+ // Loop through decoding each character's data
+ for (int yp = 0; yp < FONT_HEIGHT; ++yp) {
+ byte *lineP = (byte *)destSurface.getBasePtr(0, yp * 2);
+ byte byteVal = *charData++;
+
+ for (int xp = 0; xp < FONT_WIDTH; ++xp, ++lineP, byteVal <<= 1) {
+ if (byteVal & 0x80) {
+ *lineP = palIndex;
+ *(lineP + SCREEN_WIDTH) = palIndex;
+ }
+ }
+ }
+}
+
+/**
+ * Draws a box at the specified position and size
+ * @remarks Because the ScummVM surface is using a double height 640x400 surface to
+ * simulate the original 640x400 surface, all Y values have to be doubled
+ */
+void ScreenSurface::drawBox(int x, int y, int dx, int dy, int col) {
+ if (_vm->_resolutionScaler == 1) {
+ x = (uint)x >> 1;
+ dx = (uint)dx >> 1;
+ }
+
+ Graphics::Surface destSurface = lockArea(Common::Rect(x, y * 2, x + dx, (y + dy) * 2));
+
+ destSurface.hLine(0, 0, dx, col);
+ destSurface.hLine(0, 1, dx, col);
+ destSurface.hLine(0, destSurface.h - 1, dx, col);
+ destSurface.hLine(0, destSurface.h - 2, dx, col);
+ destSurface.vLine(0, 2, destSurface.h - 3, col);
+ destSurface.vLine(1, 2, destSurface.h - 3, col);
+ destSurface.vLine(dx - 1, 2, destSurface.h - 3, col);
+ destSurface.vLine(dx - 2, 2, destSurface.h - 3, col);
+}
+
+/**
+ * Fills an area with the specified color
+ * @remarks Because the ScummVM surface is using a double height 640x400 surface to
+ * simulate the original 640x400 surface, all Y values have to be doubled
+ */
+void ScreenSurface::fillRect(int color, const Common::Rect &bounds) {
+ Graphics::Surface destSurface = lockArea(Common::Rect(bounds.left, bounds.top * 2,
+ bounds.right, bounds.bottom * 2));
+
+ // Fill the area
+ destSurface.fillRect(Common::Rect(0, 0, destSurface.w, destSurface.h), color);
+}
+
+/**
+ * Clears the screen
+ */
+void ScreenSurface::clearScreen() {
+ Graphics::Surface destSurface = lockArea(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+ destSurface.fillRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+}
+
+/**
+ * Sets a single pixel at the specified co-ordinates
+ * @remarks Because the ScummVM surface is using a double height 640x400 surface to
+ * simulate the original 640x400 surface, all Y values have to be doubled
+ */
+void ScreenSurface::setPixel(const Common::Point &pt, int palIndex) {
+ assert((pt.x >= 0) && (pt.y >= 0) && (pt.x <= SCREEN_WIDTH) && (pt.y <= SCREEN_ORIG_HEIGHT));
+ Graphics::Surface destSurface = lockArea(Common::Rect(pt.x, pt.y * 2, pt.x + 1, (pt.y + 1) * 2));
+
+ byte *destP = (byte *)destSurface.pixels;
+ *destP = palIndex;
+ *(destP + SCREEN_WIDTH) = palIndex;
+}
+
+/**
+ * Write out a string
+ * @remarks Originally called 'writeg'
+ */
+void ScreenSurface::drawString(const Common::String &l, int command) {
+ if (l == "")
+ return;
+
+ _vm->_mouse.hideMouse();
+ Common::Point pt = _textPos;
+
+ int charWidth;
+ if (_vm->_resolutionScaler == 2)
+ charWidth = 6;
+ else
+ charWidth = 10;
+
+ int x = pt.x + charWidth * l.size();
+ int color = 0;
+
+ switch (command) {
+ case 0:
+ case 2:
+ color = 15;
+ _vm->_screenSurface.fillRect(0, Common::Rect(pt.x, pt.y, x, pt.y + 7));
+ break;
+ case 1:
+ case 3:
+ _vm->_screenSurface.fillRect(15, Common::Rect(pt.x, pt.y, x, pt.y + 7));
+ break;
+ case 5:
+ color = 15;
+ break;
+ default:
+ // Default: Color set to zero (already done)
+ break;
+ }
+
+ pt.x += 1;
+ pt.y += 1;
+ for (x = 1; (x <= (int)l.size()) && (l[x - 1] != 0); ++x) {
+ _vm->_screenSurface.writeCharacter(Common::Point(pt.x, pt.y), l[x - 1], color);
+ pt.x += charWidth;
+ }
+ _vm->_mouse.showMouse();
+}
+
+/**
+ * Gets the width in pixels of the specified string
+ */
+int ScreenSurface::getStringWidth(const Common::String &s) {
+ int charWidth = (_vm->_resolutionScaler == 2) ? 6 : 10;
+
+ return s.size() * charWidth;
+}
+
+void ScreenSurface::drawLine(int x, int y, int xx, int yy, int coul) {
+ int step, i;
+ float a, b;
+ float xr, yr, xro, yro;
+
+ xr = x;
+ yr = y;
+ xro = xx;
+ yro = yy;
+
+ if (abs(y - yy) > abs(x - xx)) {
+ a = (float)((x - xx)) / (y - yy);
+ b = (yr * xro - yro * xr) / (y - yy);
+ i = y;
+ if (y > yy)
+ step = -1;
+ else
+ step = 1;
+ do {
+ _vm->_screenSurface.setPixel(Common::Point(abs((int)(a * i + b)), i), coul);
+ i += step;
+ } while (i != yy);
+ } else {
+ a = (float)((y - yy)) / (x - xx);
+ b = ((yro * xr) - (yr * xro)) / (x - xx);
+ i = x;
+ if (x > xx)
+ step = -1;
+ else
+ step = 1;
+ do {
+ _vm->_screenSurface.setPixel(Common::Point(i, abs((int)(a * i + b))), coul);
+ i = i + step;
+ } while (i != xx);
+ }
+}
+
+/**
+ * Draw plain rectangle
+ * @remarks Originally called 'paint_rect'
+ */
+void ScreenSurface::drawRectangle(int x, int y, int dx, int dy) {
+ int co;
+
+ if (_vm->_currGraphicalDevice == MODE_CGA)
+ co = 3;
+ else
+ co = 11;
+ _vm->_screenSurface.fillRect(co, Common::Rect(x, y, x + dx, y + dy));
+}
+
+void ScreenSurface::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+
+
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/graphics.h b/engines/mortevielle/graphics.h
new file mode 100644
index 0000000000..e31f5da29a
--- /dev/null
+++ b/engines/mortevielle/graphics.h
@@ -0,0 +1,117 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#ifndef MORTEVIELLE_GRAPHICS_H
+#define MORTEVIELLE_GRAPHICS_H
+
+#include "common/file.h"
+#include "common/list.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace Mortevielle {
+class MortevielleEngine;
+
+class PaletteManager {
+private:
+ void setPalette(const int *palette, uint idx, uint size);
+
+public:
+ void setDefaultPalette();
+};
+
+#define FONT_WIDTH 8
+#define FONT_HEIGHT 6
+#define FONT_NUM_CHARS 121
+
+class GfxSurface : public Graphics::Surface {
+private:
+ int _xp, _yp;
+ int _xSize, _ySize;
+ int _lookupIndex, _lookupValue;
+ bool _nibbleFlag;
+ int _thickness;
+ int _yInc, _yEnd, _xInc, _xEnd;
+
+ byte nextNibble(const byte *&pSrc);
+ byte nextByte(const byte *&pSrc, const byte *&pLookup);
+
+ void majTtxTty();
+ int desanalyse(const byte *&pSrc);
+ void horizontal(const byte *&pSrc, byte *&pDest, const byte *&pLookup);
+ void vertical(const byte *&pSrc, byte *&pDest, const byte *&pLookup);
+ void decom11(const byte *&pSrc, byte *&pDest, const byte *&pLookup);
+ void diag(const byte *&pSrc, byte *&pDest, const byte *&pLookup);
+ void nextDecompPtr(byte *&pDest);
+ void negXInc();
+ void negYInc();
+ bool TFP(int v);
+ void TF1(byte *&pDest, int &v);
+ void TF2(const byte *&pSrc, byte *&pDest, const byte *&pLookup, int &v);
+public:
+ // Specifies offset when drawing the image
+ Common::Point _offset;
+ // Transparency palette index
+ int _transparency;
+
+ ~GfxSurface();
+
+ void decode(const byte *pSrc);
+};
+
+class ScreenSurface: public Graphics::Surface {
+private:
+ MortevielleEngine *_vm;
+
+ Common::List<Common::Rect> _dirtyRects;
+ byte _fontData[FONT_NUM_CHARS * FONT_HEIGHT];
+
+public:
+ Common::Point _textPos; // Original called xwhere/ywhere
+ void readFontData(Common::File &f, int dataSize);
+ Graphics::Surface lockArea(const Common::Rect &bounds);
+ void updateScreen();
+ void drawPicture(GfxSurface &surface, int x, int y);
+ void copyFrom(Graphics::Surface &src, int x, int y);
+ void writeCharacter(const Common::Point &pt, unsigned char ch, int palIndex);
+ void drawBox(int x, int y, int dx, int dy, int col);
+ void fillRect(int color, const Common::Rect &bounds);
+ void clearScreen();
+ void putxy(int x, int y) { _textPos = Common::Point(x, y); }
+ void drawString(const Common::String &l, int command);
+ int getStringWidth(const Common::String &s);
+ void drawLine(int x, int y, int xx, int yy, int coul);
+ void drawRectangle(int x, int y, int dx, int dy);
+ void setParent(MortevielleEngine *vm);
+
+ // TODO: Refactor code to remove this method, for increased performance
+ void setPixel(const Common::Point &pt, int palIndex);
+};
+
+} // End of namespace Mortevielle
+
+#endif
diff --git a/engines/mortevielle/menu.cpp b/engines/mortevielle/menu.cpp
new file mode 100644
index 0000000000..f86fd208c1
--- /dev/null
+++ b/engines/mortevielle/menu.cpp
@@ -0,0 +1,599 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file _distributed with this source _distribution.
+ *
+ * This program is free software; you can re_distribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is _distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+
+#include "mortevielle/menu.h"
+#include "mortevielle/mouse.h"
+#include "mortevielle/outtext.h"
+
+#include "common/scummsys.h"
+#include "common/str.h"
+#include "common/textconsole.h"
+
+namespace Mortevielle {
+
+const byte menuConstants[8][4] = {
+ { 7, 37, 23, 8},
+ {19, 33, 23, 7},
+ {31, 89, 10, 21},
+ {43, 25, 11, 5},
+ {55, 37, 5, 8},
+ {64, 13, 11, 2},
+ {62, 42, 13, 9},
+ {62, 46, 13, 10}
+};
+
+/**
+ * Setup a menu's contents
+ * @remarks Originally called 'menut'
+ */
+void Menu::setText(int menuId, int actionId, Common::String name) {
+ Common::String s = name;
+
+ while (s.size() < 22)
+ s += ' ';
+
+ switch (menuId) {
+ case MENU_INVENTORY:
+ if (actionId != 7) {
+ _inventoryStringArray[actionId] = s;
+ _inventoryStringArray[actionId].insertChar(' ', 0);
+ }
+ break;
+ case MENU_MOVE:
+ _moveStringArray[actionId] = s;
+ break;
+ case MENU_ACTION:
+ _actionStringArray[actionId] = s;
+ break;
+ case MENU_SELF:
+ _selfStringArray[actionId] = s;
+ break;
+ case MENU_DISCUSS:
+ _discussStringArray[actionId] = s;
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Init destination menu
+ * @remarks Originally called 'tmlieu'
+ */
+void Menu::setDestinationText(int roomId) {
+ Common::String nomp;
+
+ if (roomId == 26)
+ roomId = LANDING;
+
+ int destinationId = 0;
+ for (; (destinationId < 7) && (_vm->_destinationArray[destinationId][roomId]); ++destinationId) {
+ nomp = _vm->getString(_vm->_destinationArray[destinationId][roomId] + kMenuPlaceStringIndex);
+ while (nomp.size() < 20)
+ nomp += ' ';
+ setText(_moveMenu[destinationId + 1]._menuId, _moveMenu[destinationId + 1]._actionId, nomp);
+ }
+ nomp = "* ";
+ for (int i = 7; i >= destinationId + 1; --i)
+ setText(_moveMenu[i]._menuId, _moveMenu[i]._actionId, nomp);
+}
+
+/**
+ * _disable a menu item
+ * @param menuId Menu number
+ * @param actionId Item index
+ */
+void Menu::disableMenuItem(int menuId, int actionId) {
+ switch (menuId) {
+ case MENU_INVENTORY:
+ if (actionId > 6) {
+ _inventoryStringArray[actionId].setChar('<', 0);
+ _inventoryStringArray[actionId].setChar('>', 21);
+ } else
+ _inventoryStringArray[actionId].setChar('*', 0);
+ break;
+ case MENU_MOVE:
+ _moveStringArray[actionId].setChar('*', 0);
+ break;
+ case MENU_ACTION:
+ _actionStringArray[actionId].setChar('*', 0);
+ break;
+ case MENU_SELF:
+ _selfStringArray[actionId].setChar('*', 0);
+ break;
+ case MENU_DISCUSS:
+ _discussStringArray[actionId].setChar('*', 0);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Enable a menu item
+ * @param menuId Menu number
+ * @param actionId Item index
+ * @remarks Originally called menu_enable
+ */
+void Menu::enableMenuItem(int menuId, int actionId) {
+ switch (menuId) {
+ case MENU_INVENTORY:
+ _inventoryStringArray[actionId].setChar(' ', 0);
+ _inventoryStringArray[actionId].setChar(' ', 21);
+ break;
+ case MENU_MOVE:
+ _moveStringArray[actionId].setChar(' ', 0);
+ break;
+ case MENU_ACTION:
+ _actionStringArray[actionId].setChar(' ', 0);
+ break;
+ case MENU_SELF:
+ _selfStringArray[actionId].setChar(' ', 0);
+ // The original sets two times the same value. Skipped
+ // _selfStringArray[l].setChar(' ', 0);
+ break;
+ case MENU_DISCUSS:
+ _discussStringArray[actionId].setChar(' ', 0);
+ break;
+ default:
+ break;
+ }
+}
+
+void Menu::displayMenu() {
+ int ind_tabl, k, col;
+
+ int pt, x, y, color, msk, num_letr;
+
+ _vm->_mouse.hideMouse();
+
+ _vm->_screenSurface.fillRect(7, Common::Rect(0, 0, 639, 10));
+ col = 28 * _vm->_resolutionScaler;
+ if (_vm->_currGraphicalDevice == MODE_CGA)
+ color = 1;
+ else
+ color = 9;
+ num_letr = 0;
+ do { // One character after the other
+ ++num_letr;
+ ind_tabl = 0;
+ y = 1;
+ do { // One column after the other
+ k = 0;
+ x = col;
+ do { // One line after the other
+ msk = 0x80;
+ for (pt = 0; pt <= 7; ++pt) {
+ if ((_charArr[num_letr - 1][ind_tabl] & msk) != 0) {
+ _vm->_screenSurface.setPixel(Common::Point(x + 1, y + 1), 0);
+ _vm->_screenSurface.setPixel(Common::Point(x, y + 1), 0);
+ _vm->_screenSurface.setPixel(Common::Point(x, y), color);
+ }
+ msk = (uint)msk >> 1;
+ ++x;
+ }
+ ++ind_tabl;
+ ++k;
+ } while (k != 3);
+ ++y;
+ } while (y != 9);
+ col += 48 * _vm->_resolutionScaler;
+ } while (num_letr != 6);
+ _vm->_mouse.showMouse();
+}
+
+/**
+ * Show the menu
+ */
+void Menu::drawMenu() {
+ displayMenu();
+ _menuActive = true;
+ _msg4 = OPCODE_NONE;
+ _msg3 = OPCODE_NONE;
+ _menuSelected = false;
+ _vm->setMouseClick(false);
+ _multiTitle = false;
+}
+
+/**
+ * Menu function - Invert a menu entry
+ * @remarks Originally called 'invers'
+ */
+void Menu::invert(int indx) {
+ if (_msg4 == OPCODE_NONE)
+ return;
+
+ int menuIndex = _msg4 & 0xFF;
+
+ _vm->_screenSurface.putxy(menuConstants[_msg3 - 1][0] << 3, (menuIndex + 1) << 3);
+
+ Common::String str;
+ switch (_msg3) {
+ case MENU_INVENTORY:
+ str = _inventoryStringArray[menuIndex];
+ break;
+ case MENU_MOVE:
+ str = _moveStringArray[menuIndex];
+ break;
+ case MENU_ACTION:
+ str = _actionStringArray[menuIndex];
+ break;
+ case MENU_SELF:
+ str = _selfStringArray[menuIndex];
+ break;
+ case MENU_DISCUSS:
+ str = _discussStringArray[menuIndex];
+ break;
+ case MENU_FILE:
+ str = _vm->getEngineString(S_SAVE_LOAD + menuIndex);
+ break;
+ case MENU_SAVE:
+ str = _vm->getEngineString(S_SAVE_LOAD + 1);
+ str += ' ';
+ str += (char)(48 + menuIndex);
+ break;
+ case MENU_LOAD:
+ if (menuIndex == 1) {
+ str = _vm->getEngineString(S_RESTART);
+ } else {
+ str = _vm->getEngineString(S_SAVE_LOAD + 2);
+ str += ' ';
+ str += (char)(47 + menuIndex);
+ }
+ break;
+ default:
+ break;
+ }
+ if ((str[0] != '*') && (str[0] != '<'))
+ _vm->_screenSurface.drawString(str, indx);
+ else
+ _msg4 = OPCODE_NONE;
+}
+
+void Menu::util(Common::Point pos) {
+
+ int ymx = (menuConstants[_msg3 - 1][3] << 3) + 16;
+ int dxcar = menuConstants[_msg3 - 1][2];
+ int xmn = (menuConstants[_msg3 - 1][0] << 2) * _vm->_resolutionScaler;
+
+ int ix;
+ if (_vm->_resolutionScaler == 1)
+ ix = 5;
+ else
+ ix = 3;
+ int xmx = dxcar * ix * _vm->_resolutionScaler + xmn + 2;
+ if ((pos.x > xmn) && (pos.x < xmx) && (pos.y < ymx) && (pos.y > 15)) {
+ ix = (((uint)pos.y >> 3) - 1) + (_msg3 << 8);
+ if (ix != _msg4) {
+ invert(1);
+ _msg4 = ix;
+ invert(0);
+ }
+ } else if (_msg4 != OPCODE_NONE) {
+ invert(1);
+ _msg4 = OPCODE_NONE;
+ }
+}
+
+/**
+ * Draw a menu
+ */
+void Menu::menuDown(int ii) {
+ int cx, xcc, xco;
+ int lignNumb;
+
+ // Make a copy of the current screen surface for later restore
+ _vm->_backgroundSurface.copyFrom(_vm->_screenSurface);
+
+ // Draw the menu
+ xco = menuConstants[ii - 1][0];
+ lignNumb = menuConstants[ii - 1][3];
+ _vm->_mouse.hideMouse();
+ xco = xco << 3;
+ if (_vm->_resolutionScaler == 1)
+ cx = 10;
+ else
+ cx = 6;
+ xcc = xco + (menuConstants[ii - 1][2] * cx) + 6;
+ if ((ii == 4) && (_vm->getLanguage() == Common::EN_ANY))
+ // Extra width needed for Self menu in English version
+ xcc = 435;
+
+ _vm->_screenSurface.fillRect(15, Common::Rect(xco, 12, xcc, 10 + (menuConstants[ii - 1][1] << 1)));
+ _vm->_screenSurface.fillRect(0, Common::Rect(xcc, 12, xcc + 4, 10 + (menuConstants[ii - 1][1] << 1)));
+ _vm->_screenSurface.fillRect(0, Common::Rect(xco, 8 + (menuConstants[ii - 1][1] << 1), xcc + 4, 12 + (menuConstants[ii - 1][1] << 1)));
+ _vm->_screenSurface.putxy(xco, 16);
+ cx = 0;
+ do {
+ ++cx;
+ switch (ii) {
+ case 1:
+ if (_inventoryStringArray[cx][0] != '*')
+ _vm->_screenSurface.drawString(_inventoryStringArray[cx], 4);
+ break;
+ case 2:
+ if (_moveStringArray[cx][0] != '*')
+ _vm->_screenSurface.drawString(_moveStringArray[cx], 4);
+ break;
+ case 3:
+ if (_actionStringArray[cx][0] != '*')
+ _vm->_screenSurface.drawString(_actionStringArray[cx], 4);
+ break;
+ case 4:
+ if (_selfStringArray[cx][0] != '*')
+ _vm->_screenSurface.drawString(_selfStringArray[cx], 4);
+ break;
+ case 5:
+ if (_discussStringArray[cx][0] != '*')
+ _vm->_screenSurface.drawString(_discussStringArray[cx], 4);
+ break;
+ case 6:
+ _vm->_screenSurface.drawString(_vm->getEngineString(S_SAVE_LOAD + cx), 4);
+ break;
+ case 7: {
+ Common::String s = _vm->getEngineString(S_SAVE_LOAD + 1);
+ s += ' ';
+ s += (char)(48 + cx);
+ _vm->_screenSurface.drawString(s, 4);
+ }
+ break;
+ case 8:
+ if (cx == 1)
+ _vm->_screenSurface.drawString(_vm->getEngineString(S_RESTART), 4);
+ else {
+ Common::String s = _vm->getEngineString(S_SAVE_LOAD + 2);
+ s += ' ';
+ s += (char)(47 + cx);
+ _vm->_screenSurface.drawString(s, 4);
+ }
+ break;
+ default:
+ break;
+ }
+ _vm->_screenSurface.putxy(xco, _vm->_screenSurface._textPos.y + 8);
+ } while (cx != lignNumb);
+ _multiTitle = true;
+ _vm->_mouse.showMouse();
+}
+
+/**
+ * Menu is being removed, so restore the previous background area.
+ */
+void Menu::menuUp(int msgId) {
+ if (_multiTitle) {
+ /* Restore the background area */
+ assert(_vm->_screenSurface.pitch == _vm->_backgroundSurface.pitch);
+
+ // Get a pointer to the source and destination of the area to restore
+ const byte *pSrc = (const byte *)_vm->_backgroundSurface.getBasePtr(0, 10);
+ Graphics::Surface destArea = _vm->_screenSurface.lockArea(Common::Rect(0, 10, SCREEN_WIDTH, SCREEN_HEIGHT));
+ byte *pDest = (byte *)destArea.getBasePtr(0, 0);
+
+ // Copy the data
+ Common::copy(pSrc, pSrc + (400 - 10) * SCREEN_WIDTH, pDest);
+
+ _multiTitle = false;
+ }
+}
+
+/**
+ * Erase the menu
+ */
+void Menu::eraseMenu() {
+ _menuActive = false;
+ _vm->setMouseClick(false);
+ menuUp(_msg3);
+}
+
+/**
+ * Handle updates to the menu
+ * @remarks Originally called 'mdn'
+ */
+void Menu::updateMenu() {
+ if (!_menuActive)
+ return;
+
+ Common::Point curPos = _vm->_mouse._pos;
+ if (!_vm->getMouseClick()) {
+ if (curPos == _vm->_prevPos)
+ return;
+ else
+ _vm->_prevPos = curPos;
+
+ bool tes = (curPos.y < 11)
+ && ((curPos.x >= (28 * _vm->_resolutionScaler) && curPos.x <= (28 * _vm->_resolutionScaler + 24))
+ || (curPos.x >= (76 * _vm->_resolutionScaler) && curPos.x <= (76 * _vm->_resolutionScaler + 24))
+ || ((curPos.x > 124 * _vm->_resolutionScaler) && (curPos.x < 124 * _vm->_resolutionScaler + 24))
+ || ((curPos.x > 172 * _vm->_resolutionScaler) && (curPos.x < 172 * _vm->_resolutionScaler + 24))
+ || ((curPos.x > 220 * _vm->_resolutionScaler) && (curPos.x < 220 * _vm->_resolutionScaler + 24))
+ || ((curPos.x > 268 * _vm->_resolutionScaler) && (curPos.x < 268 * _vm->_resolutionScaler + 24)));
+ if (tes) {
+ int ix;
+
+ if (curPos.x < 76 * _vm->_resolutionScaler)
+ ix = MENU_INVENTORY;
+ else if (curPos.x < 124 * _vm->_resolutionScaler)
+ ix = MENU_MOVE;
+ else if (curPos.x < 172 * _vm->_resolutionScaler)
+ ix = MENU_ACTION;
+ else if (curPos.x < 220 * _vm->_resolutionScaler)
+ ix = MENU_SELF;
+ else if (curPos.x < 268 * _vm->_resolutionScaler)
+ ix = MENU_DISCUSS;
+ else
+ ix = MENU_FILE;
+
+ if ((ix != _msg3) || (!_multiTitle))
+ if (!((ix == MENU_FILE) && ((_msg3 == MENU_SAVE) || (_msg3 == MENU_LOAD)))) {
+ menuUp(_msg3);
+ menuDown(ix);
+ _msg3 = ix;
+ _msg4 = OPCODE_NONE;
+ }
+ } else { // Not in the MenuTitle line
+ if ((curPos.y > 11) && (_multiTitle))
+ util(curPos);
+ }
+ } else { // There was a click
+ if ((_msg3 == MENU_FILE) && (_msg4 != OPCODE_NONE)) {
+ // Another menu to be _displayed
+ _vm->setMouseClick(false);
+ menuUp(_msg3);
+ if ((_msg4 & 0xFF) == 1)
+ _msg3 = MENU_SAVE;
+ else
+ _msg3 = MENU_LOAD;
+ menuDown(_msg3);
+
+ _vm->setMouseClick(false);
+ } else {
+ // A menu was clicked on
+ _menuSelected = (_multiTitle) && (_msg4 != OPCODE_NONE);
+ menuUp(_msg3);
+ _vm->_currAction = _msg4;
+ _vm->_currMenu = _msg3;
+ _msg3 = OPCODE_NONE;
+ _msg4 = OPCODE_NONE;
+
+ _vm->setMouseClick(false);
+ }
+ }
+}
+
+void Menu::initMenu(MortevielleEngine *vm) {
+ _vm = vm;
+
+ int i;
+ Common::File f;
+
+ if (!f.open("menufr.mor"))
+ if (!f.open("menual.mor"))
+ if (!f.open("menu.mor"))
+ error("Missing file - menufr.mor or menual.mor or menu.mor");
+
+ f.read(_charArr, 7 * 24);
+ f.close();
+
+ // Skipped: dialog asking to swap floppy
+
+ for (i = 1; i <= 8; ++i)
+ _inventoryStringArray[i] = "* ";
+ _inventoryStringArray[7] = "< -*-*-*-*-*-*-*-*-*- ";
+ for (i = 1; i <= 7; ++i)
+ _moveStringArray[i] = "* ";
+ i = 1;
+ do {
+ _actionStringArray[i] = _vm->getString(i + kMenuActionStringIndex);
+
+ while (_actionStringArray[i].size() < 10)
+ _actionStringArray[i] += ' ';
+
+ if (i < 9) {
+ if (i < 6) {
+ _selfStringArray[i] = _vm->getString(i + kMenuSelfStringIndex);
+ while (_selfStringArray[i].size() < 10)
+ _selfStringArray[i] += ' ';
+ }
+ _discussStringArray[i] = _vm->getString(i + kMenuSayStringIndex) + ' ';
+ }
+ ++i;
+ } while (i != 22);
+ for (i = 1; i <= 8; ++i) {
+ _discussMenu[i]._menuId = MENU_DISCUSS;
+ _discussMenu[i]._actionId = i;
+ if (i < 8) {
+ _moveMenu[i]._menuId = MENU_MOVE;
+ _moveMenu[i]._actionId = i;
+ }
+ _inventoryMenu[i]._menuId = MENU_INVENTORY;
+ _inventoryMenu[i]._actionId = i;
+ if (i > 6)
+ disableMenuItem(_inventoryMenu[i]._menuId, _inventoryMenu[i]._actionId);
+ }
+ _msg3 = OPCODE_NONE;
+ _msg4 = OPCODE_NONE;
+ _vm->_currMenu = OPCODE_NONE;
+ _vm->_currAction = OPCODE_NONE;
+ _vm->setMouseClick(false);
+}
+
+/**
+ * Engine function - Switch action menu to "Search" mode
+ * @remarks Originally called 'mfoudi'
+ */
+void Menu::setSearchMenu() {
+ for (int i = 1; i <= 7; ++i)
+ disableMenuItem(MENU_MOVE, _moveMenu[i]._actionId);
+
+ for (int i = 1; i <= 11; ++i)
+ disableMenuItem(_actionMenu[i]._menuId, _actionMenu[i]._actionId);
+
+ setText(OPCODE_SOUND >> 8, OPCODE_SOUND & 0xFF, _vm->getEngineString(S_SUITE));
+ setText(OPCODE_LIFT >> 8, OPCODE_LIFT & 0xFF, _vm->getEngineString(S_STOP));
+}
+
+/**
+ * Engine function - Switch action menu from "Search" mode back to normal mode
+ * @remarks Originally called 'mfouen'
+ */
+void Menu::unsetSearchMenu() {
+ setDestinationText(_vm->_coreVar._currPlace);
+ for (int i = 1; i <= 11; ++i)
+ enableMenuItem(_actionMenu[i]._menuId, _actionMenu[i]._actionId);
+
+ setText(OPCODE_SOUND >> 8, OPCODE_SOUND & 0xFF, _vm->getEngineString(S_PROBE));
+ setText(OPCODE_LIFT >> 8, OPCODE_LIFT & 0xFF, _vm->getEngineString(S_RAISE));
+}
+
+/**
+ * Set Inventory menu texts
+ * @remarks Originally called 'modinv'
+ */
+void Menu::setInventoryText() {
+ Common::String nomp;
+
+ int cy = 0;
+ for (int i = 1; i <= 6; ++i) {
+ if (_vm->_coreVar._inventory[i] != 0) {
+ ++cy;
+ int r = _vm->_coreVar._inventory[i] + 400;
+ nomp = _vm->getString(r - 501 + kInventoryStringIndex);
+ setText(_inventoryMenu[cy]._menuId, _inventoryMenu[cy]._actionId, nomp);
+ enableMenuItem(_inventoryMenu[i]._menuId, _inventoryMenu[i]._actionId);
+ }
+ }
+
+ if (cy < 6) {
+ for (int i = cy + 1; i <= 6; ++i) {
+ setText(_inventoryMenu[i]._menuId, _inventoryMenu[i]._actionId, " ");
+ disableMenuItem(_inventoryMenu[i]._menuId, _inventoryMenu[i]._actionId);
+ }
+ }
+}
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/menu.h b/engines/mortevielle/menu.h
new file mode 100644
index 0000000000..2428d8917b
--- /dev/null
+++ b/engines/mortevielle/menu.h
@@ -0,0 +1,112 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#ifndef MORTEVIELLE_MENU_H
+#define MORTEVIELLE_MENU_H
+
+#include "common/rect.h"
+#include "common/str.h"
+
+namespace Mortevielle {
+class MortevielleEngine;
+
+enum {
+ MENU_NONE = 0, MENU_INVENTORY = 1, MENU_MOVE = 2, MENU_ACTION = 3,
+ MENU_SELF = 4, MENU_DISCUSS = 5, MENU_FILE = 6, MENU_SAVE = 7,
+ MENU_LOAD = 8
+};
+
+enum verbs {OPCODE_NONE = 0, OPCODE_ATTACH = 0x301, OPCODE_WAIT = 0x302, OPCODE_FORCE = 0x303, OPCODE_SLEEP = 0x304, OPCODE_LISTEN = 0x305,
+OPCODE_ENTER = 0x306, OPCODE_CLOSE = 0x307, OPCODE_SEARCH = 0x308, OPCODE_KNOCK = 0x309, OPCODE_SCRATCH = 0x30a,
+OPCODE_READ = 0x30b, OPCODE_EAT = 0x30c, OPCODE_PLACE = 0x30d, OPCODE_OPEN = 0x30e, OPCODE_TAKE = 0x30f,
+OPCODE_LOOK = 0x310, OPCODE_SMELL = 0x311, OPCODE_SOUND = 0x312, OPCODE_LEAVE = 0x313, OPCODE_LIFT = 0x314,
+OPCODE_TURN = 0x315, OPCODE_SHIDE = 0x401, OPCODE_SSEARCH = 0x402, OPCODE_SREAD = 0x403, OPCODE_SPUT = 0x404,
+OPCODE_SLOOK = 0x405};
+
+struct menuItem {
+ int _menuId;
+ int _actionId;
+};
+
+static const menuItem _actionMenu[12] = {
+ {OPCODE_NONE >> 8, OPCODE_NONE & 0xFF},
+ {OPCODE_SHIDE >> 8, OPCODE_SHIDE & 0xFF},
+ {OPCODE_ATTACH >> 8, OPCODE_ATTACH & 0xFF},
+ {OPCODE_FORCE >> 8, OPCODE_FORCE & 0xFF},
+ {OPCODE_SLEEP >> 8, OPCODE_SLEEP & 0xFF},
+ {OPCODE_ENTER >> 8, OPCODE_ENTER & 0xFF},
+ {OPCODE_CLOSE >> 8, OPCODE_CLOSE & 0xFF},
+ {OPCODE_KNOCK >> 8, OPCODE_KNOCK & 0xFF},
+ {OPCODE_EAT >> 8, OPCODE_EAT & 0xFF},
+ {OPCODE_PLACE >> 8, OPCODE_PLACE & 0xFF},
+ {OPCODE_OPEN >> 8, OPCODE_OPEN & 0xFF},
+ {OPCODE_LEAVE >> 8, OPCODE_LEAVE & 0xFF}
+};
+
+class Menu {
+private:
+ MortevielleEngine *_vm;
+
+ byte _charArr[7][24];
+ int _msg3;
+ int _msg4;
+
+ void util(Common::Point pos);
+ void invert(int indx);
+ void menuDown(int ii);
+public:
+ bool _menuActive;
+ bool _menuSelected;
+ bool _multiTitle;
+ bool _menuDisplayed;
+ Common::String _inventoryStringArray[9];
+ Common::String _moveStringArray[8];
+ Common::String _actionStringArray[22];
+ Common::String _selfStringArray[7];
+ Common::String _discussStringArray[9];
+ menuItem _discussMenu[9];
+ menuItem _inventoryMenu[9];
+ menuItem _moveMenu[8];
+
+ void setText(int menuId, int actionId, Common::String name);
+ void setDestinationText(int roomId);
+ void setInventoryText();
+ void disableMenuItem(int menuId, int actionId);
+ void enableMenuItem(int menuId, int actionId);
+ void displayMenu();
+ void drawMenu();
+ void menuUp(int msgId);
+ void eraseMenu();
+ void updateMenu();
+ void initMenu(MortevielleEngine *vm);
+
+ void setSearchMenu();
+ void unsetSearchMenu();
+};
+
+} // End of namespace Mortevielle
+#endif
diff --git a/engines/mortevielle/module.mk b/engines/mortevielle/module.mk
new file mode 100644
index 0000000000..e18657cb6a
--- /dev/null
+++ b/engines/mortevielle/module.mk
@@ -0,0 +1,24 @@
+MODULE := engines/mortevielle
+
+MODULE_OBJS := \
+ actions.o \
+ debugger.o \
+ detection.o \
+ dialogs.o \
+ graphics.o \
+ menu.o \
+ mortevielle.o \
+ mouse.o \
+ outtext.o \
+ saveload.o \
+ sound.o \
+ speech.o \
+ utils.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_MORTEVIELLE), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/mortevielle/mortevielle.cpp b/engines/mortevielle/mortevielle.cpp
new file mode 100644
index 0000000000..2d45923032
--- /dev/null
+++ b/engines/mortevielle/mortevielle.cpp
@@ -0,0 +1,445 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+
+#include "mortevielle/dialogs.h"
+#include "mortevielle/menu.h"
+#include "mortevielle/mouse.h"
+#include "mortevielle/outtext.h"
+#include "mortevielle/saveload.h"
+#include "mortevielle/outtext.h"
+
+#include "common/system.h"
+#include "common/config-manager.h"
+#include "common/debug-channels.h"
+#include "engines/util.h"
+#include "engines/engine.h"
+#include "graphics/palette.h"
+#include "graphics/pixelformat.h"
+
+namespace Mortevielle {
+
+MortevielleEngine *g_vm;
+
+MortevielleEngine::MortevielleEngine(OSystem *system, const ADGameDescription *gameDesc):
+ Engine(system), _gameDescription(gameDesc), _randomSource("mortevielle"),
+ _soundManager(_mixer) {
+ g_vm = this;
+ _debugger.setParent(this);
+ _dialogManager.setParent(this);
+ _screenSurface.setParent(this);
+ _mouse.setParent(this);
+ _text.setParent(this);
+ _soundManager.setParent(this);
+ _speechManager.setParent(this);
+ _savegameManager.setParent(this);
+
+ _lastGameFrame = 0;
+ _mouseClick = false;
+ _inMainGameLoop = false;
+ _quitGame = false;
+
+ _roomPresenceLuc = false;
+ _roomPresenceIda = false;
+ _purpleRoomPresenceLeo = false;
+ _roomPresenceGuy = false;
+ _roomPresenceEva = false;
+ _roomPresenceMax = false;
+ _roomPresenceBob = false;
+ _roomPresencePat = false;
+ _toiletsPresenceBobMax = false;
+ _bathRoomPresenceBobMax = false;
+ _room9PresenceLeo = false;
+
+ _soundOff = false;
+ _largestClearScreen = false;
+ _hiddenHero = false;
+ _heroSearching = false;
+ _keyPressedEsc = false;
+ _reloadCFIEC = false;
+
+ _blo = false;
+ _col = false;
+ _syn = false;
+ _obpart = false;
+ _destinationOk = false;
+ _anyone = false;
+ _uptodatePresence = false;
+
+ _textColor = 0;
+ _currGraphicalDevice = -1;
+ _newGraphicalDevice = -1;
+ _place = -1;
+
+ _x26KeyCount = -1;
+ _caff = -1;
+ _day = 0;
+
+ memset(_mem, 0, sizeof(_mem));
+ _curPict = nullptr;
+ _curAnim = nullptr;
+ _rightFramePict = nullptr;
+ _compMusicBuf1 = nullptr;
+ _compMusicBuf2 = nullptr;
+}
+
+MortevielleEngine::~MortevielleEngine() {
+ free(_curPict);
+ free(_curAnim);
+ free(_rightFramePict);
+ free(_compMusicBuf1);
+ free(_compMusicBuf2);
+}
+
+/**
+ * Specifies whether the engine supports given features
+ */
+bool MortevielleEngine::hasFeature(EngineFeature f) const {
+ return
+ (f == kSupportsRTL) ||
+ (f == kSupportsLoadingDuringRuntime) ||
+ (f == kSupportsSavingDuringRuntime);
+}
+
+/**
+ * Return true if a game can currently be loaded
+ */
+bool MortevielleEngine::canLoadGameStateCurrently() {
+ // Saving is only allowed in the main game event loop
+ return _inMainGameLoop;
+}
+
+/**
+ * Return true if a game can currently be saved
+ */
+bool MortevielleEngine::canSaveGameStateCurrently() {
+ // Loading is only allowed in the main game event loop
+ return _inMainGameLoop;
+}
+
+/**
+ * Load in a savegame at the specified slot number
+ */
+Common::Error MortevielleEngine::loadGameState(int slot) {
+ return _savegameManager.loadGame(slot);
+}
+
+/**
+ * Save the current game
+ */
+Common::Error MortevielleEngine::saveGameState(int slot, const Common::String &desc) {
+ if (slot == 0)
+ return Common::kWritingFailed;
+
+ return _savegameManager.saveGame(slot, desc);
+}
+
+/**
+ * Support method that generates a savegame name
+ * @param slot Slot number
+ */
+Common::String MortevielleEngine::generateSaveFilename(const Common::String &target, int slot) {
+ if (slot == 0)
+ // Initial game state loaded when the game starts
+ return "sav0.mor";
+
+ return Common::String::format("%s.%03d", target.c_str(), slot);
+}
+
+/**
+ * Initialize the game state
+ */
+Common::ErrorCode MortevielleEngine::initialize() {
+ // Initialize graphics mode
+ initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, true);
+
+ // Set debug channels
+ DebugMan.addDebugChannel(kMortevielleCore, "core", "Core debugging");
+ DebugMan.addDebugChannel(kMortevielleGraphics, "graphics", "Graphics debugging");
+
+ // Set up an intermediate screen surface
+ _screenSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
+
+ // Set the screen mode
+ _currGraphicalDevice = MODE_EGA;
+ _resolutionScaler = 2;
+
+ _txxFileFl = false;
+ // Load texts from TXX files
+ loadTexts();
+
+ // Load the mort.dat resource
+ Common::ErrorCode result = loadMortDat();
+ if (result != Common::kNoError) {
+ _screenSurface.free();
+ return result;
+ }
+
+ // Load some error messages (was previously in chartex())
+ _hintPctMessage = getString(580); // You should have noticed %d hints
+
+ // Set default EGA palette
+ _paletteManager.setDefaultPalette();
+
+ // Setup the mouse cursor
+ initMouse();
+
+ _currGraphicalDevice = MODE_EGA;
+ _newGraphicalDevice = _currGraphicalDevice;
+ loadPalette();
+ loadCFIPH();
+ loadCFIEC();
+ decodeNumber(&_cfiecBuffer[161 * 16], (_cfiecBufferSize - (161 * 16)) / 64);
+ _x26KeyCount = 1;
+ initMaxAnswer();
+ initMouse();
+
+ loadPlaces();
+ _soundOff = false;
+ _largestClearScreen = false;
+
+ testKeyboard();
+ showConfigScreen();
+ _newGraphicalDevice = _currGraphicalDevice;
+ testKeyboard();
+ if (_newGraphicalDevice != _currGraphicalDevice)
+ _currGraphicalDevice = _newGraphicalDevice;
+ hirs();
+
+ return Common::kNoError;
+}
+
+/**
+ * Loads the contents of the mort.dat data file
+ */
+Common::ErrorCode MortevielleEngine::loadMortDat() {
+ Common::File f;
+
+ // Open the mort.dat file
+ if (!f.open(MORT_DAT)) {
+ GUIErrorMessage("Could not locate 'mort.dat'.");
+ return Common::kReadingFailed;
+ }
+
+ // Validate the data file header
+ char fileId[4];
+ f.read(fileId, 4);
+ if (strncmp(fileId, "MORT", 4) != 0) {
+ GUIErrorMessage("The located mort.dat data file is invalid");
+ return Common::kReadingFailed;
+ }
+
+ // Check the version
+ if (f.readByte() < MORT_DAT_REQUIRED_VERSION) {
+ GUIErrorMessage("The located mort.dat data file is too old, please download an updated version on scummvm.org");
+ return Common::kReadingFailed;
+ }
+ f.readByte(); // Minor version
+
+ // Loop to load resources from the data file
+ while (f.pos() < f.size()) {
+ // Get the Id and size of the next resource
+ char dataType[4];
+ int dataSize;
+ f.read(dataType, 4);
+ dataSize = f.readUint16LE();
+
+ if (!strncmp(dataType, "FONT", 4)) {
+ // Font resource
+ _screenSurface.readFontData(f, dataSize);
+ } else if (!strncmp(dataType, "SSTR", 4)) {
+ readStaticStrings(f, dataSize, kStaticStrings);
+ } else if ((!strncmp(dataType, "GSTR", 4)) && (!_txxFileFl)) {
+ readStaticStrings(f, dataSize, kGameStrings);
+ } else {
+ // Unknown section
+ f.skip(dataSize);
+ }
+ }
+
+ // Close the file
+ f.close();
+
+ assert(_engineStrings.size() > 0);
+ return Common::kNoError;
+}
+
+/**
+ * Read in a static strings block, and if the language matches, load up the static strings
+ */
+void MortevielleEngine::readStaticStrings(Common::File &f, int dataSize, DataType dataType) {
+ // Figure out what language Id is needed
+ byte desiredLanguageId;
+ switch(getLanguage()) {
+ case Common::EN_ANY:
+ desiredLanguageId = MORTDAT_LANG_ENGLISH;
+ break;
+ case Common::FR_FRA:
+ desiredLanguageId = MORTDAT_LANG_FRENCH;
+ break;
+ case Common::DE_DEU:
+ desiredLanguageId = MORTDAT_LANG_GERMAN;
+ break;
+ default:
+ warning("Language not supported, switching to English");
+ desiredLanguageId = MORTDAT_LANG_ENGLISH;
+ break;
+ }
+
+ // Read in the language
+ byte languageId = f.readByte();
+ --dataSize;
+
+ // If the language isn't correct, then skip the entire block
+ if (languageId != desiredLanguageId) {
+ f.skip(dataSize);
+ return;
+ }
+
+ // Load in each of the strings
+ while (dataSize > 0) {
+ Common::String s;
+ char ch;
+ while ((ch = (char)f.readByte()) != '\0')
+ s += ch;
+
+ if (dataType == kStaticStrings)
+ _engineStrings.push_back(s);
+ else if (dataType == kGameStrings)
+ _gameStrings.push_back(s);
+
+ dataSize -= s.size() + 1;
+ }
+ assert(dataSize == 0);
+}
+
+/*-------------------------------------------------------------------------*/
+
+Common::Error MortevielleEngine::run() {
+ // Initialize the game
+ Common::ErrorCode err = initialize();
+ if (err != Common::kNoError)
+ return err;
+
+ // Check for a savegame
+ int loadSlot = 0;
+ if (ConfMan.hasKey("save_slot")) {
+ int gameToLoad = ConfMan.getInt("save_slot");
+ if ((gameToLoad >= 1) && (gameToLoad <= 999))
+ loadSlot = gameToLoad;
+ }
+
+ if (loadSlot == 0)
+ // Show the game introduction
+ showIntroduction();
+
+ // Either load the initial game state savegame, or the specified savegame number
+ adzon();
+ _savegameManager.loadSavegame(generateSaveFilename(loadSlot));
+
+ // Run the main game loop
+ mainGame();
+
+ // Cleanup (allocated in initialize())
+ _screenSurface.free();
+ free(_speechManager._cfiphBuffer);
+ free(_cfiecBuffer);
+
+ return Common::kNoError;
+}
+
+/**
+ * Show the game introduction
+ */
+void MortevielleEngine::showIntroduction() {
+ _dialogManager.displayIntroScreen(false);
+ _speechManager._mlec = 0;
+ _dialogManager.checkForF8(142, false);
+ if (shouldQuit())
+ return;
+
+ _dialogManager.displayIntroFrame2();
+ _dialogManager.checkForF8(143, true);
+ if (shouldQuit())
+ return;
+
+ // TODO: Once music (Amiga/Atari ports) is implemented, only use the below delay if music is turned off
+ showTitleScreen();
+ delay(3000);
+ music();
+}
+
+/**
+ * Main game loop. Handles potentially playing the game multiple times, such as if the player
+ * loses, and chooses to start playing the game again.
+ */
+void MortevielleEngine::mainGame() {
+ if (_reloadCFIEC)
+ loadCFIEC();
+
+ for (_crep = 1; _crep <= _x26KeyCount; ++_crep)
+ decodeNumber(&_cfiecBuffer[161 * 16], (_cfiecBufferSize - (161 * 16)) / 64);
+
+ loadBRUIT5();
+ _menu.initMenu(this);
+
+ charToHour();
+ initGame();
+ hirs();
+ drawRightFrame();
+ _mouse.showMouse();
+
+ // Loop to play the game
+ do {
+ playGame();
+ if (shouldQuit())
+ return;
+ } while (!_quitGame);
+}
+
+/**
+ * This method handles playing a loaded game
+ * @remarks Originally called tjouer
+ */
+void MortevielleEngine::playGame() {
+ gameLoaded();
+
+ // Loop handling actions until the game has to be quit, or show the lose or end sequence
+ do {
+ handleAction();
+ if (shouldQuit())
+ return;
+ } while (!((_quitGame) || (_endGame) || (_loseGame)));
+
+ if (_endGame)
+ endGame();
+ else if (_loseGame)
+ askRestart();
+}
+
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/mortevielle.h b/engines/mortevielle/mortevielle.h
new file mode 100644
index 0000000000..795bac5652
--- /dev/null
+++ b/engines/mortevielle/mortevielle.h
@@ -0,0 +1,522 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#ifndef MORTEVIELLE_MORTEVIELLE_H
+#define MORTEVIELLE_MORTEVIELLE_H
+
+#include "common/events.h"
+#include "common/file.h"
+#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"
+#include "mortevielle/debugger.h"
+#include "mortevielle/dialogs.h"
+#include "mortevielle/graphics.h"
+#include "mortevielle/menu.h"
+#include "mortevielle/mouse.h"
+#include "mortevielle/saveload.h"
+#include "mortevielle/sound.h"
+#include "mortevielle/speech.h"
+#include "mortevielle/outtext.h"
+
+namespace Mortevielle {
+
+/*---------------------------------------------------------------------------*/
+/*------------------- MEMORY MAP ------------------------*/
+/*---------------------------------------------------------------------------*/
+/* The following is a list of physical addresses in memory currently used
+ * by the game.
+ *
+ * Address
+ * -------
+ * 5000:0 - Music data
+ * 6000:0 - Decompressed current image
+ * 7000:0+ - Compressed images
+ * 7000:2 - 16 words representing palette map
+ * 7000:4138 - width, height, x/y offset of decoded image
+ */
+const int kAdrMusic = 0x5000;
+
+// Debug channels
+enum {
+ kMortevielleCore = 1 << 0,
+ kMortevielleGraphics = 1 << 1
+};
+
+// Game languages
+enum {
+ MORTDAT_LANG_FRENCH = 0,
+ MORTDAT_LANG_ENGLISH = 1,
+ MORTDAT_LANG_GERMAN = 2
+};
+
+// Static string list
+enum {
+ S_YES_NO = 0, S_GO_TO = 1, S_SOMEONE_ENTERS = 2, S_COOL = 3, S_LOURDE = 4,
+ S_MALSAINE = 5, S_IDEM = 6, S_YOU = 7, S_ARE = 8, S_ALONE = 9,
+ S_HEAR_NOISE = 10, S_SHOULD_HAVE_NOTICED = 11, S_NUMBER_OF_HINTS = 12,
+ S_WANT_TO_WAKE_UP = 13, S_OKAY = 14, S_SAVE_LOAD = 15, S_RESTART = 18, S_F3 = 19,
+ S_F8 = 20, S_HIDE_SELF = 21, S_TAKE = 22, S_PROBE = 23, S_RAISE = 24, S_SUITE = 25,
+ S_STOP = 26, S_USE_DEP_MENU = 27, S_LIFT = 28, S_READ = 29,
+ S_LOOK = 30, S_SEARCH = 31, S_OPEN = 32, S_PUT = 33, S_TURN = 34, S_TIE = 35, S_CLOSE = 36,
+ S_HIT = 37, S_POSE = 38, S_SMASH = 39,
+
+ S_SMELL = 40, S_SCRATCH = 41, S_PROBE2 = 42, S_BEFORE_USE_DEP_MENU = 43, S_DAY = 44
+};
+
+enum DataType {
+ kStaticStrings = 0,
+ kGameStrings = 1
+};
+
+#define SCREEN_WIDTH 640
+#define SCREEN_HEIGHT 400
+#define SCREEN_ORIG_HEIGHT 200
+#define MORT_DAT_REQUIRED_VERSION 1
+#define MORT_DAT "mort.dat"
+#define GAME_FRAME_DELAY (1000 / 50)
+
+const int kTime1 = 410;
+const int kTime2 = 250;
+
+const int kAcha = 492;
+const int kFleche = 1758;
+
+const int kAsoul = 154;
+const int kAouvr = 282;
+const int kAchai = 387;
+const int kArcf = 1272;
+const int kArep = 1314;
+const int kAmzon = 1650;
+const int kArega = 0;
+
+const int kMaxDialogIndex = 9000;
+const int kMaxDialogHint = 600;
+
+const int kDescriptionStringIndex = 0; // Unused
+const int kInventoryStringIndex = 186;
+const int kQuestionStringIndex = 247;
+const int kDialogStringIndex = 292;
+const int kMenuPlaceStringIndex = 435;
+const int kMenuActionStringIndex = 476;
+const int kMenuSelfStringIndex = 497;
+const int kMenuSayStringIndex = 502;
+const int kMaxPatt = 20;
+
+/*
+9 "A glance at the forbidden$",
+18 "It's already open$",
+26 "A photograph$"
+*/
+enum Places {
+ OWN_ROOM = 0, GREEN_ROOM = 1, PURPLE_ROOM = 2, TOILETS = 3, DARKBLUE_ROOM = 4,
+ BLUE_ROOM = 5, RED_ROOM = 6, BATHROOM = 7, GREEN_ROOM2 = 8, ROOM9 = 9,
+ DINING_ROOM = 10, BUREAU = 11, KITCHEN = 12, ATTIC = 13, CELLAR = 14,
+ LANDING = 15, CRYPT = 16, SECRET_PASSAGE = 17, ROOM18 = 18, MOUNTAIN = 19,
+ CHAPEL = 20, MANOR_FRONT = 21, MANOR_BACK = 22, INSIDE_WELL = 23, WELL = 24,
+ DOOR = 25, ROOM26 = 26, COAT_ARMS = 27
+};
+
+enum GraphicModes { MODE_AMSTRAD1512 = 0, MODE_CGA = 1, MODE_EGA = 2, MODE_HERCULES = 3, MODE_TANDY = 4 };
+
+struct nhom {
+ byte _id; /* number between 0 and 32 */
+ byte _hom[4];
+};
+
+struct CgaPalette {
+ byte _p;
+ nhom _a[16];
+};
+
+struct Pattern {
+ byte _tay, _tax;
+ byte _des[kMaxPatt + 1][kMaxPatt + 1];
+};
+
+struct SaveStruct {
+ int _faithScore;
+ byte _pctHintFound[11];
+ byte _availableQuestion[43];
+ byte _inventory[31];
+ int _currPlace;
+ int _atticBallHoleObjectId;
+ int _atticRodHoleObjectId;
+ int _cellarObjectId;
+ int _secretPassageObjectId;
+ int _wellObjectId;
+ int _selectedObjectId;
+ int _purpleRoomObjectId;
+ int _cryptObjectId;
+ bool _alreadyEnteredManor;
+ byte _fullHour;
+};
+
+struct Hint {
+ int _hintId;
+ byte _point;
+};
+
+class MortevielleEngine : public Engine {
+private:
+ const ADGameDescription *_gameDescription;
+ Common::Stack<int> _keypresses;
+ uint32 _lastGameFrame;
+ Common::Point _mousePos;
+ Common::StringArray _engineStrings;
+ Common::StringArray _gameStrings;
+
+ Pattern _patternArr[15];
+ int _menuOpcode;
+
+ bool _mouseClick;
+ bool _inMainGameLoop; // Flag when the main game loop is active
+ bool _quitGame; // Quit game flag. Originally called 'arret'
+ bool _endGame; // End game flag. Originally called 'solu'
+ bool _loseGame; // Lose game flag. Originally called 'perdu'
+ bool _txxFileFl; // Flag used to determine if texts are from the original files or from a DAT file
+ bool _roomPresenceLuc;
+ bool _roomPresenceIda;
+ bool _purpleRoomPresenceLeo;
+ bool _roomPresenceGuy;
+ bool _roomPresenceEva;
+ bool _roomPresenceMax;
+ bool _roomPresenceBob;
+ bool _roomPresencePat;
+ bool _toiletsPresenceBobMax;
+ bool _bathRoomPresenceBobMax;
+ bool _room9PresenceLeo;
+ bool _hiddenHero;
+ bool _heroSearching;
+ bool _keyPressedEsc;
+ bool _reloadCFIEC;
+ bool _col;
+ bool _syn;
+ bool _obpart;
+ bool _anyone;
+ bool _uptodatePresence;
+
+ int _textColor;
+ int _place;
+ int _manorDistance;
+ int _currBitIndex;
+ int _currDay;
+ int _currHour;
+ int _currHalfHour;
+ int _day;
+ int _hour;
+ int _minute;
+ int _mchai;
+ int _controlMenu;
+ int _startHour;
+ int _endHour;
+ Common::Point _stdPal[91][17];
+ CgaPalette _cgaPal[91];
+
+ int _x26KeyCount;
+ int _roomDoorId;
+ int _openObjCount;
+ int _takeObjCount;
+ int _num;
+ int _searchCount;
+ bool _introSpeechPlayed;
+ int _inGameHourDuration;
+ int _x;
+ int _y;
+ int _currentHourCount;
+ int _currentDayHour;
+
+ Common::String _hintPctMessage;
+ byte *_cfiecBuffer;
+ int _cfiecBufferSize;
+ int _openObjects[8];
+ uint16 _dialogIndexArray[kMaxDialogIndex + 1];
+ Hint _dialogHintArray[kMaxDialogHint + 1];
+
+ Common::ErrorCode initialize();
+ Common::ErrorCode loadMortDat();
+ void readStaticStrings(Common::File &f, int dataSize, DataType dataType);
+ void loadFont(Common::File &f);
+ bool handleEvents();
+ void addKeypress(Common::Event &evt);
+ void initMouse();
+ void showIntroduction();
+ void mainGame();
+ void playGame();
+ void handleAction();
+ void displayCGAPattern(int n, Pattern p, nhom *pal);
+ void loadPalette();
+ void loadTexts();
+ void loadBRUIT5();
+ void loadCFIEC();
+ void loadCFIPH();
+ void showTitleScreen();
+ int readclock();
+ void palette(int v1);
+ int checkLeoMaxRandomPresence();
+ void interactNPC();
+ void initCaveOrCellar();
+ void displayControlMenu();
+ void displayItemInHand(int objId);
+ void resetRoomVariables(int roomId);
+ int getPresenceStats(int &rand, int faithScore, int roomId);
+ void setPresenceFlags(int roomId);
+ void testKey(bool d);
+ void exitRoom();
+ void getReadDescription(int objId);
+ void getSearchDescription(int objId);
+ int checkLeaveSecretPassage();
+ void changeGraphicalDevice(int newDevice);
+ void startDialog(int16 rep);
+ void endSearch();
+ int convertCharacterIndexToBitIndex(int characterIndex);
+ int convertBitIndexToCharacterIndex(int bitIndex);
+ void clearUpperLeftPart();
+ void clearDescriptionBar();
+ void clearVerbBar();
+ void clearUpperRightPart();
+ int getRandomNumber(int minval, int maxval);
+ void showMoveMenuAlert();
+ void showConfigScreen();
+ void decodeNumber(byte *pStart, int count);
+ void resetVariables();
+ void music();
+ void drawRightFrame();
+ void prepareRoom();
+ void drawClock();
+ void checkManorDistance();
+ void gotoManorFront();
+ void gotoManorBack();
+ void gotoDiningRoom();
+ bool checkInventory(int objectId);
+ void loseGame();
+ void floodedInWell();
+ void displayDiningRoom();
+ void startMusicOrSpeech(int so);
+ void setTextColor(int col);
+ void prepareScreenType1();
+ void prepareScreenType2();
+ void prepareScreenType3();
+ void updateHour(int &day, int &hour, int &minute);
+ void getKnockAnswer();
+ int getPresenceStatsGreenRoom();
+ int getPresenceStatsPurpleRoom();
+ int getPresenceStatsToilets();
+ int getPresenceStatsBlueRoom();
+ int getPresenceStatsRedRoom();
+ int getPresenceStatsDiningRoom(int &hour);
+ int getPresenceStatsBureau(int &hour);
+ int getPresenceStatsKitchen();
+ int getPresenceStatsAttic();
+ int getPresenceStatsLanding();
+ int getPresenceStatsChapel(int &hour);
+ int getPresenceBitIndex(int roomId);
+ void setPresenceGreenRoom(int roomId);
+ void setPresencePurpleRoom();
+ void setPresenceBlueRoom();
+ void setPresenceRedRoom(int roomId);
+ int setPresenceDiningRoom(int hour);
+ int setPresenceBureau(int hour);
+ int setPresenceKitchen();
+ int setPresenceLanding();
+ int setPresenceChapel(int hour);
+ void setRandomPresenceGreenRoom(int faithScore);
+ void setRandomPresencePurpleRoom(int faithScore);
+ void setRandomPresenceBlueRoom(int faithScore);
+ void setRandomPresenceRedRoom(int faithScore);
+ void setRandomPresenceRoom9(int faithScore);
+ void setRandomPresenceDiningRoom(int faithScore);
+ void setRandomPresenceBureau(int faithScore);
+ void setRandomPresenceKitchen(int faithScore);
+ void setRandomPresenceAttic(int faithScore);
+ void setRandomPresenceLanding(int faithScore);
+ void setRandomPresenceChapel(int faithScore);
+ void loadPlaces();
+ void resetPresenceInRooms(int roomId);
+ void showPeoplePresent(int bitIndex);
+ int selectCharacters(int min, int max);
+ void fctMove();
+ void fctTake();
+ void fctInventoryTake();
+ void fctLift();
+ void fctRead();
+ void fctSelfRead();
+ void fctLook();
+ void fctSelftLook();
+ void fctSearch();
+ void fctSelfSearch();
+ void fctOpen();
+ void fctPlace();
+ void fctTurn();
+ void fctSelfHide();
+ void fctAttach();
+ void fctClose();
+ void fctKnock();
+ void fctSelfPut();
+ void fctListen();
+ void fctEat();
+ void fctEnter();
+ void fctSleep();
+ void fctForce();
+ void fctLeave();
+ void fctWait();
+ void fctSound();
+ void fctDiscuss();
+ void fctSmell();
+ void fctScratch();
+ void endGame();
+ void askRestart();
+ void handleOpcode();
+ void prepareDisplayText();
+ bool decryptNextChar(char &c, int &idx, byte &pt);
+ void displayStatusArrow();
+ void displayStatusInDescriptionBar(char stat);
+ void displayQuestionText(Common::String s, int cmd);
+ void displayTextInDescriptionBar(int x, int y, int nb, int mesgId);
+ void displayTextInVerbBar(Common::String text);
+ void mapMessageId(int &mesgId);
+ void resetOpenObjects();
+ void setCoordinates(int sx);
+ void drawPicture();
+ void drawPictureWithText();
+ void addObjectToInventory(int objectId);
+ void putInHand(int &objId);
+ void initMaxAnswer();
+ void displayAnimFrame(int frameNum, int animId);
+
+ void copcha();
+ void adzon();
+ void premtet();
+ void ajchai();
+ void ecr2(Common::String text);
+ void tlu(int af, int ob);
+ void mennor();
+ void tsuiv();
+ void treg(int objId);
+ int rechai();
+
+public:
+ Common::Point _prevPos;
+ int _currMenu;
+ int _currAction;
+ int _drawingSizeArr[108];
+ int _charAnswerCount[9];
+ int _charAnswerMax[9];
+ byte _tabdon[4001];
+ bool _soundOff;
+ bool _blo;
+ bool _destinationOk;
+ bool _largestClearScreen;
+ int _currGraphicalDevice;
+ int _newGraphicalDevice;
+ float _addFix;
+ int _savedBitIndex;
+ int _numpal;
+ int _key;
+ SaveStruct _coreVar, _saveStruct;
+
+ int _maff;
+ int _caff;
+ int _crep;
+
+ int _resolutionScaler;
+ byte _destinationArray[7][25];
+
+ // TODO: Replace the following with proper implementations, or refactor out the code using them
+ byte _mem[65536 * 16];
+ byte *_curPict;
+ byte *_curAnim;
+ byte *_rightFramePict;
+ byte *_compMusicBuf1;
+ byte *_compMusicBuf2;
+
+ Debugger _debugger;
+ ScreenSurface _screenSurface;
+ PaletteManager _paletteManager;
+ GfxSurface _backgroundSurface;
+ Common::RandomSource _randomSource;
+ SoundManager _soundManager;
+ SavegameManager _savegameManager;
+ SpeechManager _speechManager;
+ Menu _menu;
+ MouseHandler _mouse;
+ TextHandler _text;
+ DialogManager _dialogManager;
+
+ MortevielleEngine(OSystem *system, const ADGameDescription *gameDesc);
+ ~MortevielleEngine();
+ virtual bool hasFeature(EngineFeature f) const;
+ virtual bool canLoadGameStateCurrently();
+ virtual bool canSaveGameStateCurrently();
+ virtual Common::Error loadGameState(int slot);
+ virtual Common::Error saveGameState(int slot, const Common::String &desc);
+ virtual Common::Error run();
+ uint32 getGameFlags() const;
+ Common::Language getLanguage() const;
+ static Common::String generateSaveFilename(const Common::String &target, int slot);
+ Common::String generateSaveFilename(int slot) { return generateSaveFilename(_targetName, slot); }
+
+ int getChar();
+ bool keyPressed();
+ Common::Point getMousePos() const { return _mousePos; }
+ void setMousePos(const Common::Point &pt);
+ bool getMouseClick() const { return _mouseClick; }
+ void setMouseClick(bool v) { _mouseClick = v; }
+ Common::String getEngineString(int idx) const { return _engineStrings[idx]; }
+ Common::String getGameString(int idx) const { return _gameStrings[idx]; }
+
+ void delay(int amount);
+ void gameLoaded();
+ void initGame();
+ void displayAloneText();
+ void draw(int x, int y);
+ void charToHour();
+ void hourToChar();
+ Common::String getString(int num);
+ void setPal(int n);
+ Common::String copy(const Common::String &s, int idx, size_t size);
+ void testKeyboard();
+ int getPresence(int roomId);
+ void displayEmptyHand();
+ void displayPicture(const byte *pic, int x, int y);
+
+ int gettKeyPressed();
+ void handleDescriptionText(int f, int mesgId);
+ int getAnimOffset(int frameNum, int animNum);
+
+ void hirs();
+};
+
+extern MortevielleEngine *g_vm;
+
+} // End of namespace Mortevielle
+
+#endif
diff --git a/engines/mortevielle/mouse.cpp b/engines/mortevielle/mouse.cpp
new file mode 100644
index 0000000000..dfc9ccd706
--- /dev/null
+++ b/engines/mortevielle/mouse.cpp
@@ -0,0 +1,273 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+#include "mortevielle/mouse.h"
+
+#include "common/endian.h"
+#include "common/rect.h"
+
+namespace Mortevielle {
+
+/**
+ * Initialize the mouse
+ * @remarks Originally called 'init_mouse'
+ */
+void MouseHandler::initMouse() {
+ _counter = 0;
+ _pos = Common::Point(0, 0);
+
+ _vm->setMouseClick(false);
+}
+
+/**
+ * Backs up the area behind where the mouse cursor is to be drawn
+ * @remarks Originally called 'hide_mouse'
+ */
+void MouseHandler::hideMouse() {
+ // No implementation needed in ScummVM
+}
+
+/**
+ * Draws the mouse cursor
+ * @remarks Originally called 'show_mouse'
+ */
+void MouseHandler::showMouse() {
+ // ScummVM implementation uses CursorMan for drawing the cursor
+}
+
+/**
+ * Set mouse position
+ * @remarks Originally called 'pos_mouse'
+ */
+void MouseHandler::setMousePosition(Common::Point newPos) {
+ if (newPos.x > 314 * _vm->_resolutionScaler)
+ newPos.x = 314 * _vm->_resolutionScaler;
+ else if (newPos.x < 0)
+ newPos.x = 0;
+ if (newPos.y > 199)
+ newPos.y = 199;
+ else if (newPos.y < 0)
+ newPos.y = 0;
+ if (newPos == _pos)
+ return;
+
+ // Set the new position
+ _vm->setMousePos(newPos);
+}
+
+/**
+ * Get mouse poisition
+ * @remarks Originally called 'read_pos_mouse'
+ */
+void MouseHandler::getMousePosition(int &x, int &y, bool &click) {
+ x = _vm->getMousePos().x;
+ y = _vm->getMousePos().y;
+ click = _vm->getMouseClick();
+}
+
+/**
+ * Move mouse
+ * @remarks Originally called 'mov_mouse'
+ */
+void MouseHandler::moveMouse(bool &funct, char &key) {
+ bool p_key;
+ char in1, in2;
+ int cx, cy;
+ bool click;
+
+ // Set defaults and check pending events
+ funct = false;
+ key = '\377';
+ p_key = _vm->keyPressed();
+
+ // If mouse button clicked, return it
+ if (_vm->getMouseClick())
+ return;
+
+ // Handle any pending keypresses
+ while (p_key) {
+ if (_vm->shouldQuit())
+ return;
+
+ in1 = _vm->getChar();
+ getMousePosition(cx, cy, click);
+ switch (toupper(in1)) {
+ case '4':
+ cx -= 8;
+ break;
+ case '2':
+ cy += 8;
+ break;
+ case '6':
+ cx += 8;
+ break;
+ case '8':
+ cy -= 8;
+ break;
+ case '7':
+ cy = 1;
+ cx = 1;
+ break;
+ case '1':
+ cx = 1;
+ cy = 190;
+ break;
+ case '9':
+ cx = 315 * _vm->_resolutionScaler;
+ cy = 1;
+ break;
+ case '3':
+ cy = 190;
+ cx = 315 * _vm->_resolutionScaler;
+ break;
+ case '5':
+ cy = 100;
+ cx = 155 * _vm->_resolutionScaler;
+ break;
+ case ' ':
+ case '\15':
+ _vm->setMouseClick(true);
+ return;
+ break;
+ case '\33':
+ p_key = _vm->keyPressed();
+
+ if (p_key) {
+ in2 = _vm->getChar();
+
+ if ((in2 >= ';') && (in2 <= 'D')) {
+ funct = true;
+ key = in2;
+ return;
+ } else {
+ switch (in2) {
+ case 'K':
+ --cx;
+ break;
+ case 'P':
+ ++cy;
+ break;
+ case 'M':
+ cx += 2;
+ break;
+ case 'H':
+ --cy;
+ break;
+ case 'G':
+ --cx;
+ --cy;
+ break;
+ case 'I':
+ ++cx;
+ --cy;
+ break;
+ case 'O':
+ --cx;
+ ++cy;
+ break;
+ case 'Q':
+ ++cx;
+ ++cy;
+ break;
+ default:
+ break;
+ } // case
+ }
+ }
+ break;
+ case 'I':
+ cx = _vm->_resolutionScaler * 32;
+ cy = 8;
+ break;
+ case 'D':
+ cx = 80 * _vm->_resolutionScaler;
+ cy = 8;
+ break;
+ case 'A':
+ cx = 126 * _vm->_resolutionScaler;
+ cy = 8;
+ break;
+ case 'S':
+ cx = 174 * _vm->_resolutionScaler;
+ cy = 8;
+ break;
+ case 'P':
+ cx = 222 * _vm->_resolutionScaler;
+ cy = 8;
+ break;
+ case 'F':
+ cx = _vm->_resolutionScaler * 270;
+ cy = 8;
+ break;
+ case '\23':
+ _vm->_soundOff = !_vm->_soundOff;
+ return;
+ break;
+ case '\24': // ^T => mode tandy
+ funct = true;
+ key = '\11';
+ break;
+ case '\10': // ^H => mode Hercule
+ funct = true;
+ key = '\7';
+ break;
+ case '\1':
+ case '\3':
+ case '\5':
+ funct = true;
+ key = in1;
+ break;
+ default:
+ break;
+ }
+
+ setMousePosition(Common::Point(cx, cy));
+ p_key = _vm->keyPressed();
+ }
+}
+
+/**
+ * Mouse function : Is mouse in a given rect?
+ * @remarks Originally called 'dans_rect'
+ */
+bool MouseHandler::isMouseIn(Common::Rect r) {
+ int x, y;
+ bool click;
+
+ getMousePosition(x, y, click);
+ if ((x > r.left) && (x < r.right) && (y > r.top) && (y < r.bottom))
+ return true;
+
+ return false;
+}
+
+void MouseHandler::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/mouse.h b/engines/mortevielle/mouse.h
new file mode 100644
index 0000000000..1b9856e2c4
--- /dev/null
+++ b/engines/mortevielle/mouse.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#ifndef MORTEVIELLE_MOUSE_H
+#define MORTEVIELLE_MOUSE_H
+
+#include "common/rect.h"
+
+namespace Mortevielle {
+class MortevielleEngine;
+
+class MouseHandler {
+private:
+ MortevielleEngine *_vm;
+
+ int s_s[12][6];
+ int _counter;
+public:
+ Common::Point _pos;
+
+ void setParent(MortevielleEngine *vm);
+ void initMouse();
+ void hideMouse();
+ void showMouse();
+ void setMousePosition(Common::Point newPos);
+ void getMousePosition(int &x, int &y, bool &click);
+ void moveMouse(bool &funct, char &key);
+ bool isMouseIn(Common::Rect r);
+};
+
+} // End of namespace Mortevielle
+#endif
diff --git a/engines/mortevielle/outtext.cpp b/engines/mortevielle/outtext.cpp
new file mode 100644
index 0000000000..99c06c7c4c
--- /dev/null
+++ b/engines/mortevielle/outtext.cpp
@@ -0,0 +1,330 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+#include "mortevielle/mouse.h"
+#include "mortevielle/outtext.h"
+#include "mortevielle/graphics.h"
+
+#include "common/file.h"
+#include "common/str.h"
+
+namespace Mortevielle {
+
+/**
+ * Next word
+ * @remarks Originally called 'l_motsuiv'
+ */
+int TextHandler::nextWord(int p, const char *ch, int &tab) {
+ int c = p;
+
+ while ((ch[p] != ' ') && (ch[p] != '$') && (ch[p] != '@'))
+ ++p;
+
+ return tab * (p - c);
+}
+
+/**
+ * Engine function - Display Text
+ * @remarks Originally called 'afftex'
+ */
+void TextHandler::displayStr(Common::String inputStr, int x, int y, int dx, int dy, int typ) {
+ int tab;
+ Common::String s;
+ int i, j;
+
+ // Safeguard: add $ just in case
+ inputStr += '$';
+
+ _vm->_screenSurface.putxy(x, y);
+ if (_vm->_resolutionScaler == 1)
+ tab = 10;
+ else
+ tab = 6;
+ dx *= 6;
+ dy *= 6;
+ int xc = x;
+ int yc = y;
+ int xf = x + dx;
+ int yf = y + dy;
+ int p = 0;
+ bool stringParsed = (inputStr[p] == '$');
+ s = "";
+ while (!stringParsed) {
+ switch (inputStr[p]) {
+ case '@':
+ _vm->_screenSurface.drawString(s, typ);
+ s = "";
+ ++p;
+ xc = x;
+ yc += 6;
+ _vm->_screenSurface.putxy(xc, yc);
+ break;
+ case ' ':
+ s += ' ';
+ xc += tab;
+ ++p;
+ if (nextWord(p, inputStr.c_str(), tab) + xc > xf) {
+ _vm->_screenSurface.drawString(s, typ);
+ s = "";
+ xc = x;
+ yc += 6;
+ if (yc > yf) {
+ while (!_vm->keyPressed())
+ ;
+ i = y;
+ do {
+ j = x;
+ do {
+ _vm->_screenSurface.putxy(j, i);
+ _vm->_screenSurface.drawString(" ", 0);
+ j += 6;
+ } while (j <= xf);
+ i += 6;
+ } while (i <= yf);
+ yc = y;
+ }
+ _vm->_screenSurface.putxy(xc, yc);
+ }
+ break;
+ case '$':
+ stringParsed = true;
+ _vm->_screenSurface.drawString(s, typ);
+ break;
+ default:
+ s += inputStr[p];
+ ++p;
+ xc += tab;
+ break;
+ }
+ }
+}
+
+/**
+ * Load DES (picture container) file
+ * @remarks Originally called 'chardes'
+ */
+void TextHandler::loadPictureFile(Common::String filename, Common::String altFilename, int32 skipSize, int length) {
+ Common::File f;
+ if (!f.open(filename)) {
+ if (!f.open(altFilename))
+ error("Missing file: Either %s or %s", filename.c_str(), altFilename.c_str());
+ }
+ // HACK: The original game contains a bug in the 2nd intro screen, in German DOS version.
+ // The size specified in the fxx array is wrong (too short). In order to fix it, we are using
+ // the value -1 to force a variable read length.
+ if (length == -1)
+ length = f.size() - skipSize;
+
+ assert(skipSize + length <= f.size());
+
+ free(_vm->_curPict);
+ _vm->_curPict = (byte *)malloc(sizeof(byte) * length);
+ f.seek(skipSize);
+ f.read(_vm->_curPict, length);
+ f.close();
+}
+
+/**
+ * Load ANI file
+ * @remarks Originally called 'charani'
+ */
+void TextHandler::loadAniFile(Common::String filename, int32 skipSize, int length) {
+ Common::File f;
+ if (!f.open(filename))
+ error("Missing file - %s", filename.c_str());
+
+ assert(skipSize + length <= f.size());
+
+ free(_vm->_curAnim);
+ _vm->_curAnim = (byte *)malloc(sizeof(byte) * length);
+ f.seek(skipSize);
+ f.read(_vm->_curAnim, length);
+ f.close();
+}
+
+void TextHandler::taffich() {
+ static const byte rang[16] = {15, 14, 11, 7, 13, 12, 10, 6, 9, 5, 3, 1, 2, 4, 8, 0};
+
+ static const byte tran1[] = { 121, 121, 138, 139, 120 };
+ static const byte tran2[] = { 150, 150, 152, 152, 100, 110, 159, 100, 100 };
+
+ int cx, drawingSize, npal;
+ int32 drawingStartPos;
+ int alllum[16];
+
+ int a = _vm->_caff;
+ if ((a >= 153) && (a <= 161))
+ a = tran2[a - 153];
+ else if ((a >= 136) && (a <= 140))
+ a = tran1[a - 136];
+ int b = a;
+ if (_vm->_maff == a)
+ return;
+
+ switch (a) {
+ case 16:
+ _vm->_coreVar._pctHintFound[9] = '*';
+ _vm->_coreVar._availableQuestion[42] = '*';
+ break;
+ case 20:
+ _vm->_coreVar._availableQuestion[39] = '*';
+ if (_vm->_coreVar._availableQuestion[36] == '*') {
+ _vm->_coreVar._pctHintFound[3] = '*';
+ _vm->_coreVar._availableQuestion[38] = '*';
+ }
+ break;
+ case 24:
+ _vm->_coreVar._availableQuestion[37] = '*';
+ break;
+ case 30:
+ _vm->_coreVar._availableQuestion[9] = '*';
+ break;
+ case 31: // Coat of arms
+ _vm->_coreVar._pctHintFound[4] = '*';
+ _vm->_coreVar._availableQuestion[35] = '*';
+ break;
+ case 118:
+ _vm->_coreVar._availableQuestion[41] = '*';
+ break;
+ case 143:
+ _vm->_coreVar._pctHintFound[1] = '*';
+ break;
+ case 150:
+ _vm->_coreVar._availableQuestion[34] = '*';
+ break;
+ case 151:
+ _vm->_coreVar._pctHintFound[2] = '*';
+ break;
+ default:
+ break;
+ }
+
+ _vm->_destinationOk = true;
+ _vm->_mouse.hideMouse();
+ drawingStartPos = 0;
+ Common::String filename, altFilename;
+
+ if ((a != 50) && (a != 51)) {
+ _vm->_maff = a;
+ if (a == 159)
+ a = 86;
+ else if (a > 140)
+ a -= 67;
+ else if (a > 137)
+ a -= 66;
+ else if (a > 99)
+ a -= 64;
+ else if (a > 69)
+ a -= 42;
+ else if (a > 29)
+ a -= 5;
+ else if (a == 26)
+ a = 24;
+ else if (a > 18)
+ --a;
+ npal = a;
+
+ for (cx = 0; cx <= (a - 1); ++cx)
+ drawingStartPos += _vm->_drawingSizeArr[cx];
+ drawingSize = _vm->_drawingSizeArr[a];
+
+ altFilename = filename = "DXX.mor";
+ } else {
+ filename = "DZZ.mor";
+ altFilename = "DZZALL";
+
+ if (a == 50) {
+ // First intro screen
+ drawingStartPos = 0;
+ drawingSize = _vm->_drawingSizeArr[87];
+ } else { // a == 51
+ // Second intro screen
+ drawingStartPos = _vm->_drawingSizeArr[87];
+ // HACK: Force a variable size in order to fix the wrong size used by the German version
+ drawingSize = -1;
+ }
+ _vm->_maff = a;
+ npal = a + 37;
+ }
+ loadPictureFile(filename, altFilename, drawingStartPos, drawingSize);
+ if (_vm->_currGraphicalDevice == MODE_HERCULES) {
+ for (int i = 0; i <= 15; ++i) {
+ int palh = READ_LE_UINT16(&_vm->_curPict[2 + (i << 1)]);
+ alllum[i] = (palh & 15) + (((uint)palh >> 12) & 15) + (((uint)palh >> 8) & 15);
+ }
+ for (int i = 0; i <= 15; ++i) {
+ int k = 0;
+ for (int j = 0; j <= 15; ++j) {
+ if (alllum[j] > alllum[k])
+ k = j;
+ }
+ _vm->_curPict[2 + (k << 1)] = rang[i];
+ alllum[k] = -1;
+ }
+ }
+ _vm->_numpal = npal;
+ _vm->setPal(npal);
+
+ if ((b < 15) || (b == 16) || (b == 17) || (b == 24) || (b == 26) || (b == 50)) {
+ drawingStartPos = 0;
+ if ((b < 15) || (b == 16) || (b == 17) || (b == 24) || (b == 26)) {
+ if (b == 26)
+ b = 18;
+ else if (b == 24)
+ b = 17;
+ else if (b > 15)
+ --b;
+ for (cx = 0; cx <= (b - 1); ++cx)
+ drawingStartPos += _vm->_drawingSizeArr[cx + 89];
+ drawingSize = _vm->_drawingSizeArr[b + 89];
+ filename = "AXX.mor";
+ } else { // b == 50
+ // CHECKME: the size of AZZ.mor is 1280 for the DOS version
+ // and 1260 for the Amiga version. Maybe the 20 bytes
+ // are a filler (to get 10 blocks of 128 bytes),
+ // or the size should be variable.
+ drawingSize = 1260;
+ filename = "AZZ.mor";
+ }
+ loadAniFile(filename, drawingStartPos, drawingSize);
+ }
+ _vm->_mouse.showMouse();
+ if ((a < COAT_ARMS) && ((_vm->_maff < COAT_ARMS) || (_vm->_coreVar._currPlace == LANDING)) && (_vm->_currAction != OPCODE_ENTER)) {
+ if ((a == ATTIC) || (a == CELLAR))
+ _vm->displayAloneText();
+ else if (!_vm->_blo)
+ _vm->getPresence(_vm->_coreVar._currPlace);
+ _vm->_savedBitIndex = 0;
+ }
+}
+
+void TextHandler::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/outtext.h b/engines/mortevielle/outtext.h
new file mode 100644
index 0000000000..44868036d5
--- /dev/null
+++ b/engines/mortevielle/outtext.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.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#ifndef MORTEVIELLE_OUTTEXT_H
+#define MORTEVIELLE_OUTTEXT_H
+
+#include "common/str.h"
+
+namespace Mortevielle {
+class MortevielleEngine;
+
+class TextHandler {
+private:
+ MortevielleEngine *_vm;
+ int nextWord(int p, const char *ch, int &tab);
+public:
+ void setParent(MortevielleEngine *vm);
+ void displayStr(Common::String inputStr, int x, int y, int dx, int dy, int typ);
+ void loadPictureFile(Common::String filename, Common::String altFilename, int32 skipSize, int length);
+ void loadAniFile(Common::String filename, int32 skipSize, int length);
+ void taffich();
+};
+
+} // End of namespace Mortevielle
+#endif
diff --git a/engines/mortevielle/saveload.cpp b/engines/mortevielle/saveload.cpp
new file mode 100644
index 0000000000..77c242c9e7
--- /dev/null
+++ b/engines/mortevielle/saveload.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.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+#include "mortevielle/dialogs.h"
+#include "mortevielle/mouse.h"
+#include "mortevielle/saveload.h"
+
+#include "common/file.h"
+#include "common/system.h"
+
+namespace Mortevielle {
+
+static const char SAVEGAME_ID[4] = { 'M', 'O', 'R', 'T' };
+
+void SavegameManager::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+
+/**
+ * Handle saving or loading savegame data
+ */
+void SavegameManager::sync_save(Common::Serializer &sz) {
+ sz.syncAsSint16LE(g_vm->_saveStruct._faithScore);
+ for (int i = 0; i < 11; ++i)
+ sz.syncAsByte(g_vm->_saveStruct._pctHintFound[i]);
+ for (int i = 0; i < 43; ++i)
+ sz.syncAsByte(g_vm->_saveStruct._availableQuestion[i]);
+ for (int i = 0; i < 31; ++i)
+ sz.syncAsByte(g_vm->_saveStruct._inventory[i]);
+
+ sz.syncAsSint16LE(g_vm->_saveStruct._currPlace);
+ sz.syncAsSint16LE(g_vm->_saveStruct._atticBallHoleObjectId);
+ sz.syncAsSint16LE(g_vm->_saveStruct._atticRodHoleObjectId);
+ sz.syncAsSint16LE(g_vm->_saveStruct._cellarObjectId);
+ sz.syncAsSint16LE(g_vm->_saveStruct._secretPassageObjectId);
+ sz.syncAsSint16LE(g_vm->_saveStruct._wellObjectId);
+ sz.syncAsSint16LE(g_vm->_saveStruct._selectedObjectId);
+ sz.syncAsSint16LE(g_vm->_saveStruct._purpleRoomObjectId);
+ sz.syncAsSint16LE(g_vm->_saveStruct._cryptObjectId);
+ sz.syncAsByte(g_vm->_saveStruct._alreadyEnteredManor);
+ sz.syncAsByte(g_vm->_saveStruct._fullHour);
+
+ sz.syncBytes(_tabdonSaveBuffer, 391);
+}
+
+/**
+ * Inner code for loading a saved game
+ * @remarks Originally called 'takesav'
+ */
+void SavegameManager::loadSavegame(const Common::String &filename) {
+ // Try loading first from the save area
+ Common::SeekableReadStream *stream = g_system->getSavefileManager()->openForLoading(filename);
+
+ Common::File f;
+ if (stream == NULL) {
+ if (!f.open(filename))
+ error("Unable to open save file '%s'", filename.c_str());
+
+ stream = f.readStream(f.size());
+ f.close();
+ }
+
+ // Check whether it's a ScummVM saved game
+ char buffer[4];
+ stream->read(buffer, 4);
+ 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;
+ } else {
+ stream->seek(0);
+ }
+
+ // Read the game contents
+ Common::Serializer sz(stream, NULL);
+ sync_save(sz);
+
+ g_vm->_coreVar = g_vm->_saveStruct;
+ for (int i = 0; i <= 389; ++i)
+ g_vm->_tabdon[i + kAcha] = _tabdonSaveBuffer[i];
+
+ // Close the stream
+ delete stream;
+}
+
+/**
+ * Load a saved game
+ */
+Common::Error SavegameManager::loadGame(const Common::String &filename) {
+ g_vm->_mouse.hideMouse();
+ g_vm->displayEmptyHand();
+ loadSavegame(filename);
+
+ /* Initialization */
+ g_vm->charToHour();
+ g_vm->initGame();
+ g_vm->gameLoaded();
+ g_vm->_mouse.showMouse();
+ return Common::kNoError;
+}
+
+/**
+ * Save the game
+ */
+Common::Error SavegameManager::saveGame(int n, const Common::String &saveName) {
+ Common::OutSaveFile *f;
+ int i;
+
+ g_vm->_mouse.hideMouse();
+ g_vm->hourToChar();
+
+ for (i = 0; i <= 389; ++i)
+ _tabdonSaveBuffer[i] = g_vm->_tabdon[i + kAcha];
+ g_vm->_saveStruct = g_vm->_coreVar;
+ if (g_vm->_saveStruct._currPlace == ROOM26)
+ g_vm->_saveStruct._currPlace = LANDING;
+
+ Common::String filename = _vm->generateSaveFilename(n);
+ f = g_system->getSavefileManager()->openForSaving(filename);
+
+ // Write out the savegame header
+ f->write(&SAVEGAME_ID[0], 4);
+
+ // Write out the header
+ SavegameHeader header;
+ writeSavegameHeader(f, saveName);
+
+ // Write out the savegame contents
+ Common::Serializer sz(NULL, f);
+ sync_save(sz);
+
+ // Close the save file
+ f->finalize();
+ delete f;
+
+ // Skipped: dialog asking to swap floppy
+
+ g_vm->_mouse.showMouse();
+ return Common::kNoError;
+}
+
+Common::Error SavegameManager::loadGame(int slot) {
+ return loadGame(_vm->generateSaveFilename(slot));
+}
+
+Common::Error SavegameManager::saveGame(int slot) {
+ return saveGame(slot, _vm->generateSaveFilename(slot));
+}
+
+void SavegameManager::writeSavegameHeader(Common::OutSaveFile *out, const Common::String &saveName) {
+ // Write out a savegame header
+ out->writeByte(SAVEGAME_VERSION);
+
+ // Write savegame name
+ out->writeString(saveName);
+ out->writeByte(0);
+
+ // Get the active palette
+ uint8 thumbPalette[256 * 3];
+ g_system->getPaletteManager()->grabPalette(thumbPalette, 0, 256);
+
+ // Create a thumbnail and save it
+ Graphics::Surface *thumb = new Graphics::Surface();
+ Graphics::Surface s = g_vm->_screenSurface.lockArea(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+
+ ::createThumbnail(thumb, (const byte *)s.pixels, SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette);
+ Graphics::saveThumbnail(*out, *thumb);
+ thumb->free();
+ delete thumb;
+
+ // Write out the save date/time
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ out->writeSint16LE(td.tm_year + 1900);
+ out->writeSint16LE(td.tm_mon + 1);
+ out->writeSint16LE(td.tm_mday);
+ out->writeSint16LE(td.tm_hour);
+ out->writeSint16LE(td.tm_min);
+}
+
+bool SavegameManager::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) {
+ header.thumbnail = NULL;
+
+ // Get the savegame version
+ header.version = in->readByte();
+
+ // 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)
+ return false;
+
+ // Read in save date/time
+ header.saveYear = in->readSint16LE();
+ header.saveMonth = in->readSint16LE();
+ header.saveDay = in->readSint16LE();
+ header.saveHour = in->readSint16LE();
+ header.saveMinutes = in->readSint16LE();
+
+ return true;
+}
+
+SaveStateList SavegameManager::listSaves(const Common::String &target) {
+ Common::String pattern = 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) {
+ // Obtain the last 3 digits of the filename, since they correspond to the save slot
+ const Common::String &fname = *file;
+ int slotNumber = atoi(fname.c_str() + fname.size() - 3);
+
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(fname);
+ if (in) {
+ // There can be two types of savegames: original interpreter savegames, and ScummVM savegames.
+ // Original interpreter savegames are 497 bytes, and still need to be supported because the
+ // initial game state is stored as a savegame
+ bool validFlag = false;
+ Common::String saveDescription;
+
+ char buffer[4];
+ in->read(buffer, 4);
+ if (!strncmp(&buffer[0], &SAVEGAME_ID[0], 4)) {
+ // ScummVm savegame. Read in the header to get the savegame name
+ SavegameHeader header;
+ validFlag = readSavegameHeader(in, header);
+
+ if (validFlag) {
+ delete header.thumbnail;
+ saveDescription = header.saveName;
+ }
+ } else if (file->size() == 497) {
+ // Form an appropriate savegame name
+ saveDescription = (slotNumber == 0) ? "Initial game state" :
+ Common::String::format("Savegame #%d", slotNumber);
+ validFlag = true;
+ }
+
+ if (validFlag)
+ // Got a valid savegame
+ saveList.push_back(SaveStateDescriptor(slotNumber, saveDescription));
+
+ delete in;
+ }
+ }
+
+ return saveList;
+}
+
+SaveStateDescriptor SavegameManager::querySaveMetaInfos(const Common::String &fileName) {
+ Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName);
+
+ if (f) {
+ // Get the slot number
+ int slot = 1;
+ if (fileName.size() > 4 && fileName[fileName.size() - 4] == '.')
+ slot = atoi(fileName.c_str() + fileName.size() - 3);
+
+ // Check to see if it's a ScummVM savegame or not
+ char buffer[4];
+ f->read(buffer, 4);
+
+ bool hasHeader = !strncmp(&buffer[0], &SAVEGAME_ID[0], 4);
+
+ if (!hasHeader) {
+ // Original savegame perhaps?
+ delete f;
+
+ SaveStateDescriptor desc(slot, Common::String::format("Savegame - %03d", slot));
+ desc.setDeletableFlag(slot != 0);
+ desc.setWriteProtectedFlag(slot == 0);
+ return desc;
+ } else {
+ // Get the savegame header information
+ SavegameHeader header;
+ readSavegameHeader(f, header);
+ delete f;
+
+ // Create the return descriptor
+ SaveStateDescriptor desc(slot, header.saveName);
+ desc.setDeletableFlag(true);
+ desc.setWriteProtectedFlag(false);
+ desc.setThumbnail(header.thumbnail);
+ desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
+ desc.setSaveTime(header.saveHour, header.saveMinutes);
+
+ return desc;
+ }
+ }
+
+ return SaveStateDescriptor();
+}
+
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/saveload.h b/engines/mortevielle/saveload.h
new file mode 100644
index 0000000000..0121a04d8e
--- /dev/null
+++ b/engines/mortevielle/saveload.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.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#ifndef MORTEVIELLE_SAVELOAD_H
+#define MORTEVIELLE_SAVELOAD_H
+
+#include "common/savefile.h"
+#include "common/serializer.h"
+#include "graphics/palette.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
+
+#define SAVEGAME_VERSION 1
+
+namespace Mortevielle {
+
+struct SavegameHeader {
+ uint8 version;
+ Common::String saveName;
+ Graphics::Surface *thumbnail;
+ int saveYear, saveMonth, saveDay;
+ int saveHour, saveMinutes;
+ int totalFrames;
+};
+
+class MortevielleEngine;
+
+class SavegameManager {
+private:
+ MortevielleEngine *_vm;
+ byte _tabdonSaveBuffer[391];
+
+ void sync_save(Common::Serializer &sz);
+public:
+ void setParent(MortevielleEngine *vm);
+ void loadSavegame(const Common::String &filename);
+ Common::Error loadGame(const Common::String &filename);
+ Common::Error saveGame(int n, const Common::String &saveName);
+ Common::Error loadGame(int slot);
+ Common::Error saveGame(int slot);
+
+ void writeSavegameHeader(Common::OutSaveFile *out, const Common::String &saveName);
+ static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header);
+ static SaveStateList listSaves(const Common::String &target);
+ static SaveStateDescriptor querySaveMetaInfos(const Common::String &fileName);
+};
+
+} // End of namespace Mortevielle
+#endif
diff --git a/engines/mortevielle/sound.cpp b/engines/mortevielle/sound.cpp
new file mode 100644
index 0000000000..f9b53ffed7
--- /dev/null
+++ b/engines/mortevielle/sound.cpp
@@ -0,0 +1,205 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+#include "mortevielle/sound.h"
+
+#include "common/scummsys.h"
+
+namespace Mortevielle {
+
+/**
+ * Constructor
+ */
+PCSpeaker::PCSpeaker(int rate) {
+ _rate = rate;
+ _oscLength = 0;
+ _oscSamples = 0;
+ _remainingSamples = 0;
+ _volume = 255;
+}
+
+/**
+ * Destructor
+ */
+PCSpeaker::~PCSpeaker() {
+}
+
+/**
+ * Adds a new note to the queue of notes to be played.
+ */
+void PCSpeaker::play(int freq, uint32 length) {
+ assert((freq > 0) && (length > 0));
+ Common::StackLock lock(_mutex);
+
+ _pendingNotes.push(SpeakerNote(freq, length));
+}
+
+/**
+ * Stops the currently playing song
+ */
+void PCSpeaker::stop() {
+ Common::StackLock lock(_mutex);
+
+ _remainingSamples = 0;
+ _pendingNotes.clear();
+}
+
+void PCSpeaker::setVolume(byte volume) {
+ _volume = volume;
+}
+
+/**
+ * Return true if a song is currently playing
+ */
+bool PCSpeaker::isPlaying() const {
+ return !_pendingNotes.empty() || (_remainingSamples != 0);
+}
+
+/**
+ * Method used by the mixer to pull off pending samples to play
+ */
+int PCSpeaker::readBuffer(int16 *buffer, const int numSamples) {
+ Common::StackLock lock(_mutex);
+
+ int i;
+
+ for (i = 0; (_remainingSamples || !_pendingNotes.empty()) && (i < numSamples); ++i) {
+ if (!_remainingSamples)
+ // Used up the current note, so queue the next one
+ dequeueNote();
+
+ buffer[i] = generateSquare(_oscSamples, _oscLength) * _volume;
+ if (_oscSamples++ >= _oscLength)
+ _oscSamples = 0;
+
+ _remainingSamples--;
+ }
+
+ // Clear the rest of the buffer
+ if (i < numSamples)
+ memset(buffer + i, 0, (numSamples - i) * sizeof(int16));
+
+ return numSamples;
+}
+
+/**
+ * Dequeues a note from the pending note list
+ */
+void PCSpeaker::dequeueNote() {
+ SpeakerNote note = _pendingNotes.pop();
+
+ _oscLength = _rate / note.freq;
+ _oscSamples = 0;
+ _remainingSamples = (_rate * note.length) / 1000000;
+ assert((_oscLength > 0) && (_remainingSamples > 0));
+}
+
+/**
+ * Support method for generating a square wave
+ */
+int8 PCSpeaker::generateSquare(uint32 x, uint32 oscLength) {
+ return (x < (oscLength / 2)) ? 127 : -128;
+}
+
+/*-------------------------------------------------------------------------*/
+
+const int tab[16] = { -96, -72, -48, -32, -20, -12, -8, -4, 0, 4, 8, 12, 20, 32, 48, 72 };
+
+// The PC timer chip works at a frequency of 1.19318Mhz
+#define TIMER_FREQUENCY 1193180
+
+SoundManager::SoundManager(Audio::Mixer *mixer) {
+ _mixer = mixer;
+ _speakerStream = new PCSpeaker(mixer->getOutputRate());
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
+ _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+}
+
+SoundManager::~SoundManager() {
+ _mixer->stopHandle(_speakerHandle);
+ delete _speakerStream;
+
+}
+
+/**
+ * Decode music data
+ */
+void SoundManager::decodeMusic(const byte *PSrc, byte *PDest, int NbreSeg) {
+ int seed = 128;
+ int v;
+
+ for (int idx1 = 0; idx1 < (NbreSeg * 2); ++idx1) {
+ for (int idx2 = 0; idx2 < 64; ++idx2) {
+ byte srcByte = *PSrc++;
+ v = tab[srcByte >> 4];
+ seed += v;
+ *PDest++ = seed & 0xff;
+
+ v = tab[srcByte & 0xf];
+ seed += v;
+ *PDest++ = seed & 0xff;
+ }
+ }
+}
+
+void SoundManager::litph(tablint &t, int typ, int tempo) {
+ return;
+}
+
+void SoundManager::playNote(int frequency, int32 length) {
+ _speakerStream->play(frequency, length);
+}
+
+
+void SoundManager::musyc(tablint &tb, int nbseg, int att) {
+#ifdef DEBUG
+ const byte *pSrc = &_vm->_mem[kAdrMusic * 16];
+
+ // Convert the countdown amount to a tempo rate, and then to note length in microseconds
+ int tempo = TIMER_FREQUENCY / att;
+ int length = 1000000 / tempo;
+
+ for (int noteIndex = 0; noteIndex < (nbseg * 16); ++noteIndex) {
+ int lookupValue = *pSrc++;
+ int noteCountdown = tb[lookupValue];
+ int noteFrequency = TIMER_FREQUENCY / noteCountdown;
+
+ playNote(noteFrequency, length);
+ }
+
+ // Keep waiting until the song has been finished
+ while (_speakerStream->isPlaying() && !_vm->shouldQuit()) {
+ _vm->delay(10);
+ }
+#endif
+}
+
+void SoundManager::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/sound.h b/engines/mortevielle/sound.h
new file mode 100644
index 0000000000..a47e8db32e
--- /dev/null
+++ b/engines/mortevielle/sound.h
@@ -0,0 +1,115 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#ifndef MORTEVIELLE_SOUND_H
+#define MORTEVIELLE_SOUND_H
+
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "common/mutex.h"
+#include "common/queue.h"
+
+namespace Mortevielle {
+class MortevielleEngine;
+
+typedef int tablint[256];
+
+/**
+ * Structure used to store pending notes to play
+ */
+struct SpeakerNote {
+ int freq;
+ uint32 length;
+
+ SpeakerNote(int noteFreq, uint32 noteLength) {
+ freq = noteFreq;
+ length = noteLength;
+ }
+};
+
+/**
+ * This is a modified PC Speaker class that allows the queueing of an entire song
+ * sequence one note at a time.
+ */
+class PCSpeaker : public Audio::AudioStream {
+private:
+ Common::Queue<SpeakerNote> _pendingNotes;
+ Common::Mutex _mutex;
+
+ int _rate;
+ uint32 _oscLength;
+ uint32 _oscSamples;
+ uint32 _remainingSamples;
+ uint32 _mixedSamples;
+ byte _volume;
+
+ void dequeueNote();
+protected:
+ static int8 generateSquare(uint32 x, uint32 oscLength);
+public:
+ PCSpeaker(int rate = 44100);
+ ~PCSpeaker();
+
+ /** Play a note for length microseconds.
+ */
+ void play(int freq, uint32 length);
+ /** Stop the currently playing sequence */
+ void stop();
+ /** Adjust the volume. */
+ void setVolume(byte volume);
+
+ bool isPlaying() const;
+
+ int readBuffer(int16 *buffer, const int numSamples);
+
+ bool isStereo() const { return false; }
+ bool endOfData() const { return false; }
+ bool endOfStream() const { return false; }
+ int getRate() const { return _rate; }
+};
+
+class SoundManager {
+private:
+ MortevielleEngine *_vm;
+ Audio::Mixer *_mixer;
+ PCSpeaker *_speakerStream;
+ Audio::SoundHandle _speakerHandle;
+public:
+ SoundManager(Audio::Mixer *mixer);
+ ~SoundManager();
+
+ void setParent(MortevielleEngine *vm);
+ void playNote(int frequency, int32 length);
+
+ void decodeMusic(const byte *PSrc, byte *PDest, int NbreSeg);
+ void litph(tablint &t, int typ, int tempo);
+ void musyc(tablint &tb, int nbseg, int att);
+};
+
+} // End of namespace Mortevielle
+
+#endif
diff --git a/engines/mortevielle/speech.cpp b/engines/mortevielle/speech.cpp
new file mode 100644
index 0000000000..68ae3dac3e
--- /dev/null
+++ b/engines/mortevielle/speech.cpp
@@ -0,0 +1,611 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+
+#include "mortevielle/speech.h"
+#include "mortevielle/sound.h"
+
+#include "common/endian.h"
+#include "common/file.h"
+
+namespace Mortevielle {
+
+const byte _tnocon[364] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const byte _intcon[26] = {1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0};
+const byte _typcon[26] = {0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3};
+const byte _tabdph[16] = {0, 10, 2, 0, 2, 10, 3, 0, 3, 7, 5, 0, 6, 7, 7, 10};
+const byte _tabdbc[18] = {7, 23, 7, 14, 13, 9, 14, 9, 5, 12, 6, 12, 13, 4, 0, 4, 5, 9};
+
+SpeechManager::SpeechManager() {
+ _typlec = 0;
+ _phonemeNumb = 0;
+
+ for (int i = 0; i < 3; i++) {
+ _queue[i]._val = 0;
+ _queue[i]._code = 0;
+ _queue[i]._acc = 0;
+ _queue[i]._freq = 0;
+ _queue[i]._rep = 0;
+ }
+ _noise5Buf = nullptr;
+}
+
+SpeechManager::~SpeechManager() {
+ free(_noise5Buf);
+}
+
+void SpeechManager::spfrac(int wor) {
+ _queue[2]._rep = (uint)wor >> 12;
+ if ((_typlec == 0) && (_queue[2]._code != 9))
+ if (((_queue[2]._code > 4) && (_queue[2]._val != 20) && (_queue[2]._rep != 3) && (_queue[2]._rep != 6) && (_queue[2]._rep != 9)) ||
+ ((_queue[2]._code < 5) && ((_queue[2]._val != 19) && (_queue[2]._val != 22) && (_queue[2]._rep != 4) && (_queue[2]._rep != 9)))) {
+ ++_queue[2]._rep;
+ }
+
+ _queue[2]._freq = ((uint)wor >> 6) & 7;
+ _queue[2]._acc = ((uint)wor >> 9) & 7;
+}
+
+void SpeechManager::charg_car(int &currWordNumb) {
+ int wor = READ_BE_UINT16(&_vm->_mem[(kAdrWord * 16) + currWordNumb]);
+ int int_ = wor & 0x3f; // 63
+
+ if ((int_ >= 0) && (int_ <= 13)) {
+ _queue[2]._val = int_;
+ _queue[2]._code = 5;
+ } else if ((int_ >= 14) && (int_ <= 21)) {
+ _queue[2]._val = int_;
+ _queue[2]._code = 6;
+ } else if ((int_ >= 22) && (int_ <= 47)) {
+ int_ = int_ - 22;
+ _queue[2]._val = int_;
+ _queue[2]._code = _typcon[int_];
+ } else if ((int_ >= 48) && (int_ <= 56)) {
+ _queue[2]._val = int_ - 22;
+ _queue[2]._code = 4;
+ } else {
+ switch (int_) {
+ case 60:
+ _queue[2]._val = 32; /* " " */
+ _queue[2]._code = 9;
+ break;
+ case 61:
+ _queue[2]._val = 46; /* "." */
+ _queue[2]._code = 9;
+ break;
+ case 62:
+ _queue[2]._val = 35; /* "#" */
+ _queue[2]._code = 9;
+ default:
+ break;
+ }
+ }
+
+ spfrac(wor);
+ currWordNumb += 2;
+}
+
+
+void SpeechManager::entroct(byte o) {
+ _vm->_mem[(kAdrTroct * 16) + _ptr_oct] = o;
+ ++_ptr_oct;
+}
+
+void SpeechManager::veracf(byte b) {
+ ;
+}
+
+void SpeechManager::cctable(tablint &t) {
+ float tb[257];
+
+ tb[0] = 0;
+ for (int k = 0; k <= 255; ++k) {
+ tb[k + 1] = _vm->_addFix + tb[k];
+ t[255 - k] = abs((int)tb[k] + 1);
+ }
+}
+
+void SpeechManager::regenbruit() {
+ int i = kOffsetB3 + 8590;
+ int j = 0;
+ do {
+ _cfiphBuffer[j] = READ_BE_UINT16(&_vm->_mem[(kAdrNoise3 * 16) + i]);
+ i += 2;
+ ++j;
+ } while (i < kOffsetB3 + 8790);
+}
+
+/**
+ * Load sonmus.mor file
+ * @remarks Originally called 'charge_son'
+ */
+void SpeechManager::loadMusicSound() {
+ Common::File f;
+ if (!f.open("sonmus.mor"))
+ error("Missing file - sonmus.mor");
+
+ free(_vm->_compMusicBuf1);
+ int size = f.size();
+ _vm->_compMusicBuf1 = (byte *)malloc(sizeof(byte) * size);
+ f.read(_vm->_compMusicBuf1, size);
+
+ _vm->_soundManager.decodeMusic(_vm->_compMusicBuf1, &_vm->_mem[kAdrNoise * 16], size / 128);
+ f.close();
+}
+
+/**
+ * Load phoneme sound file
+ * @remarks Originally called 'charge_phbruit'
+ */
+void SpeechManager::loadPhonemeSounds() {
+ Common::File f;
+
+ if (!f.open("phbrui.mor"))
+ error("Missing file - phbrui.mor");
+
+ for (int i = 1; i <= f.size() / 2; ++i)
+ _cfiphBuffer[i] = f.readUint16BE();
+
+ f.close();
+}
+
+/**
+ * Speech function - Load Noise file
+ * @remarks Originally called 'charge_bruit'
+ */
+void SpeechManager::loadNoise() {
+ Common::File f;
+
+ if (!f.open("bruits")) //Translation: "noise"
+ error("Missing file - bruits");
+
+ f.read(&_vm->_mem[kAdrNoise * 16], 250 * 128); // 32000
+ for (int i = 0; i < _noise5Size; ++i)
+ _vm->_mem[(kAdrNoise * 16) + 32000 + i] = _noise5Buf[i];
+ f.read(&_vm->_mem[(kAdrNoise1 * 16) + kOffsetB1], 149 * 128); // 19072
+
+ f.close();
+}
+
+void SpeechManager::trait_car() {
+ byte d3;
+ int d2, i;
+
+ switch (_queue[1]._code) {
+ case 9:
+ if (_queue[1]._val != (int)'#')
+ for (i = 0; i <= _queue[1]._rep; ++i)
+ entroct(_queue[1]._val);
+ break;
+ case 5:
+ case 6:
+ if (_queue[1]._code == 6)
+ d3 = _tabdph[(_queue[1]._val - 14) << 1];
+ else
+ d3 = kNullValue;
+ if (_queue[0]._code >= 5) {
+ veracf(_queue[1]._acc);
+ if (_queue[0]._code == 9) {
+ entroct(4);
+ if (d3 == kNullValue)
+ entroct(_queue[1]._val);
+ else
+ entroct(d3);
+ entroct(22);
+ }
+ }
+
+ switch (_queue[1]._rep) {
+ case 0:
+ entroct(0);
+ entroct(_queue[1]._val);
+ if (d3 == kNullValue)
+ if (_queue[2]._code == 9)
+ entroct(2);
+ else
+ entroct(4);
+ else if (_queue[2]._code == 9)
+ entroct(0);
+ else
+ entroct(1);
+ break;
+ case 4:
+ case 5:
+ case 6:
+ if (_queue[1]._rep != 4) {
+ i = _queue[1]._rep - 5;
+ do {
+ --i;
+ entroct(0);
+ if (d3 == kNullValue)
+ entroct(_queue[1]._val);
+ else
+ entroct(d3);
+ entroct(3);
+ } while (i >= 0);
+ }
+ if (d3 == kNullValue) {
+ entroct(4);
+ entroct(_queue[1]._val);
+ entroct(0);
+ } else {
+ entroct(0);
+ entroct(_queue[1]._val);
+ entroct(3);
+ }
+ break;
+ case 7:
+ case 8:
+ case 9:
+ if (_queue[1]._rep != 7) {
+ i = _queue[1]._rep - 8;
+ do {
+ --i;
+ entroct(0);
+ if (d3 == kNullValue)
+ entroct(_queue[1]._val);
+ else
+ entroct(d3);
+ entroct(3);
+ } while (i >= 0);
+ }
+ if (d3 == kNullValue) {
+ entroct(0);
+ entroct(_queue[1]._val);
+ entroct(2);
+ } else {
+ entroct(0);
+ entroct(_queue[1]._val);
+ entroct(0);
+ }
+ break;
+ case 1:
+ case 2:
+ case 3:
+ if (_queue[1]._rep != 1) {
+ i = _queue[1]._rep - 2;
+ do {
+ --i;
+ entroct(0);
+ if (d3 == kNullValue)
+ entroct(_queue[1]._val);
+ else
+ entroct(d3);
+ entroct(3);
+ } while (i >= 0);
+ }
+ entroct(0);
+ entroct(_queue[1]._val);
+ if (_queue[2]._code == 9)
+ entroct(0);
+ else
+ entroct(1);
+ break;
+ default:
+ break;
+ } // switch c2.rep
+ break;
+
+ case 2:
+ case 3:
+ d3 = _queue[1]._code + 5; // 7 ou 8 => Corresponding vowel
+ if (_queue[0]._code > 4) {
+ veracf(_queue[1]._acc);
+ if (_queue[0]._code == 9) {
+ entroct(4);
+ entroct(d3);
+ entroct(22);
+ }
+ }
+ i = _queue[1]._rep;
+ assert(i >= 0);
+ if (i != 0) {
+ do {
+ --i;
+ entroct(0);
+ entroct(d3);
+ entroct(3);
+ } while (i > 0);
+ }
+ veracf(_queue[2]._acc);
+ if (_queue[2]._code == 6) {
+ entroct(4);
+ entroct(_tabdph[(_queue[2]._val - 14) << 1]);
+ entroct(_queue[1]._val);
+ } else {
+ entroct(4);
+ if (_queue[2]._val == 4)
+ entroct(3);
+ else
+ entroct(_queue[2]._val);
+ entroct(_queue[1]._val);
+ }
+ break;
+ case 0:
+ case 1:
+ veracf(_queue[1]._acc);
+ switch (_queue[2]._code) {
+ case 2:
+ d2 = 7;
+ break;
+ case 3:
+ d2 = 8;
+ break;
+ case 6:
+ d2 = _tabdph[(_queue[2]._val - 14) << 1];
+ break;
+ case 5:
+ d2 = _queue[2]._val;
+ break;
+ default:
+ d2 = 10;
+ break;
+ } // switch c3._code
+ d2 = (d2 * 26) + _queue[1]._val;
+ if (_tnocon[d2] == 0)
+ d3 = 2;
+ else
+ d3 = 6;
+ if (_queue[1]._rep >= 5) {
+ _queue[1]._rep -= 5;
+ d3 = 8 - d3; // Swap 2 and 6
+ }
+ if (_queue[1]._code == 0) {
+ i = _queue[1]._rep;
+ if (i != 0) {
+ do {
+ --i;
+ entroct(d3);
+ entroct(_queue[1]._val);
+ entroct(3);
+ } while (i > 0);
+ }
+ entroct(d3);
+ entroct(_queue[1]._val);
+ entroct(4);
+ } else {
+ entroct(d3);
+ entroct(_queue[1]._val);
+ entroct(3);
+ i = _queue[1]._rep;
+ if (i != 0) {
+ do {
+ --i;
+ entroct(d3);
+ entroct(_queue[1]._val);
+ entroct(4);
+ } while (i > 0);
+ }
+ }
+ if (_queue[2]._code == 9) {
+ entroct(d3);
+ entroct(_queue[1]._val);
+ entroct(5);
+ } else if ((_queue[2]._code != 0) && (_queue[2]._code != 1) && (_queue[2]._code != 4)) {
+ veracf(_queue[2]._acc);
+ switch (_queue[2]._code) {
+ case 3:
+ d2 = 8;
+ break;
+ case 6:
+ d2 = _tabdph[(_queue[2]._val - 14) << 1];
+ break;
+ case 5:
+ d2 = _queue[2]._val;
+ break;
+ default:
+ d2 = 7;
+ break;
+ } // switch c3._code
+ if (d2 == 4)
+ d2 = 3;
+
+ if (_intcon[_queue[1]._val] != 0)
+ ++_queue[1]._val;
+
+ if ((_queue[1]._val == 17) || (_queue[1]._val == 18))
+ _queue[1]._val = 16;
+
+ entroct(4);
+ entroct(d2);
+ entroct(_queue[1]._val);
+ }
+
+ break;
+ case 4:
+ veracf(_queue[1]._acc);
+ i = _queue[1]._rep;
+ if (i != 0) {
+ do {
+ --i;
+ entroct(2);
+ entroct(_queue[1]._val);
+ entroct(3);
+ } while (i > 0);
+ }
+ entroct(2);
+ entroct(_queue[1]._val);
+ entroct(4);
+ if (_queue[2]._code == 9) {
+ entroct(2);
+ entroct(_queue[1]._val);
+ entroct(5);
+ } else if ((_queue[2]._code != 0) && (_queue[2]._code != 1) && (_queue[2]._code != 4)) {
+ veracf(_queue[2]._acc);
+ switch (_queue[2]._code) {
+ case 3:
+ d2 = 8;
+ break;
+ case 6:
+ d2 = _tabdph[(_queue[2]._val - 14) << 1];
+ break;
+ case 5:
+ d2 = _queue[2]._val;
+ break;
+ default:
+ d2 = 7;
+ break;
+ } // switch c3._code
+
+ if (d2 == 4)
+ d2 = 3;
+
+ if (_intcon[_queue[1]._val] != 0)
+ ++_queue[1]._val;
+
+ entroct(4);
+ entroct(d2);
+ entroct(_tabdbc[((_queue[1]._val - 26) << 1) + 1]);
+ }
+
+ break;
+ default:
+ break;
+ } // switch c2.code
+}
+
+/**
+ * Make the queue evolve by 1 value
+ * @remarks Originally called 'rot_chariot'
+ */
+void SpeechManager::moveQueue() {
+ _queue[0] = _queue[1];
+ _queue[1] = _queue[2];
+ _queue[2]._val = 32;
+ _queue[2]._code = 9;
+}
+
+/**
+ * initialize the queue
+ * @remarks Originally called 'init_chariot'
+ */
+void SpeechManager::initQueue() {
+ _queue[2]._rep = 0;
+ _queue[2]._freq = 0;
+ _queue[2]._acc = 0;
+ moveQueue();
+ moveQueue();
+}
+
+/**
+ * Handle a phoneme
+ * @remarks Originally called 'trait_ph'
+ */
+void SpeechManager::handlePhoneme() {
+ const uint16 deca[3] = {300, 30, 40};
+
+ uint16 startPos = _cfiphBuffer[_phonemeNumb - 1] + deca[_typlec];
+ uint16 endPos = _cfiphBuffer[_phonemeNumb] + deca[_typlec];
+ int wordCount = endPos - startPos;
+
+ startPos /= 2;
+ endPos /= 2;
+ for (int i = startPos, currWord = 0; i < endPos; i++, currWord += 2)
+ WRITE_BE_UINT16(&_vm->_mem[(kAdrWord * 16) + currWord], _cfiphBuffer[i]);
+
+ _ptr_oct = 0;
+ int currWord = 0;
+ initQueue();
+
+ do {
+ moveQueue();
+ charg_car(currWord);
+ trait_car();
+ } while (currWord < wordCount);
+
+ moveQueue();
+ trait_car();
+ entroct((int)'#');
+}
+
+/**
+ * Start speech
+ * @remarks Originally called 'parole'
+ */
+void SpeechManager::startSpeech(int rep, int ht, int typ) {
+ uint16 savph[501];
+ int tempo;
+
+ if (_vm->_soundOff)
+ return;
+
+ _phonemeNumb = rep;
+ int haut = ht;
+ _typlec = typ;
+ if (_typlec != 0) {
+ for (int i = 0; i <= 500; ++i)
+ savph[i] = _cfiphBuffer[i];
+ tempo = kTempoNoise;
+ } else if (haut > 5)
+ tempo = kTempoF;
+ else
+ tempo = kTempoM;
+ _vm->_addFix = (float)((tempo - 8)) / 256;
+ cctable(_tbi);
+ switch (typ) {
+ case 1:
+ loadNoise();
+ regenbruit();
+ break;
+ case 2:
+ loadMusicSound();
+ loadPhonemeSounds();
+ break;
+ default:
+ break;
+ }
+ handlePhoneme();
+ _vm->_soundManager.litph(_tbi, typ, tempo);
+ if (_typlec != 0)
+ for (int i = 0; i <= 500; ++i) {
+ _cfiphBuffer[i] = savph[i];
+ _mlec = _typlec;
+ }
+ _vm->setPal(_vm->_numpal);
+}
+
+void SpeechManager::setParent(MortevielleEngine *vm) {
+ _vm = vm;
+}
+} // End of namespace Mortevielle
diff --git a/engines/mortevielle/speech.h b/engines/mortevielle/speech.h
new file mode 100644
index 0000000000..c3c4c32942
--- /dev/null
+++ b/engines/mortevielle/speech.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.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#ifndef MORTEVIELLE_SPEECH_H
+#define MORTEVIELLE_SPEECH_H
+
+#include "mortevielle/sound.h"
+
+#include "common/scummsys.h"
+
+namespace Mortevielle {
+
+const int kAdrNoise = 0x5cb0;/*2C00;*/
+const int kAdrNoise1 = 0x6924;
+const int kAdrNoise3 = 0x6ba6;/*3AF6;*/
+const int kAdrTroct = 0x406b;
+const int kAdrWord = 0x4000;
+const int kOffsetB1 = 6;
+const int kOffsetB3 = 6;
+
+const float kfreq0 = 1.19318e6;
+const int kNullValue = 255;
+const int kTempoMusic = 71;
+const int kTempoNoise = 78;
+const int kTempoF = 80;
+const int kTempoM = 89;
+
+// Useless constants
+//const int segdon = 0x6c00;
+//const int adbruit2 = 0x6b30;/*3A80;*/
+//const int adson2 = 0x60b0;/*3000;*/
+//const int seg_syst = 0x6fed;
+//const int offsetb2 = 4;
+
+struct SpeechQueue {
+ int _val;
+ int _code;
+ int _acc;
+ int _freq;
+ int _rep;
+};
+
+class SpeechManager {
+private:
+ MortevielleEngine *_vm;
+
+ int _typlec;
+ int _phonemeNumb;
+
+ SpeechQueue _queue[3];
+ int _ptr_oct;
+
+public:
+ uint16 *_cfiphBuffer;
+ int _tbi[256];
+ int _mlec;
+ byte *_noise5Buf;
+ int _noise5Size;
+
+ SpeechManager();
+ ~SpeechManager();
+ void setParent(MortevielleEngine *vm);
+ void spfrac(int wor);
+ void charg_car(int &currWordNumb);
+ void entroct(byte o);
+ void veracf(byte b);
+ void cctable(tablint &t);
+ void regenbruit();
+ void loadMusicSound();
+ void loadPhonemeSounds();
+ void loadNoise();
+ void trait_car();
+
+ void moveQueue();
+ void initQueue();
+ void handlePhoneme();
+ void startSpeech(int rep, int ht, int typ);
+};
+
+} // End of namespace Mortevielle
+
+#endif
diff --git a/engines/mortevielle/utils.cpp b/engines/mortevielle/utils.cpp
new file mode 100644
index 0000000000..8fa608953d
--- /dev/null
+++ b/engines/mortevielle/utils.cpp
@@ -0,0 +1,3497 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This code is based on original Mortville Manor DOS source code
+ * Copyright (c) 1987-1989 Lankhor
+ */
+
+#include "mortevielle/mortevielle.h"
+
+#include "mortevielle/dialogs.h"
+#include "mortevielle/menu.h"
+#include "mortevielle/mouse.h"
+#include "mortevielle/outtext.h"
+#include "mortevielle/speech.h"
+
+#include "common/scummsys.h"
+#include "graphics/cursorman.h"
+
+namespace Mortevielle {
+
+/**
+ * Check is a key was pressed
+ * It also delays the engine and check if the screen has to be updated
+ * @remarks Originally called 'keypressed'
+ */
+bool MortevielleEngine::keyPressed() {
+ // Check for any pending key presses
+ handleEvents();
+
+ // Check if it's time to draw the next frame
+ if (g_system->getMillis() > (_lastGameFrame + GAME_FRAME_DELAY)) {
+ _lastGameFrame = g_system->getMillis();
+
+ _screenSurface.updateScreen();
+
+ _debugger.onFrame();
+ }
+
+ // Delay briefly to keep CPU usage down
+ g_system->delayMillis(5);
+
+ // Return if there are any pending key presses
+ return !_keypresses.empty();
+}
+
+/**
+ * Wait for a keypress
+ * @remarks Originally called 'get_ch'
+ */
+int MortevielleEngine::getChar() {
+ // If there isn't any pending keypress, wait until there is
+ while (!shouldQuit() && _keypresses.empty()) {
+ keyPressed();
+ }
+
+ // Return the top keypress
+ return shouldQuit() ? 0 : _keypresses.pop();
+}
+
+/**
+ * Handle pending events
+ * @remarks Since the ScummVM screen surface is double height to handle 640x200 using 640x400,
+ * the mouse Y position is divided by 2 to keep the game thinking the Y goes from 0 - 199
+ */
+bool MortevielleEngine::handleEvents() {
+ Common::Event event;
+ if (!g_system->getEventManager()->pollEvent(event))
+ return false;
+
+ switch (event.type) {
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_MOUSEMOVE:
+ _mousePos = Common::Point(event.mouse.x, event.mouse.y / 2);
+ _mouse._pos.x = event.mouse.x;
+ _mouse._pos.y = event.mouse.y / 2;
+
+ if (event.type == Common::EVENT_LBUTTONDOWN)
+ _mouseClick = true;
+ else if (event.type == Common::EVENT_LBUTTONUP)
+ _mouseClick = false;
+
+ break;
+ case Common::EVENT_KEYDOWN:
+ addKeypress(event);
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+/**
+ * Add the specified key to the pending keypress stack
+ */
+void MortevielleEngine::addKeypress(Common::Event &evt) {
+ // Character to add
+ char ch = evt.kbd.ascii;
+
+ // Check for debugger
+ if ((evt.kbd.keycode == Common::KEYCODE_d) && (evt.kbd.flags & Common::KBD_CTRL)) {
+ // Attach to the debugger
+ _debugger.attach();
+ _debugger.onFrame();
+ } else if ((evt.kbd.keycode >= Common::KEYCODE_a) && (evt.kbd.keycode <= Common::KEYCODE_z)) {
+ // Handle alphabetic keys
+ if (evt.kbd.hasFlags(Common::KBD_CTRL))
+ ch = evt.kbd.keycode - Common::KEYCODE_a + 1;
+ else
+ ch = evt.kbd.keycode - Common::KEYCODE_a + 'A';
+ } else if ((evt.kbd.keycode >= Common::KEYCODE_F1) && (evt.kbd.keycode <= Common::KEYCODE_F12)) {
+ // Handle function keys
+ ch = 59 + evt.kbd.keycode - Common::KEYCODE_F1;
+ } else {
+ // Series of special cases
+ switch (evt.kbd.keycode) {
+ case Common::KEYCODE_KP4:
+ case Common::KEYCODE_LEFT:
+ ch = '4';
+ break;
+ case Common::KEYCODE_KP2:
+ case Common::KEYCODE_DOWN:
+ ch = '2';
+ break;
+ case Common::KEYCODE_KP6:
+ case Common::KEYCODE_RIGHT:
+ ch = '6';
+ break;
+ case Common::KEYCODE_KP8:
+ case Common::KEYCODE_UP:
+ ch = '8';
+ break;
+ case Common::KEYCODE_KP7:
+ ch = '7';
+ break;
+ case Common::KEYCODE_KP1:
+ ch = '1';
+ break;
+ case Common::KEYCODE_KP9:
+ ch = '9';
+ break;
+ case Common::KEYCODE_KP3:
+ ch = '3';
+ break;
+ case Common::KEYCODE_KP5:
+ ch = '5';
+ break;
+ case Common::KEYCODE_RETURN:
+ ch = '\13';
+ break;
+ case Common::KEYCODE_ESCAPE:
+ ch = '\33';
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (ch != 0)
+ _keypresses.push(ch);
+}
+
+
+static const byte CURSOR_ARROW_DATA[16 * 16] = {
+ 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x0f, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+/**
+ * Initialize the mouse
+ */
+void MortevielleEngine::initMouse() {
+ CursorMan.replaceCursor(CURSOR_ARROW_DATA, 16, 16, 0, 0, 0xff);
+ CursorMan.showMouse(true);
+
+ _mouse.initMouse();
+}
+
+/**
+ * Sets the mouse position
+ * @remarks Since the ScummVM screen surface is double height to handle 640x200 using 640x400,
+ * the mouse Y position is doubled to convert from 0-199 to 0-399
+ */
+void MortevielleEngine::setMousePos(const Common::Point &pt) {
+ // Adjust the passed position from simulated 640x200 to 640x400 co-ordinates
+ Common::Point newPoint(pt.x, (pt.y == 199) ? 399 : pt.y * 2);
+
+ if (newPoint != _mousePos)
+ // Warp the mouse to the new position
+ g_system->warpMouse(newPoint.x, newPoint.y);
+
+ // Save the new position
+ _mousePos = newPoint;
+}
+
+/**
+ * Delay by a given amount
+ */
+void MortevielleEngine::delay(int amount) {
+ uint32 endTime = g_system->getMillis() + amount;
+
+ while (g_system->getMillis() < endTime) {
+ if (g_system->getMillis() > (_lastGameFrame + GAME_FRAME_DELAY)) {
+ _lastGameFrame = g_system->getMillis();
+ _screenSurface.updateScreen();
+
+ _debugger.onFrame();
+ }
+
+ g_system->delayMillis(10);
+ }
+}
+
+/**
+ * Waits for the user to select an action, and then handles it
+ * @remarks Originally called tecran
+ */
+void MortevielleEngine::handleAction() {
+ const int lim = 20000;
+ int temps = 0;
+ char inkey = '\0';
+ bool funct = false;
+
+ clearVerbBar();
+
+ bool handledOpcodeFl = false;
+ _controlMenu = 0;
+ if (!_keyPressedEsc) {
+ _menu.drawMenu();
+ _menu._menuDisplayed = true;
+ temps = 0;
+ _key = 0;
+ funct = false;
+ inkey = '.';
+
+ _inMainGameLoop = true;
+ do {
+ _menu.updateMenu();
+ prepareRoom();
+ _mouse.moveMouse(funct, inkey);
+ if (shouldQuit())
+ return;
+ ++temps;
+ } while (!((_menu._menuSelected) || (temps > lim) || (funct) || (_anyone)));
+ _inMainGameLoop = false;
+
+ _menu.eraseMenu();
+ _menu._menuDisplayed = false;
+ if ((inkey == '\1') || (inkey == '\3') || (inkey == '\5') || (inkey == '\7') || (inkey == '\11')) {
+ changeGraphicalDevice((uint)((int)inkey - 1) >> 1);
+ return;
+ }
+ if (_menu._menuSelected && (_currMenu == MENU_SAVE)) {
+ Common::String saveName = Common::String::format("Savegame #%d", _currAction & 15);
+ _savegameManager.saveGame(_currAction & 15, saveName);
+ }
+ if (_menu._menuSelected && (_currMenu == MENU_LOAD))
+ _savegameManager.loadGame((_currAction & 15) - 1);
+ if (inkey == '\103') { /* F9 */
+ temps = _dialogManager.show(_hintPctMessage, 1);
+ return;
+ } else if (inkey == '\77') {
+ if ((_menuOpcode != OPCODE_NONE) && ((_currMenu == MENU_ACTION) || (_currMenu == MENU_SELF))) {
+ _currAction = _menuOpcode;
+ displayTextInVerbBar(getEngineString(S_IDEM));
+ } else
+ return;
+ } else if (inkey == '\104') {
+ if ((_x != 0) && (_y != 0))
+ _num = 9999;
+ return;
+ }
+ }
+ if (inkey == '\73') {
+ _quitGame = true;
+ hourToChar();
+ } else {
+ if ((funct) && (inkey != '\77'))
+ return;
+ if (temps > lim) {
+ handleDescriptionText(2, 141);
+ if (_num == 9999)
+ _num = 0;
+ } else {
+ _menuOpcode = _currMenu;
+ if ((_currMenu == MENU_ACTION) || (_currMenu == MENU_SELF))
+ _menuOpcode = _currAction;
+ if (!_anyone) {
+ if ((_heroSearching) || (_obpart)) {
+ if (_mouse._pos.y < 12)
+ return;
+
+ if ((_currAction == OPCODE_SOUND) || (_currAction == OPCODE_LIFT)) {
+ handledOpcodeFl = true;
+ if ((_currAction == OPCODE_LIFT) || (_obpart)) {
+ endSearch();
+ _caff = _coreVar._currPlace;
+ _crep = 998;
+ } else
+ tsuiv();
+ mennor();
+ }
+ }
+ }
+ do {
+ if (!handledOpcodeFl)
+ handleOpcode();
+
+ if ((_controlMenu == 0) && (! _loseGame) && (! _endGame)) {
+ _text.taffich();
+ if (_destinationOk) {
+ _destinationOk = false;
+ drawPicture();
+ }
+ if ((!_syn) || (_col))
+ handleDescriptionText(2, _crep);
+ }
+ } while (_syn);
+ if (_controlMenu != 0)
+ displayControlMenu();
+ }
+ }
+}
+
+/**
+ * Engine function - Init Places
+ * @remarks Originally called 'init_lieu'
+ */
+void MortevielleEngine::loadPlaces() {
+ Common::File f;
+
+ if (!f.open("MXX.mor"))
+ if (!f.open("MFXX.mor"))
+ error("Missing file - MXX.mor");
+
+ for (int i = 0; i < 7; ++i) {
+ for (int j = 0; j < 25; ++j)
+ _destinationArray[i][j] = f.readByte();
+ }
+
+ f.close();
+}
+
+/**
+ * Set Text Color
+ * @remarks Originally called 'text_color'
+ */
+void MortevielleEngine::setTextColor(int col) {
+ _textColor = col;
+}
+
+/**
+ * Prepare screen - Type 1!
+ * @remarks Originally called 'ecrf1'
+ */
+void MortevielleEngine::prepareScreenType1() {
+ // Large drawing
+ _screenSurface.drawBox(0, 11, 512, 164, 15);
+}
+
+/**
+ * Prepare room - Type 2!
+ * @remarks Originally called 'ecrf2'
+ */
+void MortevielleEngine::prepareScreenType2() {
+ setTextColor(5);
+}
+
+/**
+ * Prepare room - Type 3!
+ * @remarks Originally called 'ecrf7'
+ */
+void MortevielleEngine::prepareScreenType3() {
+ setTextColor(4);
+}
+
+/**
+ * Engine function - Update hour
+ * @remarks Originally called 'calch'
+ */
+void MortevielleEngine::updateHour(int &day, int &hour, int &minute) {
+ int newHour = readclock();
+ int th = _currentHourCount + ((newHour - _currentDayHour) / _inGameHourDuration);
+ minute = ((th % 2) + _currHalfHour) * 30;
+ hour = ((uint)th >> 1) + _currHour;
+ if (minute == 60) {
+ minute = 0;
+ ++hour;
+ }
+ day = (hour / 24) + _currDay;
+ hour = hour - ((day - _currDay) * 24);
+}
+
+/**
+ * Engine function - Convert character index to bit index
+ * @remarks Originally called 'conv'
+ */
+int MortevielleEngine::convertCharacterIndexToBitIndex(int characterIndex) {
+ return 128 >> (characterIndex - 1);
+}
+
+/**
+ * Engine function - Convert bit index to character index
+ * @remarks Originally called 'tip'
+ */
+int MortevielleEngine::convertBitIndexToCharacterIndex(int bitIndex) {
+ int retVal = 0;
+
+ if (bitIndex == 128)
+ retVal = 1;
+ else if (bitIndex == 64)
+ retVal = 2;
+ else if (bitIndex == 32)
+ retVal = 3;
+ else if (bitIndex == 16)
+ retVal = 4;
+ else if (bitIndex == 8)
+ retVal = 5;
+ else if (bitIndex == 4)
+ retVal = 6;
+ else if (bitIndex == 2)
+ retVal = 7;
+ else if (bitIndex == 1)
+ retVal = 8;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Reset presence in other rooms
+ * @remarks Originally called 't5'
+ */
+void MortevielleEngine::resetPresenceInRooms(int roomId) {
+ if (roomId == DINING_ROOM)
+ _blo = false;
+
+ if (roomId != GREEN_ROOM) {
+ _roomPresenceLuc = false;
+ _roomPresenceIda = false;
+ }
+
+ if (roomId != PURPLE_ROOM)
+ _purpleRoomPresenceLeo = false;
+
+ if (roomId != DARKBLUE_ROOM) {
+ _roomPresenceGuy = false;
+ _roomPresenceEva = false;
+ }
+
+ if (roomId != BLUE_ROOM)
+ _roomPresenceMax = false;
+ if (roomId != RED_ROOM)
+ _roomPresenceBob = false;
+ if (roomId != GREEN_ROOM2)
+ _roomPresencePat = false;
+ if (roomId != TOILETS)
+ _toiletsPresenceBobMax = false;
+ if (roomId != BATHROOM)
+ _bathRoomPresenceBobMax = false;
+ if (roomId != ROOM9)
+ _room9PresenceLeo = false;
+}
+
+/**
+ * Engine function - Show the people present in the given room
+ * @remarks Originally called 'affper'
+ */
+void MortevielleEngine::showPeoplePresent(int bitIndex) {
+ int xp = 580 - (_screenSurface.getStringWidth("LEO") / 2);
+
+ for (int i = 1; i <= 8; ++i)
+ _menu.disableMenuItem(_menu._discussMenu[i]._menuId, _menu._discussMenu[i]._actionId);
+
+ clearUpperRightPart();
+ if ((bitIndex & 128) == 128) {
+ _screenSurface.putxy(xp, 24);
+ _screenSurface.drawString("LEO", 4);
+ _menu.enableMenuItem(_menu._discussMenu[1]._menuId, _menu._discussMenu[1]._actionId);
+ }
+ if ((bitIndex & 64) == 64) {
+ _screenSurface.putxy(xp, 32);
+ _screenSurface.drawString("PAT", 4);
+ _menu.enableMenuItem(_menu._discussMenu[2]._menuId, _menu._discussMenu[2]._actionId);
+ }
+ if ((bitIndex & 32) == 32) {
+ _screenSurface.putxy(xp, 40);
+ _screenSurface.drawString("GUY", 4);
+ _menu.enableMenuItem(_menu._discussMenu[3]._menuId, _menu._discussMenu[3]._actionId);
+ }
+ if ((bitIndex & 16) == 16) {
+ _screenSurface.putxy(xp, 48);
+ _screenSurface.drawString("EVA", 4);
+ _menu.enableMenuItem(_menu._discussMenu[4]._menuId, _menu._discussMenu[4]._actionId);
+ }
+ if ((bitIndex & 8) == 8) {
+ _screenSurface.putxy(xp, 56);
+ _screenSurface.drawString("BOB", 4);
+ _menu.enableMenuItem(_menu._discussMenu[5]._menuId, _menu._discussMenu[5]._actionId);
+ }
+ if ((bitIndex & 4) == 4) {
+ _screenSurface.putxy(xp, 64);
+ _screenSurface.drawString("LUC", 4);
+ _menu.enableMenuItem(_menu._discussMenu[6]._menuId, _menu._discussMenu[6]._actionId);
+ }
+ if ((bitIndex & 2) == 2) {
+ _screenSurface.putxy(xp, 72);
+ _screenSurface.drawString("IDA", 4);
+ _menu.enableMenuItem(_menu._discussMenu[7]._menuId, _menu._discussMenu[7]._actionId);
+ }
+ if ((bitIndex & 1) == 1) {
+ _screenSurface.putxy(xp, 80);
+ _screenSurface.drawString("MAX", 4);
+ _menu.enableMenuItem(_menu._discussMenu[8]._menuId, _menu._discussMenu[8]._actionId);
+ }
+ _currBitIndex = bitIndex;
+}
+
+/**
+ * Engine function - Select random characters
+ * @remarks Originally called 'choix'
+ */
+int MortevielleEngine::selectCharacters(int min, int max) {
+ bool invertSelection = false;
+ int rand = getRandomNumber(min, max);
+
+ if (rand > 4) {
+ rand = 8 - rand;
+ invertSelection = true;
+ }
+
+ int i = 0;
+ int retVal = 0;
+ while (i < rand) {
+ int charIndex = getRandomNumber(1, 8);
+ int charBitIndex = convertCharacterIndexToBitIndex(charIndex);
+ if ((retVal & charBitIndex) != charBitIndex) {
+ ++i;
+ retVal |= charBitIndex;
+ }
+ }
+ if (invertSelection)
+ retVal = 255 - retVal;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Green Room
+ * @remarks Originally called 'cpl1'
+ */
+int MortevielleEngine::getPresenceStatsGreenRoom() {
+ int day, hour, minute;
+ int retVal = 0;
+
+ updateHour(day, hour, minute);
+ // The original uses an || instead of an &&, resulting
+ // in an always true condition. Based on the other tests,
+ // and on other scenes, we use an && instead.
+ if ((hour > 7) && (hour < 11))
+ retVal = 25;
+ else if ((hour > 10) && (hour < 14))
+ retVal = 35;
+ else if ((hour > 13) && (hour < 16))
+ retVal = 50;
+ else if ((hour > 15) && (hour < 18))
+ retVal = 5;
+ else if ((hour > 17) && (hour < 22))
+ retVal = 35;
+ else if ((hour > 21) && (hour < 24))
+ retVal = 50;
+ else if ((hour >= 0) && (hour < 8))
+ retVal = 70;
+
+ _menu.updateMenu();
+
+ return retVal;
+}
+/**
+ * Engine function - Get Presence Statistics - Purple Room
+ * @remarks Originally called 'cpl2'
+ */
+int MortevielleEngine::getPresenceStatsPurpleRoom() {
+ int day, hour, minute;
+ int retVal = 0;
+
+ updateHour(day, hour, minute);
+ if ((hour > 7) && (hour < 11))
+ retVal = -2;
+ else if (hour == 11)
+ retVal = 100;
+ else if ((hour > 11) && (hour < 23))
+ retVal = 10;
+ else if (hour == 23)
+ retVal = 20;
+ else if ((hour >= 0) && (hour < 8))
+ retVal = 50;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Toilets
+ * @remarks Originally called 'cpl3'
+ */
+int MortevielleEngine::getPresenceStatsToilets() {
+ int day, hour, minute;
+ int retVal = 0;
+
+ updateHour(day, hour, minute);
+ if (((hour > 8) && (hour < 10)) || ((hour > 19) && (hour < 24)))
+ retVal = 34;
+ else if (((hour > 9) && (hour < 20)) || ((hour >= 0) && (hour < 9)))
+ retVal = 0;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Blue Room
+ * @remarks Originally called 'cpl5'
+ */
+int MortevielleEngine::getPresenceStatsBlueRoom() {
+ int day, hour, minute;
+ int retVal = 0;
+
+ updateHour(day, hour, minute);
+ if ((hour > 6) && (hour < 10))
+ retVal = 0;
+ else if (hour == 10)
+ retVal = 100;
+ else if ((hour > 10) && (hour < 24))
+ retVal = 15;
+ else if ((hour >= 0) && (hour < 7))
+ retVal = 50;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Red Room
+ * @remarks Originally called 'cpl6'
+ */
+int MortevielleEngine::getPresenceStatsRedRoom() {
+ int day, hour, minute;
+ int retVal = 0;
+
+ updateHour(day, hour, minute);
+ if (((hour > 7) && (hour < 13)) || ((hour > 17) && (hour < 20)))
+ retVal = -2;
+ else if (((hour > 12) && (hour < 17)) || ((hour > 19) && (hour < 24)))
+ retVal = 35;
+ else if (hour == 17)
+ retVal = 100;
+ else if ((hour >= 0) && (hour < 8))
+ retVal = 60;
+
+ return retVal;
+}
+
+/**
+ * Shows the "you are alone" message in the status area
+ * on the right hand side of the screen
+ * @remarks Originally called 'person'
+ */
+void MortevielleEngine::displayAloneText() {
+ for (int i = 1; i <= 8; ++i)
+ _menu.disableMenuItem(_menu._discussMenu[i]._menuId, _menu._discussMenu[i]._actionId);
+
+ Common::String sYou = getEngineString(S_YOU);
+ Common::String sAre = getEngineString(S_ARE);
+ Common::String sAlone = getEngineString(S_ALONE);
+
+ clearUpperRightPart();
+ _screenSurface.putxy(580 - (_screenSurface.getStringWidth(sYou) / 2), 30);
+ _screenSurface.drawString(sYou, 4);
+ _screenSurface.putxy(580 - (_screenSurface.getStringWidth(sAre) / 2), 50);
+ _screenSurface.drawString(sAre, 4);
+ _screenSurface.putxy(580 - (_screenSurface.getStringWidth(sAlone) / 2), 70);
+ _screenSurface.drawString(sAlone, 4);
+
+ _currBitIndex = 0;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Room Bureau
+ * @remarks Originally called 'cpl10'
+ */
+int MortevielleEngine::getPresenceStatsDiningRoom(int &hour) {
+ int day, minute;
+
+ int retVal = 0;
+ updateHour(day, hour, minute);
+ if (((hour > 7) && (hour < 11)) || ((hour > 11) && (hour < 14)) || ((hour > 18) && (hour < 21)))
+ retVal = 100;
+ else if ((hour == 11) || ((hour > 20) && (hour < 24)))
+ retVal = 45;
+ else if (((hour > 13) && (hour < 17)) || (hour == 18))
+ retVal = 35;
+ else if (hour == 17)
+ retVal = 60;
+ else if ((hour >= 0) && (hour < 8))
+ retVal = 5;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Room Bureau
+ * @remarks Originally called 'cpl11'
+ */
+int MortevielleEngine::getPresenceStatsBureau(int &hour) {
+ int day, minute;
+ int retVal = 0;
+
+ updateHour(day, hour, minute);
+ if (((hour > 8) && (hour < 12)) || ((hour > 20) && (hour < 24)))
+ retVal = 25;
+ else if (((hour > 11) && (hour < 14)) || ((hour > 18) && (hour < 21)))
+ retVal = 5;
+ else if ((hour > 13) && (hour < 17))
+ retVal = 55;
+ else if ((hour > 16) && (hour < 19))
+ retVal = 45;
+ else if ((hour >= 0) && (hour < 9))
+ retVal = 0;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Room Kitchen
+ * @remarks Originally called 'cpl12'
+ */
+int MortevielleEngine::getPresenceStatsKitchen() {
+ int day, hour, minute;
+ int retVal = 0;
+
+ updateHour(day, hour, minute);
+ if (((hour > 8) && (hour < 15)) || ((hour > 16) && (hour < 22)))
+ retVal = 55;
+ else if (((hour > 14) && (hour < 17)) || ((hour > 21) && (hour < 24)))
+ retVal = 25;
+ else if ((hour >= 0) && (hour < 5))
+ retVal = 0;
+ else if ((hour > 4) && (hour < 9))
+ retVal = 15;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Room Attic
+ * @remarks Originally called 'cpl13'
+ */
+int MortevielleEngine::getPresenceStatsAttic() {
+ return 0;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Room Landing
+ * @remarks Originally called 'cpl15'
+ */
+int MortevielleEngine::getPresenceStatsLanding() {
+ int day, hour, minute;
+ int retVal = 0;
+
+ updateHour(day, hour, minute);
+ if ((hour > 7) && (hour < 12))
+ retVal = 25;
+ else if ((hour > 11) && (hour < 14))
+ retVal = 0;
+ else if ((hour > 13) && (hour < 18))
+ retVal = 10;
+ else if ((hour > 17) && (hour < 20))
+ retVal = 55;
+ else if ((hour > 19) && (hour < 22))
+ retVal = 5;
+ else if ((hour > 21) && (hour < 24))
+ retVal = 15;
+ else if ((hour >= 0) && (hour < 8))
+ retVal = -15;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Get Presence Statistics - Room Chapel
+ * @remarks Originally called 'cpl20'
+ */
+int MortevielleEngine::getPresenceStatsChapel(int &hour) {
+ int day, minute;
+ int retVal = 0;
+
+ updateHour(day, hour, minute);
+ if (hour == 10)
+ retVal = 65;
+ else if ((hour > 10) && (hour < 21))
+ retVal = 5;
+ else if ((hour > 20) && (hour < 24))
+ retVal = -15;
+ else if ((hour >= 0) && (hour < 5))
+ retVal = -300;
+ else if ((hour > 4) && (hour < 10))
+ retVal = -5;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Check who is in the Green Room
+ * @remarks Originally called 'quelq1'
+ */
+void MortevielleEngine::setPresenceGreenRoom(int roomId) {
+ int rand = getRandomNumber(1, 2);
+ if (roomId == GREEN_ROOM) {
+ if (rand == 1)
+ _roomPresenceLuc = true;
+ else
+ _roomPresenceIda = true;
+ } else if (roomId == DARKBLUE_ROOM) {
+ if (rand == 1)
+ _roomPresenceGuy = true;
+ else
+ _roomPresenceEva = true;
+ }
+
+ _currBitIndex = 10;
+}
+
+/**
+ * Engine function - Check who is in the Purple Room
+ * @remarks Originally called 'quelq2'
+ */
+void MortevielleEngine::setPresencePurpleRoom() {
+ if (_place == PURPLE_ROOM)
+ _purpleRoomPresenceLeo = true;
+ else
+ _room9PresenceLeo = true;
+
+ _currBitIndex = 10;
+}
+
+/**
+ * Engine function - Check who is in the Blue Room
+ * @remarks Originally called 'quelq5'
+ */
+void MortevielleEngine::setPresenceBlueRoom() {
+ _roomPresenceMax = true;
+ _currBitIndex = 10;
+}
+
+/**
+ * Engine function - Check who is in the Red Room
+ * @remarks Originally called 'quelq6'
+ */
+void MortevielleEngine::setPresenceRedRoom(int roomId) {
+ if (roomId == RED_ROOM)
+ _roomPresenceBob = true;
+ else if (roomId == GREEN_ROOM2)
+ _roomPresencePat = true;
+
+ _currBitIndex = 10;
+}
+
+/**
+ * Engine function - Check who is in the Dining Room
+ * @remarks Originally called 'quelq10'
+ */
+int MortevielleEngine::setPresenceDiningRoom(int hour) {
+ int retVal = 0;
+
+ if ((hour >= 0) && (hour < 8))
+ retVal = checkLeoMaxRandomPresence();
+ else {
+ int min = 0, max = 0;
+ if ((hour > 7) && (hour < 10)) {
+ min = 5;
+ max = 7;
+ } else if ((hour > 9) && (hour < 12)) {
+ min = 1;
+ max = 4;
+ } else if (((hour > 11) && (hour < 15)) || ((hour > 18) && (hour < 21))) {
+ min = 6;
+ max = 8;
+ } else if (((hour > 14) && (hour < 19)) || ((hour > 20) && (hour < 24))) {
+ min = 1;
+ max = 5;
+ }
+ retVal = selectCharacters(min, max);
+ }
+ showPeoplePresent(retVal);
+
+ return retVal;
+}
+
+/**
+ * Engine function - Check who is in the Bureau
+ * @remarks Originally called 'quelq11'
+ */
+int MortevielleEngine::setPresenceBureau(int hour) {
+ int retVal = 0;
+
+ if ((hour >= 0) && (hour < 8))
+ retVal = checkLeoMaxRandomPresence();
+ else {
+ int min = 0, max = 0;
+ if (((hour > 7) && (hour < 10)) || ((hour > 20) && (hour < 24))) {
+ min = 1;
+ max = 3;
+ } else if (((hour > 9) && (hour < 12)) || ((hour > 13) && (hour < 19))) {
+ min = 1;
+ max = 4;
+ } else if (((hour > 11) && (hour < 14)) || ((hour > 18) && (hour < 21))) {
+ min = 1;
+ max = 2;
+ }
+ retVal = selectCharacters(min, max);
+ }
+ showPeoplePresent(retVal);
+
+ return retVal;
+}
+
+/**
+ * Engine function - Check who is in the Kitchen
+ * @remarks Originally called 'quelq12'
+ */
+int MortevielleEngine::setPresenceKitchen() {
+ int retVal = checkLeoMaxRandomPresence();
+ showPeoplePresent(retVal);
+
+ return retVal;
+}
+
+/**
+ * Engine function - Check who is in the Landing
+ * @remarks Originally called 'quelq15'
+ */
+int MortevielleEngine::setPresenceLanding() {
+ bool test = false;
+ int rand = 0;
+ do {
+ rand = getRandomNumber(1, 8);
+ test = (((rand == 1) && (_purpleRoomPresenceLeo || _room9PresenceLeo)) ||
+ ((rand == 2) && _roomPresencePat) ||
+ ((rand == 3) && _roomPresenceGuy) ||
+ ((rand == 4) && _roomPresenceEva) ||
+ ((rand == 5) && _roomPresenceBob) ||
+ ((rand == 6) && _roomPresenceLuc) ||
+ ((rand == 7) && _roomPresenceIda) ||
+ ((rand == 8) && _roomPresenceMax));
+ } while (test);
+
+ int retVal = convertCharacterIndexToBitIndex(rand);
+ showPeoplePresent(retVal);
+
+ return retVal;
+}
+
+/**
+ * Engine function - Check who is in the chapel
+ * @remarks Originally called 'quelq20'
+ */
+int MortevielleEngine::setPresenceChapel(int hour) {
+ int retVal = 0;
+
+ if (((hour >= 0) && (hour < 10)) || ((hour > 18) && (hour < 24)))
+ retVal = checkLeoMaxRandomPresence();
+ else {
+ int min = 0, max = 0;
+ if ((hour > 9) && (hour < 12)) {
+ min = 3;
+ max = 7;
+ } else if ((hour > 11) && (hour < 18)) {
+ min = 1;
+ max = 2;
+ } else if (hour == 18) {
+ min = 2;
+ max = 4;
+ }
+ retVal = selectCharacters(min, max);
+ }
+ showPeoplePresent(retVal);
+
+ return retVal;
+}
+
+/**
+ * Engine function - Get the answer after you known a door
+ * @remarks Originally called 'frap'
+ */
+void MortevielleEngine::getKnockAnswer() {
+ int day, hour, minute;
+
+ updateHour(day, hour, minute);
+ if ((hour >= 0) && (hour < 8))
+ _crep = 190;
+ else {
+ if (getRandomNumber(1, 100) > 70)
+ _crep = 190;
+ else
+ _crep = 147;
+ }
+}
+
+/**
+ * Engine function - Get Room Presence Bit Index
+ * @remarks Originally called 'nouvp'
+ */
+int MortevielleEngine::getPresenceBitIndex(int roomId) {
+ int bitIndex = 0;
+ if (roomId == GREEN_ROOM) {
+ if (_roomPresenceLuc)
+ bitIndex = 4; // LUC
+ if (_roomPresenceIda)
+ bitIndex = 2; // IDA
+ } else if ( ((roomId == PURPLE_ROOM) && (_purpleRoomPresenceLeo))
+ || ((roomId == ROOM9) && (_room9PresenceLeo)))
+ bitIndex = 128; // LEO
+ else if (roomId == DARKBLUE_ROOM) {
+ if (_roomPresenceGuy)
+ bitIndex = 32; // GUY
+ if (_roomPresenceEva)
+ bitIndex = 16; // EVA
+ } else if ((roomId == BLUE_ROOM) && (_roomPresenceMax))
+ bitIndex = 1; // MAX
+ else if ((roomId == RED_ROOM) && (_roomPresenceBob))
+ bitIndex = 8; // BOB
+ else if ((roomId == GREEN_ROOM2) && (_roomPresencePat))
+ bitIndex = 64; // PAT
+ else if ( ((roomId == TOILETS) && (_toiletsPresenceBobMax))
+ || ((roomId == BATHROOM) && (_bathRoomPresenceBobMax)) )
+ bitIndex = 9; // BOB + MAX
+
+ if (bitIndex != 9)
+ showPeoplePresent(bitIndex);
+
+ return bitIndex;
+}
+
+/**
+ * Engine function - initGame
+ * @remarks Originally called 'dprog'
+ */
+void MortevielleEngine::initGame() {
+ _place = MANOR_FRONT;
+ _currentHourCount = 0;
+ if (!_coreVar._alreadyEnteredManor)
+ _blo = true;
+ _inGameHourDuration = kTime1;
+ _currentDayHour = readclock();
+}
+
+/**
+ * Engine function - Set Random Presence - Green Room
+ * @remarks Originally called 'pl1'
+ */
+void MortevielleEngine::setRandomPresenceGreenRoom(int faithScore) {
+ if ( ((_place == GREEN_ROOM) && (!_roomPresenceLuc) && (!_roomPresenceIda))
+ || ((_place == DARKBLUE_ROOM) && (!_roomPresenceGuy) && (!_roomPresenceEva)) ) {
+ int p = getPresenceStatsGreenRoom();
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresenceGreenRoom(_place);
+ }
+}
+
+/**
+ * Engine function - Set Random Presence - Purple Room
+ * @remarks Originally called 'pl2'
+ */
+void MortevielleEngine::setRandomPresencePurpleRoom(int faithScore) {
+ if (!_purpleRoomPresenceLeo) {
+ int p = getPresenceStatsPurpleRoom();
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresencePurpleRoom();
+ }
+}
+
+/**
+ * Engine function - Set Random Presence - Blue Room
+ * @remarks Originally called 'pl5'
+ */
+void MortevielleEngine::setRandomPresenceBlueRoom(int faithScore) {
+ if (!_roomPresenceMax) {
+ int p = getPresenceStatsBlueRoom();
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresenceBlueRoom();
+ }
+}
+
+/**
+ * Engine function - Set Random Presence - Red Room
+ * @remarks Originally called 'pl6'
+ */
+void MortevielleEngine::setRandomPresenceRedRoom(int faithScore) {
+ if ( ((_place == RED_ROOM) && (!_roomPresenceBob))
+ || ((_place == GREEN_ROOM2) && (!_roomPresencePat)) ) {
+ int p = getPresenceStatsRedRoom();
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresenceRedRoom(_place);
+ }
+}
+
+/**
+ * Engine function - Set Random Presence - Room 9
+ * @remarks Originally called 'pl9'
+ */
+void MortevielleEngine::setRandomPresenceRoom9(int faithScore) {
+ if (!_room9PresenceLeo) {
+ faithScore = -10;
+ if (getRandomNumber(1, 100) > faithScore) // always true?
+ displayAloneText();
+ else
+ setPresencePurpleRoom();
+ }
+}
+
+/**
+ * Engine function - Set Random Presence - Dining Room
+ * @remarks Originally called 'pl10'
+ */
+void MortevielleEngine::setRandomPresenceDiningRoom(int faithScore) {
+ int h;
+ int p = getPresenceStatsDiningRoom(h);
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresenceDiningRoom(h);
+}
+
+/**
+ * Engine function - Set Random Presence - Bureau
+ * @remarks Originally called 'pl11'
+ */
+void MortevielleEngine::setRandomPresenceBureau(int faithScore) {
+ int h;
+
+ int p = getPresenceStatsBureau(h);
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresenceBureau(h);
+}
+
+/**
+ * Engine function - Set Random Presence - Kitchen
+ * @remarks Originally called 'pl12'
+ */
+void MortevielleEngine::setRandomPresenceKitchen(int faithScore) {
+
+ int p = getPresenceStatsKitchen();
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresenceKitchen();
+}
+
+/**
+ * Engine function - Set Random Presence - Attic / Cellar
+ * @remarks Originally called 'pl13'
+ */
+void MortevielleEngine::setRandomPresenceAttic(int faithScore) {
+ int p = getPresenceStatsAttic();
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresenceKitchen();
+}
+
+/**
+ * Engine function - Set Random Presence - Landing
+ * @remarks Originally called 'pl15'
+ */
+void MortevielleEngine::setRandomPresenceLanding(int faithScore) {
+ int p = getPresenceStatsLanding();
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresenceLanding();
+}
+
+/**
+ * Engine function - Set Random Presence - Chapel
+ * @remarks Originally called 'pl20'
+ */
+void MortevielleEngine::setRandomPresenceChapel(int faithScore) {
+ int h;
+
+ int p = getPresenceStatsChapel(h);
+ p += faithScore;
+ if (getRandomNumber(1, 100) > p)
+ displayAloneText();
+ else
+ setPresenceChapel(h);
+}
+
+/**
+ * Start music or speech
+ * @remarks Originally called 'musique'
+ */
+void MortevielleEngine::startMusicOrSpeech(int so) {
+ if (so == 0) {
+ /* musik(0) */
+ ;
+ } else if ((!_introSpeechPlayed) && (!_coreVar._alreadyEnteredManor)) {
+ // Type 1: Speech
+ _speechManager.startSpeech(10, 1, 1);
+ _introSpeechPlayed = true;
+ } else {
+ if (((_coreVar._currPlace == MOUNTAIN) || (_coreVar._currPlace == MANOR_FRONT) || (_coreVar._currPlace == MANOR_BACK)) && (getRandomNumber(1, 3) == 2))
+ // Type 1: Speech
+ _speechManager.startSpeech(9, getRandomNumber(2, 4), 1);
+ else if ((_coreVar._currPlace == CHAPEL) && (getRandomNumber(1, 2) == 1))
+ // Type 1: Speech
+ _speechManager.startSpeech(8, 1, 1);
+ else if ((_coreVar._currPlace == WELL) && (getRandomNumber(1, 2) == 2))
+ // Type 1: Speech
+ _speechManager.startSpeech(12, 1, 1);
+ else if (_coreVar._currPlace == INSIDE_WELL)
+ // Type 1: Speech
+ _speechManager.startSpeech(13, 1, 1);
+ else
+ // Type 2 : music
+ _speechManager.startSpeech(getRandomNumber(1, 17), 1, 2);
+ }
+}
+
+/**
+ * Engine function - You lose!
+ * @remarks Originally called 'tperd'
+ */
+void MortevielleEngine::loseGame() {
+ resetOpenObjects();
+ _roomDoorId = OWN_ROOM;
+ _mchai = 0;
+ _menu.unsetSearchMenu();
+ if (!_blo)
+ getPresence(MANOR_FRONT);
+
+ _loseGame = true;
+ clearUpperLeftPart();
+ _screenSurface.drawBox(60, 35, 400, 50, 15);
+ handleDescriptionText(9, _crep);
+ clearDescriptionBar();
+ clearVerbBar();
+ _col = false;
+ _syn = false;
+ _destinationOk = false;
+}
+
+/**
+ * Engine function - Check inventory for a given object
+ * @remarks Originally called 'cherjer'
+ */
+bool MortevielleEngine::checkInventory(int objectId) {
+ bool retVal = false;
+ for (int i = 1; i <= 6; ++i)
+ retVal = (retVal || (_coreVar._inventory[i] == objectId));
+
+ if (_coreVar._selectedObjectId == objectId)
+ retVal = true;
+
+ return retVal;
+}
+
+/**
+ * Engine function - Display Dining Room
+ * @remarks Originally called 'st1sama'
+ */
+void MortevielleEngine::displayDiningRoom() {
+ _coreVar._currPlace = DINING_ROOM;
+ prepareDisplayText();
+}
+
+/**
+ * Engine function - Start non interactive Dialog
+ * @remarks Originally called 'sparl'
+ */
+void MortevielleEngine::startDialog(int16 rep) {
+ const int haut[9] = { 0, 0, 1, -3, 6, -2, 2, 7, -1 };
+ int key;
+
+ assert(rep >= 0);
+
+ _mouse.hideMouse();
+ Common::String dialogStr = getString(rep + kDialogStringIndex);
+ _text.displayStr(dialogStr, 230, 4, 65, 24, 5);
+ _dialogManager.drawF3F8();
+
+ key = 0;
+ do {
+ _speechManager.startSpeech(rep, haut[_caff - 69], 0);
+ key = _dialogManager.waitForF3F8();
+ if (shouldQuit())
+ return;
+ } while (key != 66);
+ hirs();
+ _mouse.showMouse();
+}
+
+/**
+ * Engine function - End of Search: reset globals
+ * @remarks Originally called 'finfouill'
+ */
+void MortevielleEngine::endSearch() {
+ _heroSearching = false;
+ _obpart = false;
+ _searchCount = 0;
+ _menu.unsetSearchMenu();
+}
+
+/**
+ * Engine function - Go to Dining room
+ * @remarks Originally called 't1sama'
+ */
+void MortevielleEngine::gotoDiningRoom() {
+ int day, hour, minute;
+
+ updateHour(day, hour, minute);
+ if ((hour < 5) && (_coreVar._currPlace > ROOM18)) {
+ if (!checkInventory(137)) { //You don't have the keys, and it's late
+ _crep = 1511;
+ loseGame();
+ } else
+ displayDiningRoom();
+ } else if (!_coreVar._alreadyEnteredManor) { //Is it your first time?
+ _currBitIndex = 255; // Everybody is present
+ showPeoplePresent(_currBitIndex);
+ _caff = 77;
+ drawPictureWithText();
+ _screenSurface.drawBox(223, 47, 155, 92, 15);
+ handleDescriptionText(2, 33);
+ testKey(false);
+ mennor();
+ _mouse.hideMouse();
+ hirs();
+ premtet();
+ startDialog(140);
+ drawRightFrame();
+ drawClock();
+ _mouse.showMouse();
+ _coreVar._currPlace = OWN_ROOM;
+ prepareDisplayText();
+ resetPresenceInRooms(DINING_ROOM);
+ if (!_blo)
+ getPresence(OWN_ROOM);
+ _currBitIndex = 0;
+ _savedBitIndex = 0;
+ _coreVar._alreadyEnteredManor = true;
+ } else
+ displayDiningRoom();
+}
+
+/**
+ * Engine function - Check Manor distance (in the mountains)
+ * @remarks Originally called 't1neig'
+ */
+void MortevielleEngine::checkManorDistance() {
+ ++_manorDistance;
+ if (_manorDistance > 2) {
+ _crep = 1506;
+ loseGame();
+ } else {
+ _destinationOk = true;
+ _coreVar._currPlace = MOUNTAIN;
+ prepareDisplayText();
+ }
+}
+
+/**
+ * Engine function - Go to Manor front
+ * @remarks Originally called 't1deva'
+ */
+void MortevielleEngine::gotoManorFront() {
+ _manorDistance = 0;
+ _coreVar._currPlace = MANOR_FRONT;
+ prepareDisplayText();
+}
+
+/**
+ * Engine function - Go to Manor back
+ * @remarks Originally called 't1derr'
+ */
+void MortevielleEngine::gotoManorBack() {
+ _coreVar._currPlace = MANOR_BACK;
+ prepareDisplayText();
+}
+
+/**
+ * Engine function - Dead : Flooded in Well
+ * @remarks Originally called 't1deau'
+ */
+void MortevielleEngine::floodedInWell() {
+ _crep = 1503;
+ loseGame();
+}
+
+/**
+ * Engine function - Change Graphical Device
+ * @remarks Originally called 'change_gd'
+ */
+void MortevielleEngine::changeGraphicalDevice(int newDevice) {
+ _mouse.hideMouse();
+ _currGraphicalDevice = newDevice;
+ hirs();
+ _mouse.initMouse();
+ _mouse.showMouse();
+ drawRightFrame();
+ prepareRoom();
+ drawClock();
+ if (_currBitIndex != 0)
+ showPeoplePresent(_currBitIndex);
+ else
+ displayAloneText();
+ clearDescriptionBar();
+ clearVerbBar();
+ _maff = 68;
+ drawPictureWithText();
+ handleDescriptionText(2, _crep);
+ _menu.displayMenu();
+}
+
+/**
+ * Called when a savegame has been loaded.
+ * @remarks Originally called 'antegame'
+ */
+void MortevielleEngine::gameLoaded() {
+ _mouse.hideMouse();
+ _menu._menuDisplayed = false;
+ _loseGame = true;
+ _anyone = false;
+ _destinationOk = true;
+ _col = false;
+ _hiddenHero = false;
+ _uptodatePresence = false;
+ _maff = 68;
+ _menuOpcode = OPCODE_NONE;
+ _introSpeechPlayed = false;
+ _x = 0;
+ _y = 0;
+ _num = 0;
+ _startHour = 0;
+ _endHour = 0;
+ _searchCount = 0;
+ _roomDoorId = OWN_ROOM;
+ _syn = true;
+ _heroSearching = true;
+ _mchai = 0;
+ _manorDistance = 0;
+ resetOpenObjects();
+ _takeObjCount = 0;
+ prepareDisplayText();
+ _hintPctMessage = getString(580);
+
+ _destinationOk = false;
+ _endGame = true;
+ _loseGame = false;
+ _heroSearching = false;
+
+ displayAloneText();
+ prepareRoom();
+ drawClock();
+ drawPictureWithText();
+ handleDescriptionText(2, _crep);
+ clearVerbBar();
+ _endGame = false;
+ _menu.setDestinationText(_coreVar._currPlace);
+ _menu.setInventoryText();
+ if (_coreVar._selectedObjectId != 0)
+ displayItemInHand(_coreVar._selectedObjectId + 400);
+ _mouse.showMouse();
+}
+
+/**
+ * Engine function - Handle OpCodes
+ * @remarks Originally called 'tsitu'
+ */
+void MortevielleEngine::handleOpcode() {
+ if (!_col)
+ clearDescriptionBar();
+ _syn = false;
+ _keyPressedEsc = false;
+ if (!_anyone) {
+ if (_uptodatePresence) {
+ if ((_currMenu == MENU_MOVE) || (_currAction == OPCODE_LEAVE) || (_currAction == OPCODE_SLEEP) || (_currAction == OPCODE_EAT)) {
+ _controlMenu = 4;
+ mennor();
+ return;
+ }
+ }
+ if (_currMenu == MENU_MOVE)
+ fctMove();
+ if (_currMenu == MENU_DISCUSS)
+ fctDiscuss();
+ if (_currMenu == MENU_INVENTORY)
+ fctInventoryTake();
+ if (_currAction == OPCODE_ATTACH)
+ fctAttach();
+ if (_currAction == OPCODE_WAIT)
+ fctWait();
+ if (_currAction == OPCODE_FORCE)
+ fctForce();
+ if (_currAction == OPCODE_SLEEP)
+ fctSleep();
+ if (_currAction == OPCODE_LISTEN)
+ fctListen();
+ if (_currAction == OPCODE_ENTER)
+ fctEnter();
+ if (_currAction == OPCODE_CLOSE)
+ fctClose();
+ if (_currAction == OPCODE_SEARCH)
+ fctSearch();
+ if (_currAction == OPCODE_KNOCK)
+ fctKnock();
+ if (_currAction == OPCODE_SCRATCH)
+ fctScratch();
+ if (_currAction == OPCODE_READ)
+ fctRead();
+ if (_currAction == OPCODE_EAT)
+ fctEat();
+ if (_currAction == OPCODE_PLACE)
+ fctPlace();
+ if (_currAction == OPCODE_OPEN)
+ fctOpen();
+ if (_currAction == OPCODE_TAKE)
+ fctTake();
+ if (_currAction == OPCODE_LOOK)
+ fctLook();
+ if (_currAction == OPCODE_SMELL)
+ fctSmell();
+ if (_currAction == OPCODE_SOUND)
+ fctSound();
+ if (_currAction == OPCODE_LEAVE)
+ fctLeave();
+ if (_currAction == OPCODE_LIFT)
+ fctLift();
+ if (_currAction == OPCODE_TURN)
+ fctTurn();
+ if (_currAction == OPCODE_SSEARCH)
+ fctSelfSearch();
+ if (_currAction == OPCODE_SREAD)
+ fctSelfRead();
+ if (_currAction == OPCODE_SPUT)
+ fctSelfPut();
+ if (_currAction == OPCODE_SLOOK)
+ fctSelftLook();
+ _hiddenHero = false;
+
+ if (_currAction == OPCODE_SHIDE)
+ fctSelfHide();
+ } else {
+ if (_anyone) {
+ interactNPC();
+ _anyone = false;
+ mennor();
+ return;
+ }
+ }
+ int hour, day, minute;
+ updateHour(day, hour, minute);
+ if ((((hour == 12) || (hour == 13) || (hour == 19)) && (_coreVar._currPlace != DINING_ROOM)) ||
+ ((hour > 0) && (hour < 6) && (_coreVar._currPlace != OWN_ROOM)))
+ ++_coreVar._faithScore;
+ if (((_coreVar._currPlace < CRYPT) || (_coreVar._currPlace > MOUNTAIN)) && (_coreVar._currPlace != INSIDE_WELL)
+ && (_coreVar._currPlace != OWN_ROOM) && (_coreVar._selectedObjectId != 152) && (!_loseGame)) {
+ if ((_coreVar._faithScore > 99) && (hour > 8) && (hour < 16)) {
+ _crep = 1501;
+ loseGame();
+ }
+ if ((_coreVar._faithScore > 99) && (hour > 0) && (hour < 9)) {
+ _crep = 1508;
+ loseGame();
+ }
+ if ((day > 1) && (hour > 8) && (!_loseGame)) {
+ _crep = 1502;
+ loseGame();
+ }
+ }
+ mennor();
+}
+
+/**
+ * Engine function - Transform time into a char
+ * @remarks Originally called 'tmaj3'
+ */
+void MortevielleEngine::hourToChar() {
+ int day, hour, minute;
+
+ updateHour(day, hour, minute);
+ if (minute == 30)
+ minute = 1;
+ hour += day * 24;
+ minute += hour * 2;
+ _coreVar._fullHour = (unsigned char)minute;
+}
+
+/**
+ * Engine function - extract time from a char
+ * @remarks Originally called 'theure'
+ */
+void MortevielleEngine::charToHour() {
+ int fullHour = _coreVar._fullHour;
+ int tmpHour = fullHour % 48;
+ _currDay = fullHour / 48;
+ _currHalfHour = tmpHour % 2;
+ _currHour = tmpHour / 2;
+ _hour = _currHour;
+ if (_currHalfHour == 1)
+ _minute = 30;
+ else
+ _minute = 0;
+}
+
+/**
+ * Engine function - Clear upper left part of Screen - Type 1
+ * @remarks Originally called 'clsf1'
+ */
+void MortevielleEngine::clearUpperLeftPart() {
+ _mouse.hideMouse();
+ _screenSurface.fillRect(0, Common::Rect(0, 11, 514, 175));
+ _mouse.showMouse();
+}
+
+/**
+ * Engine function - Clear low bar used by description
+ * @remarks Originally called 'clsf2'
+ */
+void MortevielleEngine::clearDescriptionBar() {
+ _mouse.hideMouse();
+ if (_largestClearScreen) {
+ _screenSurface.fillRect(0, Common::Rect(1, 176, 633, 199));
+ _screenSurface.drawBox(0, 176, 634, 23, 15);
+ _largestClearScreen = false;
+ } else {
+ _screenSurface.fillRect(0, Common::Rect(1, 176, 633, 190));
+ _screenSurface.drawBox(0, 176, 634, 14, 15);
+ }
+ _mouse.showMouse();
+}
+
+/**
+ * Engine function - Clear lowest bar used by verbs
+ * @remarks Originally called 'clsf3'
+ */
+void MortevielleEngine::clearVerbBar() {
+ _mouse.hideMouse();
+ _screenSurface.fillRect(0, Common::Rect(1, 192, 633, 199));
+ _screenSurface.drawBox(0, 191, 634, 8, 15);
+ _mouse.showMouse();
+}
+
+/**
+ * Engine function - Clear upper right part of the screen
+ * @remarks Originally called 'clsf10'
+ */
+void MortevielleEngine::clearUpperRightPart() {
+ int x1, x2;
+ Common::String st;
+
+ _mouse.hideMouse();
+ if (_resolutionScaler == 1) {
+ x2 = 634;
+ x1 = 534;
+ } else {
+ x2 = 600;
+ x1 = 544;
+ }
+ // Clear ambiance description
+ _screenSurface.fillRect(15, Common::Rect(x1, 93, x2, 98));
+ if (_coreVar._faithScore < 33)
+ st = getEngineString(S_COOL);
+ else if (_coreVar._faithScore < 66)
+ st = getEngineString(S_LOURDE);
+ else if (_coreVar._faithScore > 65)
+ st = getEngineString(S_MALSAINE);
+
+ x1 = 580 - (_screenSurface.getStringWidth(st) / 2);
+ _screenSurface.putxy(x1, 92);
+ _screenSurface.drawString(st, 4);
+
+ // Clear person list
+ _screenSurface.fillRect(15, Common::Rect(560, 24, 610, 86));
+ _mouse.showMouse();
+}
+
+/**
+ * Engine function - Get a random number between two values
+ * @remarks Originally called 'get_random_number' and 'hazard'
+ */
+int MortevielleEngine::getRandomNumber(int minval, int maxval) {
+ return _randomSource.getRandomNumber(maxval - minval) + minval;
+}
+
+/**
+ * Engine function - Show alert "use move menu"
+ * @remarks Originally called 'aldepl'
+ */
+void MortevielleEngine::showMoveMenuAlert() {
+ _dialogManager.show(getEngineString(S_USE_DEP_MENU), 1);
+}
+
+/**
+ * The original engine used this method to display a starting text screen letting the player
+ * select the graphics mode to use
+ * @remarks Originally called 'dialpre'
+ */
+void MortevielleEngine::showConfigScreen() {
+ _crep = 998;
+}
+
+/**
+ * Decodes a number of 64 byte blocks
+ * @param pStart Start of data
+ * @param count Number of 64 byte blocks
+ * @remarks Originally called 'zzuul'
+ */
+void MortevielleEngine::decodeNumber(byte *pStart, int count) {
+ while (count-- > 0) {
+ for (int idx = 0; idx < 64; ++pStart, ++idx) {
+ uint16 v = ((*pStart - 0x80) << 1) + 0x80;
+
+ if (v & 0x8000)
+ *pStart = 0;
+ else if (v & 0xff00)
+ *pStart = 0xff;
+ else
+ *pStart = (byte)v;
+ }
+ }
+}
+
+const byte cryptoArrDefaultFr[32] = {
+ 32, 101, 115, 97, 114, 105, 110,
+ 117, 116, 111, 108, 13, 100, 99,
+ 112, 109, 46, 118, 130, 39, 102,
+ 98, 44, 113, 104, 103, 33, 76,
+ 85, 106, 30, 31
+};
+
+const byte cryptoArr30Fr[32] = {
+ 69, 67, 74, 138, 133, 120, 77, 122,
+ 121, 68, 65, 63, 73, 80, 83, 82,
+ 156, 45, 58, 79, 49, 86, 78, 84,
+ 71, 81, 64, 66, 135, 34, 136, 91
+};
+
+const byte cryptoArr31Fr[32]= {
+ 93, 47, 48, 53, 50, 70, 124, 75,
+ 72, 147, 140, 150, 151, 57, 56, 51,
+ 107, 139, 55, 89, 131, 37, 54, 88,
+ 119, 0, 0, 0, 0, 0, 0, 0
+};
+
+const byte cryptoArrDefaultDe[32] = {
+ 0x20, 0x65, 0x6E, 0x69, 0x73, 0x72, 0x74,
+ 0x68, 0x61, 0x75, 0x0D, 0x63, 0x6C, 0x64,
+ 0x6D, 0x6F, 0x67, 0x2E, 0x62, 0x66, 0x53,
+ 0x2C, 0x77, 0x45, 0x7A, 0x6B, 0x44, 0x76,
+ 0x9C, 0x47, 0x1E, 0x1F
+};
+
+const byte cryptoArr30De[32] = {
+ 0x49, 0x4D, 0x21, 0x42, 0x4C, 0x70, 0x41, 0x52,
+ 0x57, 0x4E, 0x48, 0x3F, 0x46, 0x50, 0x55, 0x4B,
+ 0x5A, 0x4A, 0x54, 0x31, 0x4F, 0x56, 0x79, 0x3A,
+ 0x6A, 0x5B, 0x5D, 0x40, 0x22, 0x2F, 0x30, 0x35
+};
+
+const byte cryptoArr31De[32]= {
+ 0x78, 0x2D, 0x32, 0x82, 0x43, 0x39, 0x33, 0x38,
+ 0x7C, 0x27, 0x37, 0x3B, 0x25, 0x28, 0x29, 0x36,
+ 0x51, 0x59, 0x71, 0x81, 0x87, 0x88, 0x93, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const byte *cryptoArrDefault, *cryptoArr30, *cryptoArr31;
+uint16 ctrlChar;
+
+/**
+ * Decrypt the next character
+ * @param c OUT, next decrypted char
+ * @param idx IN/OUT, current buffer index
+ * @param pt IN/OUT, current encryption point
+ * @return a boolean specifying if a stop character has been encountered
+ * @remarks Originally called 'cinq_huit'
+ */
+bool MortevielleEngine::decryptNextChar(char &c, int &idx, byte &pt) {
+ uint16 oct, ocd;
+
+ /* 5-8 */
+ oct = _dialogIndexArray[idx];
+ oct = ((uint16)(oct << (16 - pt))) >> (16 - pt);
+ if (pt < 6) {
+ ++idx;
+ oct = oct << (5 - pt);
+ pt += 11;
+ oct = oct | ((uint)_dialogIndexArray[idx] >> pt);
+ } else {
+ pt -= 5;
+ oct = (uint)oct >> pt;
+ }
+
+ if (oct == ctrlChar) {
+ c = '$';
+ return true;
+ } else if (oct == 30 || oct == 31) {
+ ocd = _dialogIndexArray[idx];
+ ocd = (uint16)(ocd << (16 - pt)) >> (16 - pt);
+ if (pt < 6) {
+ ++idx;
+ ocd = ocd << (5 - pt);
+ pt += 11;
+ ocd = ocd | ((uint)_dialogIndexArray[idx] >> pt);
+ } else {
+ pt -= 5;
+ ocd = (uint)ocd >> pt;
+ }
+
+ if (oct == 30)
+ c = (unsigned char)cryptoArr30[ocd];
+ else
+ c = (unsigned char)cryptoArr31[ocd];
+
+ if (c == '\0') {
+ c = '#';
+ return true;
+ }
+ } else {
+ c = (unsigned char)cryptoArrDefault[oct];
+ }
+ return false;
+}
+
+/**
+ * Decode and extract the line with the given Id
+ * @remarks Originally called 'deline'
+ */
+Common::String MortevielleEngine::getString(int num) {
+ Common::String wrkStr = "";
+
+ if (num < 0) {
+ warning("getString(%d): num < 0! Skipping", num);
+ } else if (!_txxFileFl) {
+ wrkStr = getGameString(num);
+ } else {
+ int hint = _dialogHintArray[num]._hintId;
+ byte point = _dialogHintArray[num]._point;
+ int length = 0;
+ bool endFl = false;
+ char let;
+ do {
+ endFl = decryptNextChar(let, hint, point);
+ wrkStr += let;
+ ++length;
+ } while (!endFl);
+ }
+
+ while (wrkStr.lastChar() == '$')
+ // Remove trailing '$'s
+ wrkStr.deleteLastChar();
+
+ return wrkStr;
+}
+
+void MortevielleEngine::copcha() {
+ for (int i = kAcha; i < kAcha + 390; i++)
+ _tabdon[i] = _tabdon[i + 390];
+}
+
+/**
+ * Engine function - When restarting the game, reset the main variables used by the engine
+ * @remarks Originally called 'inzon'
+ */
+void MortevielleEngine::resetVariables() {
+ copcha();
+
+ _coreVar._alreadyEnteredManor = false;
+ _coreVar._selectedObjectId = 0;
+ _coreVar._cellarObjectId = 0;
+ _coreVar._atticBallHoleObjectId = 0;
+ _coreVar._atticRodHoleObjectId = 0;
+ _coreVar._wellObjectId = 0;
+ _coreVar._secretPassageObjectId = 0;
+ _coreVar._purpleRoomObjectId = 136;
+ _coreVar._cryptObjectId = 141;
+ _coreVar._faithScore = getRandomNumber(4, 10);
+ _coreVar._currPlace = MANOR_FRONT;
+
+ for (int i = 2; i <= 6; ++i)
+ _coreVar._inventory[i] = 0;
+
+ // Only object in inventory: a gun
+ _coreVar._inventory[1] = 113;
+
+ _coreVar._fullHour = (unsigned char)20;
+
+ for (int i = 1; i <= 10; ++i)
+ _coreVar._pctHintFound[i] = ' ';
+
+ for (int i = 1; i <= 6; ++i)
+ _coreVar._availableQuestion[i] = '*';
+
+ for (int i = 7; i <= 9; ++i)
+ _coreVar._availableQuestion[i] = ' ';
+
+ for (int i = 10; i <= 28; ++i)
+ _coreVar._availableQuestion[i] = '*';
+
+ for (int i = 29; i <= 42; ++i)
+ _coreVar._availableQuestion[i] = ' ';
+
+ _coreVar._availableQuestion[33] = '*';
+
+ for (int i = 1; i <= 8; ++i)
+ _charAnswerCount[i] = 0;
+
+ initMaxAnswer();
+}
+
+/**
+ * Engine function - Set the palette
+ * @remarks Originally called 'writepal'
+ */
+void MortevielleEngine::setPal(int n) {
+ switch (_currGraphicalDevice) {
+ case MODE_TANDY:
+ case MODE_EGA:
+ case MODE_AMSTRAD1512:
+ for (int i = 1; i <= 16; ++i) {
+ _curPict[(2 * i)] = _stdPal[n][i].x;
+ _curPict[(2 * i) + 1] = _stdPal[n][i].y;
+ }
+ break;
+ case MODE_CGA: {
+ nhom pal[16];
+ for (int i = 0; i < 16; ++i) {
+ pal[i] = _cgaPal[n]._a[i];
+ }
+
+ if (n < 89)
+ palette(_cgaPal[n]._p);
+
+ for (int i = 0; i <= 15; ++i)
+ displayCGAPattern(i, _patternArr[pal[i]._id], pal);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * Engine function - Display a CGA pattern, using a specified palette
+ * @remarks Originally called 'outbloc'
+ */
+void MortevielleEngine::displayCGAPattern(int n, Pattern p, nhom *pal) {
+ int addr = n * 404 + 0xd700;
+
+ WRITE_LE_UINT16(&_curPict[addr], p._tax);
+ WRITE_LE_UINT16(&_curPict[addr + 2], p._tay);
+ addr += 4;
+ for (int i = 0; i < p._tax; ++i) {
+ for (int j = 0; j < p._tay; ++j)
+ _curPict[addr + j * p._tax + i] = pal[n]._hom[p._des[i + 1][j + 1]];
+ }
+}
+
+/**
+ * Engine function - Load Palette from File
+ * @remarks Originally called 'charpal'
+ */
+void MortevielleEngine::loadPalette() {
+ Common::File f;
+ byte b;
+
+ if (!f.open("fxx.mor")) {
+ if (f.open("mfxx.mor"))
+ f.seek(7 * 25);
+ else
+ error("Missing file - fxx.mor");
+ }
+
+ for (int i = 0; i < 108; ++i)
+ _drawingSizeArr[i] = f.readSint16LE();
+ f.close();
+
+ if (!f.open("plxx.mor"))
+ error("Missing file - plxx.mor");
+ for (int i = 0; i <= 90; ++i) {
+ for (int j = 1; j <= 16; ++j) {
+ _stdPal[i][j].x = f.readByte();
+ _stdPal[i][j].y = f.readByte();
+ }
+ }
+ f.close();
+
+ if (!f.open("cxx.mor"))
+ error("Missing file - cxx.mor");
+
+ for (int j = 0; j <= 90; ++j) {
+ _cgaPal[j]._p = f.readByte();
+ for (int i = 0; i <= 15; ++i) {
+ nhom &with = _cgaPal[j]._a[i];
+
+ b = f.readByte();
+ with._id = (uint)b >> 4;
+ with._hom[0] = ((uint)b >> 2) & 3;
+ with._hom[1] = b & 3;
+ }
+ }
+
+ _cgaPal[10]._a[9] = _cgaPal[10]._a[5];
+ for (int j = 0; j <= 14; ++j) {
+ _patternArr[j]._tax = f.readByte();
+ _patternArr[j]._tay = f.readByte();
+ for (int i = 1; i <= 20; ++i) {
+ for (int k = 1; k <= 20; ++k)
+ _patternArr[j]._des[i][k] = f.readByte();
+ }
+ }
+ f.close();
+}
+
+/**
+ * Engine function - Load Texts from File
+ * @remarks Originally called 'chartex'
+ */
+void MortevielleEngine::loadTexts() {
+ Common::File inpFile;
+ Common::File ntpFile;
+
+ _txxFileFl = false;
+ if (getLanguage() == Common::EN_ANY) {
+ warning("English version expected - Switching to DAT file");
+ return;
+ }
+
+ if (!inpFile.open("TXX.INP")) {
+ if (!inpFile.open("TXX.MOR")) {
+ warning("Missing file - TXX.INP or .MOR - Switching to DAT file");
+ return;
+ }
+ }
+ if (ntpFile.open("TXX.NTP")) {
+ cryptoArr30 = cryptoArr30Fr;
+ cryptoArr31 = cryptoArr31Fr;
+ cryptoArrDefault = cryptoArrDefaultFr;
+ ctrlChar = 11;
+ } else if (ntpFile.open("TXX.IND")) {
+ cryptoArr30 = cryptoArr30De;
+ cryptoArr31 = cryptoArr31De;
+ cryptoArrDefault = cryptoArrDefaultDe;
+ ctrlChar = 10;
+ } else {
+ warning("Missing file - TXX.NTP or .IND - Switching to DAT file");
+ return;
+ }
+
+ if ((inpFile.size() > (kMaxDialogIndex * 2)) || (ntpFile.size() > (kMaxDialogHint * 3))) {
+ warning("TXX file - Unexpected format - Switching to DAT file");
+ return;
+ }
+
+ for (int i = 0; i < inpFile.size() / 2; ++i)
+ _dialogIndexArray[i] = inpFile.readUint16LE();
+
+ inpFile.close();
+ _txxFileFl = true;
+
+ for (int i = 0; i < (ntpFile.size() / 3); ++i) {
+ _dialogHintArray[i]._hintId = ntpFile.readSint16LE();
+ _dialogHintArray[i]._point = ntpFile.readByte();
+ }
+
+ ntpFile.close();
+
+}
+
+void MortevielleEngine::loadBRUIT5() {
+ Common::File f;
+
+ if (!f.open("bruit5"))
+ error("Missing file - bruit5");
+
+ free(_speechManager._noise5Buf);
+ _speechManager._noise5Size = f.size();
+ _speechManager._noise5Buf = (byte *)malloc(sizeof(byte) * _speechManager._noise5Size);
+ f.read(_speechManager._noise5Buf, _speechManager._noise5Size);
+ f.close();
+}
+
+void MortevielleEngine::loadCFIEC() {
+ Common::File f;
+
+ if (!f.open("cfiec.mor")) {
+ if (!f.open("alcfiec.mor"))
+ error("Missing file - *cfiec.mor");
+ }
+
+ _cfiecBufferSize = ((f.size() / 128) + 1) * 128;
+ int32 fileSize = f.size();
+
+ if (!_reloadCFIEC)
+ _cfiecBuffer = (byte *)malloc(sizeof(byte) * _cfiecBufferSize);
+
+ for (int32 i = 0; i < fileSize; ++i)
+ _cfiecBuffer[i] = f.readByte();
+
+ for (int i = fileSize; i < _cfiecBufferSize; i++)
+ _cfiecBuffer[i] = 0;
+
+ f.close();
+
+ _reloadCFIEC = false;
+}
+
+
+void MortevielleEngine::loadCFIPH() {
+ Common::File f;
+
+ if (!f.open("cfiph.mor")) {
+ if (!f.open("alcfiph.mor"))
+ error("Missing file - *cfiph.mor");
+ }
+
+ _speechManager._cfiphBuffer = (uint16 *)malloc(sizeof(uint16) * (f.size() / 2));
+
+ for (int i = 0; i < (f.size() / 2); ++i)
+ _speechManager._cfiphBuffer[i] = f.readUint16BE();
+
+ f.close();
+}
+
+/**
+ * Engine function - Play Music
+ * @remarks Originally called 'music'
+ */
+void MortevielleEngine::music() {
+ if (_soundOff)
+ return;
+
+ _reloadCFIEC = true;
+
+ Common::File f;
+ if (!f.open("mort.img"))
+ error("Missing file - mort.img");
+
+ free(_compMusicBuf2);
+ int size = f.size();
+ _compMusicBuf2 = (byte *)malloc(sizeof(byte) * size);
+ f.read(_compMusicBuf2, size);
+ f.close();
+
+ _soundManager.decodeMusic(_compMusicBuf2, &_mem[kAdrMusic * 16], size / 128);
+ _addFix = (float)((kTempoMusic - 8)) / 256;
+ _speechManager.cctable(_speechManager._tbi);
+
+ bool fin = false;
+ int k = 0;
+ do {
+ fin = keyPressed();
+ _soundManager.musyc(_speechManager._tbi, 9958, kTempoMusic);
+ ++k;
+ fin = fin | keyPressed() | (k >= 5);
+ } while (!fin);
+ while (keyPressed())
+ getChar();
+}
+
+/**
+ * Engine function - Show title screen
+ * @remarks Originally called 'suite'
+ */
+void MortevielleEngine::showTitleScreen() {
+ hirs();
+ handleDescriptionText(7, 2035);
+ _caff = 51;
+ _text.taffich();
+ testKeyboard();
+ if (_newGraphicalDevice != _currGraphicalDevice)
+ _currGraphicalDevice = _newGraphicalDevice;
+ hirs();
+ draw(0, 0);
+
+ Common::String cpr = "COPYRIGHT 1989 : LANKHOR";
+ _screenSurface.putxy(104 + 72 * _resolutionScaler, 185);
+ _screenSurface.drawString(cpr, 0);
+}
+
+/**
+ * Draw picture
+ * @remarks Originally called 'dessine'
+ */
+void MortevielleEngine::draw(int x, int y) {
+ _mouse.hideMouse();
+ setPal(_numpal);
+ displayPicture(_curPict, x, y);
+ _mouse.showMouse();
+}
+
+/**
+ * Draw right frame
+ * @remarks Originally called 'dessine_rouleau'
+ */
+void MortevielleEngine::drawRightFrame() {
+ setPal(89);
+ if (_currGraphicalDevice == MODE_HERCULES)
+ _curPict[14] = 15;
+
+ _mouse.hideMouse();
+ displayPicture(_rightFramePict, 0, 0);
+ _mouse.showMouse();
+}
+
+/**
+ * Read the current system time
+ */
+int MortevielleEngine::readclock() {
+ TimeDate dateTime;
+ g_system->getTimeAndDate(dateTime);
+
+ int m = dateTime.tm_min * 60;
+ int h = dateTime.tm_hour * 3600;
+ return h + m + dateTime.tm_sec;
+}
+
+/**
+ * Engine function - Prepare room and hint string
+ * @remarks Originally called 'tinke'
+ */
+void MortevielleEngine::prepareRoom() {
+ int day, hour, minute;
+
+ _anyone = false;
+ updateHour(day, hour, minute);
+ if (day != _day) {
+ _day = day;
+ for (int i = 0; i < 9; i++) {
+ if (_charAnswerMax[i] > 0)
+ --_charAnswerMax[i];
+ _charAnswerCount[i] = 0;
+ }
+ }
+ if ((hour > _hour) || ((hour == 0) && (_hour == 23))) {
+ _hour = hour;
+ _minute = 0;
+ drawClock();
+ int hintCount = 0;
+ for (int i = 1; i <= 10; ++i) {
+ if (_coreVar._pctHintFound[i] == '*')
+ ++hintCount;
+ }
+
+ Common::String pctStr;
+ if (hintCount == 10)
+ pctStr = "10";
+ else
+ pctStr = (unsigned char)(hintCount + 48);
+
+ _hintPctMessage = "[1][";
+ _hintPctMessage += getEngineString(S_SHOULD_HAVE_NOTICED);
+ _hintPctMessage += pctStr;
+ _hintPctMessage += '0';
+ _hintPctMessage += getEngineString(S_NUMBER_OF_HINTS);
+ _hintPctMessage += "][";
+ _hintPctMessage += getEngineString(S_OKAY);
+ _hintPctMessage += ']';
+ }
+ if (minute > _minute) {
+ _minute = 30;
+ drawClock();
+ }
+ if (_mouse._pos.y < 12)
+ return;
+
+ if (!_blo) {
+ if ((hour == 12) || ((hour > 18) && (hour < 21)) || ((hour >= 0) && (hour < 7)))
+ _inGameHourDuration = kTime2;
+ else
+ _inGameHourDuration = kTime1;
+ if ((_coreVar._faithScore > 33) && (_coreVar._faithScore < 66))
+ _inGameHourDuration -= (_inGameHourDuration / 3);
+
+ if (_coreVar._faithScore > 65)
+ _inGameHourDuration -= ((_inGameHourDuration / 3) * 2);
+
+ int newHour = readclock();
+ if ((newHour - _currentDayHour) > _inGameHourDuration) {
+ bool activeMenu = _menu._menuActive;
+ _menu.eraseMenu();
+ _currentHourCount += ((newHour - _currentDayHour) / _inGameHourDuration);
+ _currentDayHour = newHour;
+ switch (_place) {
+ case GREEN_ROOM:
+ case DARKBLUE_ROOM:
+ setRandomPresenceGreenRoom(_coreVar._faithScore);
+ break;
+ case PURPLE_ROOM:
+ setRandomPresencePurpleRoom(_coreVar._faithScore);
+ break;
+ case BLUE_ROOM:
+ setRandomPresenceBlueRoom(_coreVar._faithScore);
+ break;
+ case RED_ROOM:
+ case GREEN_ROOM2:
+ setRandomPresenceRedRoom(_coreVar._faithScore);
+ break;
+ case ROOM9:
+ setRandomPresenceRoom9(_coreVar._faithScore);
+ break;
+ case DINING_ROOM:
+ setRandomPresenceDiningRoom(_coreVar._faithScore);
+ break;
+ case BUREAU:
+ setRandomPresenceBureau(_coreVar._faithScore);
+ break;
+ case KITCHEN:
+ setRandomPresenceKitchen(_coreVar._faithScore);
+ break;
+ case ATTIC:
+ case CELLAR:
+ setRandomPresenceAttic(_coreVar._faithScore);
+ break;
+ case LANDING:
+ case ROOM26:
+ setRandomPresenceLanding(_coreVar._faithScore);
+ break;
+ case CHAPEL:
+ setRandomPresenceChapel(_coreVar._faithScore);
+ break;
+ }
+ if ((_savedBitIndex != 0) && (_currBitIndex != 10))
+ _savedBitIndex = _currBitIndex;
+
+ if ((_savedBitIndex == 0) && (_currBitIndex > 0)) {
+ if ((_coreVar._currPlace == ATTIC) || (_coreVar._currPlace == CELLAR)) {
+ initCaveOrCellar();
+ } else if (_currBitIndex == 10) {
+ _currBitIndex = 0;
+ if (!_uptodatePresence) {
+ _uptodatePresence = true;
+ _startHour = readclock();
+ if (getRandomNumber(1, 5) < 5) {
+ clearVerbBar();
+ prepareScreenType2();
+ displayTextInVerbBar(getEngineString(S_HEAR_NOISE));
+ int rand = (getRandomNumber(0, 4)) - 2;
+ _speechManager.startSpeech(1, rand, 1);
+ clearVerbBar();
+ }
+ }
+ }
+ }
+
+ if (activeMenu)
+ _menu.drawMenu();
+ }
+ }
+ _endHour = readclock();
+ if ((_uptodatePresence) && ((_endHour - _startHour) > 17)) {
+ getPresenceBitIndex(_place);
+ _uptodatePresence = false;
+ _startHour = 0;
+ if ((_coreVar._currPlace > OWN_ROOM) && (_coreVar._currPlace < DINING_ROOM))
+ _anyone = true;
+ }
+}
+
+/**
+ * Engine function - Draw Clock
+ * @remarks Originally called 'pendule'
+ */
+void MortevielleEngine::drawClock() {
+ const int cv[2][12] = {
+ { 5, 8, 10, 8, 5, 0, -5, -8, -10, -8, -5, 0 },
+ { -5, -3, 0, 3, 5, 6, 5, 3, 0, -3, -5, -6 }
+ };
+ const int x = 580;
+ const int y = 123;
+ const int rg = 9;
+ int hourColor;
+
+ _mouse.hideMouse();
+
+ _screenSurface.drawRectangle(570, 118, 20, 10);
+ _screenSurface.drawRectangle(578, 114, 6, 18);
+ if ((_currGraphicalDevice == MODE_CGA) || (_currGraphicalDevice == MODE_HERCULES))
+ hourColor = 0;
+ else
+ hourColor = 1;
+
+ if (_minute == 0)
+ _screenSurface.drawLine(((uint)x >> 1) * _resolutionScaler, y, ((uint)x >> 1) * _resolutionScaler, (y - rg), hourColor);
+ else
+ _screenSurface.drawLine(((uint)x >> 1) * _resolutionScaler, y, ((uint)x >> 1) * _resolutionScaler, (y + rg), hourColor);
+
+ int hour12 = _hour;
+ if (hour12 > 12)
+ hour12 -= 12;
+ if (hour12 == 0)
+ hour12 = 12;
+
+ _screenSurface.drawLine(((uint)x >> 1) * _resolutionScaler, y, ((uint)(x + cv[0][hour12 - 1]) >> 1) * _resolutionScaler, y + cv[1][hour12 - 1], hourColor);
+ _mouse.showMouse();
+ _screenSurface.putxy(568, 154);
+
+ if (_hour > 11)
+ _screenSurface.drawString("PM ", 1);
+ else
+ _screenSurface.drawString("AM ", 1);
+
+ _screenSurface.putxy(550, 160);
+ if ((_day >= 0) && (_day <= 8)) {
+ Common::String tmp = getEngineString(S_DAY);
+ tmp.insertChar((char)(_day + 49), 0);
+ _screenSurface.drawString(tmp, 1);
+ }
+}
+
+void MortevielleEngine::palette(int v1) {
+ warning("TODO: palette");
+}
+
+/**
+ * Returns a substring of the given string
+ * @param s Source string
+ * @param idx Starting index (1 based)
+ * @param size Number of characters to return
+ */
+
+Common::String MortevielleEngine::copy(const Common::String &s, int idx, size_t size) {
+ assert(idx + size < s.size());
+
+ // Copy the substring into a temporary buffer
+ char *tmp = new char[size + 1];
+ strncpy(tmp, s.c_str() + idx - 1, size);
+ tmp[size] = '\0';
+
+ Common::String result(tmp);
+ delete[] tmp;
+ return result;
+}
+
+void MortevielleEngine::hirs() {
+ // Note: The original used this to set the graphics mode and clear the screen, both at
+ // the start of the game, and whenever the screen need to be cleared. As such, this
+ // method is deprecated in favour of clearing the screen
+ debugC(1, kMortevielleCore, "TODO: hirs is deprecated in favour of ScreenSurface::clearScreen");
+
+ if (_currGraphicalDevice == MODE_TANDY) {
+ _screenSurface.fillRect(0, Common::Rect(0, 0, 639, 200));
+ _resolutionScaler = 1;
+ } else if (_currGraphicalDevice == MODE_CGA) {
+ palette(1);
+ _resolutionScaler = 1;
+ } else
+ _resolutionScaler = 2;
+
+ _screenSurface.clearScreen();
+}
+
+/**
+ * Init room : Cave or Cellar
+ * @remarks Originally called 'cavegre'
+ */
+void MortevielleEngine::initCaveOrCellar() {
+ _coreVar._faithScore += 2;
+ if (_coreVar._faithScore > 69)
+ _coreVar._faithScore += (_coreVar._faithScore / 10);
+ clearVerbBar();
+ prepareScreenType2();
+ displayTextInVerbBar(getEngineString(S_SOMEONE_ENTERS));
+ int rand = (getRandomNumber(0, 4)) - 2;
+ _speechManager.startSpeech(2, rand, 1);
+
+ // The original was doing here a useless loop.
+ // It has been removed
+
+ clearVerbBar();
+ displayAloneText();
+}
+
+/**
+ * Display control menu string
+ * @remarks Originally called 'tctrm'
+ */
+void MortevielleEngine::displayControlMenu() {
+ handleDescriptionText(2, (3000 + _controlMenu));
+ _controlMenu = 0;
+}
+
+/**
+ * Display picture at a given coordinate
+ * @remarks Originally called 'pictout'
+ */
+void MortevielleEngine::displayPicture(const byte *pic, int x, int y) {
+ GfxSurface surface;
+ surface.decode(pic);
+
+ if (_currGraphicalDevice == MODE_HERCULES) {
+ _curPict[2] = 0;
+ _curPict[32] = 15;
+ }
+
+ _screenSurface.drawPicture(surface, x, y);
+}
+
+void MortevielleEngine::adzon() {
+ Common::File f;
+
+ if (!f.open("don.mor"))
+ error("Missing file - don.mor");
+
+ f.read(_tabdon, 7 * 256);
+ f.close();
+
+ if (!f.open("bmor.mor"))
+ error("Missing file - bmor.mor");
+
+ f.read(&_tabdon[kFleche], 1916);
+ f.close();
+
+ // Read Right Frame Drawing
+ if (!f.open("dec.mor"))
+ error("Missing file - dec.mor");
+
+ free(_rightFramePict);
+ _rightFramePict = (byte *)malloc(sizeof(byte) * f.size());
+ f.read(_rightFramePict, f.size());
+ f.close();
+}
+
+/**
+ * Returns the offset within the compressed image data resource of the desired image
+ * @remarks Originally called 'animof'
+ */
+int MortevielleEngine::getAnimOffset(int frameNum, int animNum) {
+ int animCount = _curAnim[1];
+ int aux = animNum;
+ if (frameNum != 1)
+ aux += animCount;
+
+ return (animCount << 2) + 2 + READ_BE_UINT16(&_curAnim[aux << 1]);
+}
+
+/**
+ * Display text in description bar
+ * @remarks Originally called 'text1'
+ */
+void MortevielleEngine::displayTextInDescriptionBar(int x, int y, int nb, int mesgId) {
+ int co;
+
+ if (_resolutionScaler == 1)
+ co = 10;
+ else
+ co = 6;
+ Common::String tmpStr = getString(mesgId);
+ if ((y == 182) && ((int) tmpStr.size() * co > nb * 6))
+ y = 176;
+ _text.displayStr(tmpStr, x, y, nb, 20, _textColor);
+}
+
+/**
+ * Display description text
+ * @remarks Originally called 'repon'
+ */
+void MortevielleEngine::handleDescriptionText(int f, int mesgId) {
+ if ((mesgId > 499) && (mesgId < 563)) {
+ Common::String tmpStr = getString(mesgId - 501 + kInventoryStringIndex);
+
+ if ((int) tmpStr.size() > ((58 + (_resolutionScaler - 1) * 37) << 1))
+ _largestClearScreen = true;
+ else
+ _largestClearScreen = false;
+
+ clearDescriptionBar();
+ _text.displayStr(tmpStr, 8, 176, 85, 3, 5);
+ } else {
+ mapMessageId(mesgId);
+ switch (f) {
+ case 2:
+ case 8:
+ clearDescriptionBar();
+ prepareScreenType2();
+ displayTextInDescriptionBar(8, 182, 103, mesgId);
+ if ((mesgId == 68) || (mesgId == 69))
+ _coreVar._availableQuestion[40] = '*';
+ if ((mesgId == 104) && (_caff == CELLAR)) {
+ _coreVar._availableQuestion[36] = '*';
+ if (_coreVar._availableQuestion[39] == '*') {
+ _coreVar._pctHintFound[3] = '*';
+ _coreVar._availableQuestion[38] = '*';
+ }
+ }
+ break;
+ case 1:
+ case 6:
+ case 9: {
+ int i;
+ if ((f == 1) || (f == 6))
+ i = 4;
+ else
+ i = 5;
+
+ Common::String tmpStr = getString(mesgId);
+ _text.displayStr(tmpStr, 80, 40, 60, 25, i);
+
+ if (mesgId == 180)
+ _coreVar._pctHintFound[6] = '*';
+ else if (mesgId == 179)
+ _coreVar._pctHintFound[10] = '*';
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * Recompute message Id
+ * @remarks Originally called 'modif'
+ */
+void MortevielleEngine::mapMessageId(int &mesgId) {
+ if (mesgId == 26)
+ mesgId = 25;
+ else if ((mesgId > 29) && (mesgId < 36))
+ mesgId -= 4;
+ else if ((mesgId > 69) && (mesgId < 78))
+ mesgId -= 37;
+ else if ((mesgId > 99) && (mesgId < 194))
+ mesgId -= 59;
+ else if ((mesgId > 996) && (mesgId < 1000))
+ mesgId -= 862;
+ else if ((mesgId > 1500) && (mesgId < 1507))
+ mesgId -= 1363;
+ else if ((mesgId > 1507) && (mesgId < 1513))
+ mesgId -= 1364;
+ else if ((mesgId > 1999) && (mesgId < 2002))
+ mesgId -= 1851;
+ else if (mesgId == 2010)
+ mesgId = 151;
+ else if ((mesgId > 2011) && (mesgId < 2025))
+ mesgId -= 1860;
+ else if (mesgId == 2026)
+ mesgId = 165;
+ else if ((mesgId > 2029) && (mesgId < 2037))
+ mesgId -= 1864;
+ else if ((mesgId > 3000) && (mesgId < 3005))
+ mesgId -= 2828;
+ else if (mesgId == 4100)
+ mesgId = 177;
+ else if (mesgId == 4150)
+ mesgId = 178;
+ else if ((mesgId > 4151) && (mesgId < 4156))
+ mesgId -= 3973;
+ else if (mesgId == 4157)
+ mesgId = 183;
+ else if ((mesgId == 4160) || (mesgId == 4161))
+ mesgId -= 3976;
+}
+
+/**
+ * Initialize open objects array
+ * @remarks Originally called 'initouv'
+ */
+void MortevielleEngine::resetOpenObjects() {
+ for (int cx = 1; cx <= 7; ++cx)
+ _openObjects[cx] = 0;
+ _openObjCount = 0;
+}
+
+void MortevielleEngine::ecr2(Common::String text) {
+ // Some dead code was present in the original: removed
+ _screenSurface.putxy(8, 177);
+ int tlig = 59 + (_resolutionScaler - 1) * 36;
+
+ if ((int)text.size() < tlig)
+ _screenSurface.drawString(text, 5);
+ else if ((int)text.size() < (tlig << 1)) {
+ _screenSurface.putxy(8, 176);
+ _screenSurface.drawString(copy(text, 1, (tlig - 1)), 5);
+ _screenSurface.putxy(8, 182);
+ _screenSurface.drawString(copy(text, tlig, tlig << 1), 5);
+ } else {
+ _largestClearScreen = true;
+ clearDescriptionBar();
+ _screenSurface.putxy(8, 176);
+ _screenSurface.drawString(copy(text, 1, (tlig - 1)), 5);
+ _screenSurface.putxy(8, 182);
+ _screenSurface.drawString(copy(text, tlig, ((tlig << 1) - 1)), 5);
+ _screenSurface.putxy(8, 190);
+ _screenSurface.drawString(copy(text, tlig << 1, tlig * 3), 5);
+ }
+}
+
+void MortevielleEngine::displayTextInVerbBar(Common::String text) {
+ clearVerbBar();
+ _screenSurface.putxy(8, 192);
+ _screenSurface.drawString(text, 5);
+}
+
+/**
+ * Display item in hand
+ * @remarks Originally called 'modobj'
+ */
+void MortevielleEngine::displayItemInHand(int objId) {
+ Common::String strp = Common::String(' ');
+
+ if (objId != 500)
+ strp = getString(objId - 501 + kInventoryStringIndex);
+
+ _menu.setText(_menu._inventoryMenu[8]._menuId, _menu._inventoryMenu[8]._actionId, strp);
+ _menu.disableMenuItem(_menu._inventoryMenu[8]._menuId, _menu._inventoryMenu[8]._actionId);
+}
+
+/**
+ * Display empty hand
+ * @remarks Originally called 'maivid'
+ */
+void MortevielleEngine::displayEmptyHand() {
+ _coreVar._selectedObjectId = 0;
+ displayItemInHand(500);
+}
+
+/**
+ * Set a random presence: Leo or Max
+ * @remarks Originally called 'chlm'
+ */
+int MortevielleEngine::checkLeoMaxRandomPresence() {
+ int retval = getRandomNumber(1, 2);
+ if (retval == 2)
+ retval = 128;
+
+ return retval;
+}
+
+/**
+ * Reset room variables
+ * @remarks Originally called 'debloc'
+ */
+void MortevielleEngine::resetRoomVariables(int roomId) {
+ _num = 0;
+ _x = 0;
+ _y = 0;
+ if ((roomId != ROOM26) && (roomId != LANDING))
+ resetPresenceInRooms(roomId);
+ _savedBitIndex = _currBitIndex;
+}
+
+/**
+ * Compute presence stats
+ * @remarks Originally called 'ecfren'
+ */
+int MortevielleEngine::getPresenceStats(int &rand, int faithScore, int roomId) {
+ if (roomId == OWN_ROOM)
+ displayAloneText();
+ int retVal = -500;
+ rand = 0;
+ if ( ((roomId == GREEN_ROOM) && (!_roomPresenceLuc) && (!_roomPresenceIda))
+ || ((roomId == DARKBLUE_ROOM) && (!_roomPresenceGuy) && (!_roomPresenceEva)) )
+ retVal = getPresenceStatsGreenRoom();
+ if ((roomId == PURPLE_ROOM) && (!_purpleRoomPresenceLeo) && (!_room9PresenceLeo))
+ retVal = getPresenceStatsPurpleRoom();
+ if ( ((roomId == TOILETS) && (!_toiletsPresenceBobMax))
+ || ((roomId == BATHROOM) && (!_bathRoomPresenceBobMax)) )
+ retVal = getPresenceStatsToilets();
+ if ((roomId == BLUE_ROOM) && (!_roomPresenceMax))
+ retVal = getPresenceStatsBlueRoom();
+ if ( ((roomId == RED_ROOM) && (!_roomPresenceBob))
+ || ((roomId == GREEN_ROOM2) && (!_roomPresencePat)))
+ retVal = getPresenceStatsRedRoom();
+ if ((roomId == ROOM9) && (!_room9PresenceLeo) && (!_purpleRoomPresenceLeo))
+ retVal = 10;
+ if ( ((roomId == PURPLE_ROOM) && (_room9PresenceLeo))
+ || ((roomId == ROOM9) && (_purpleRoomPresenceLeo)))
+ retVal = -400;
+ if (retVal != -500) {
+ retVal += faithScore;
+ rand = getRandomNumber(1, 100);
+ }
+
+ return retVal;
+}
+
+/**
+ * Set presence flags
+ * @remarks Originally called 'becfren'
+ */
+void MortevielleEngine::setPresenceFlags(int roomId) {
+ if ((roomId == GREEN_ROOM) || (roomId == DARKBLUE_ROOM)) {
+ int rand = getRandomNumber(1, 2);
+ if (roomId == GREEN_ROOM) {
+ if (rand == 1)
+ _roomPresenceLuc = true;
+ else
+ _roomPresenceIda = true;
+ } else { // roomId == DARKBLUE_ROOM
+ if (rand == 1)
+ _roomPresenceGuy = true;
+ else
+ _roomPresenceEva = true;
+ }
+ } else if (roomId == PURPLE_ROOM)
+ _purpleRoomPresenceLeo = true;
+ else if (roomId == TOILETS)
+ _toiletsPresenceBobMax = true;
+ else if (roomId == BLUE_ROOM)
+ _roomPresenceMax = true;
+ else if (roomId == RED_ROOM)
+ _roomPresenceBob = true;
+ else if (roomId == BATHROOM)
+ _bathRoomPresenceBobMax = true;
+ else if (roomId == GREEN_ROOM2)
+ _roomPresencePat = true;
+ else if (roomId == ROOM9)
+ _room9PresenceLeo = true;
+}
+
+/**
+ * Initialize max answers per character
+ * @remarks Originally called 'init_nbrepm'
+ */
+void MortevielleEngine::initMaxAnswer() {
+ static const byte maxAnswer[9] = { 0, 4, 5, 6, 7, 5, 6, 5, 8 };
+
+ for (int idx = 0; idx < 9; ++idx)
+ _charAnswerMax[idx] = maxAnswer[idx];
+}
+
+/**
+ * Get Presence
+ * @remarks Originally called 't11'
+ */
+int MortevielleEngine::getPresence(int roomId) {
+ int retVal = 0;
+ int rand;
+
+ int p = getPresenceStats(rand, _coreVar._faithScore, roomId);
+ _place = roomId;
+ if ((roomId > OWN_ROOM) && (roomId < DINING_ROOM)) {
+ if (p != -500) {
+ if (rand > p) {
+ displayAloneText();
+ retVal = 0;
+ } else {
+ setPresenceFlags(_place);
+ retVal = getPresenceBitIndex(_place);
+ }
+ } else
+ retVal = getPresenceBitIndex(_place);
+ }
+
+ if (roomId > ROOM9) {
+ if ((roomId > LANDING) && (roomId != CHAPEL) && (roomId != ROOM26))
+ displayAloneText();
+ else {
+ int h = 0;
+ if (roomId == DINING_ROOM)
+ p = getPresenceStatsDiningRoom(h);
+ else if (roomId == BUREAU)
+ p = getPresenceStatsBureau(h);
+ else if (roomId == KITCHEN)
+ p = getPresenceStatsKitchen();
+ else if ((roomId == ATTIC) || (roomId == CELLAR))
+ p = getPresenceStatsAttic();
+ else if ((roomId == LANDING) || (roomId == ROOM26))
+ p = getPresenceStatsLanding();
+ else if (roomId == CHAPEL)
+ p = getPresenceStatsChapel(h);
+ p += _coreVar._faithScore;
+ rand = getRandomNumber(1, 100);
+ if (rand > p) {
+ displayAloneText();
+ retVal = 0;
+ } else {
+ if (roomId == DINING_ROOM)
+ p = setPresenceDiningRoom(h);
+ else if (roomId == BUREAU)
+ p = setPresenceBureau(h);
+ else if ((roomId == KITCHEN) || (roomId == ATTIC) || (roomId == CELLAR))
+ p = setPresenceKitchen();
+ else if ((roomId == LANDING) || (roomId == ROOM26))
+ p = setPresenceLanding();
+ else if (roomId == CHAPEL)
+ p = setPresenceChapel(h);
+ retVal = p;
+ }
+ }
+ }
+
+ return retVal;
+}
+
+/**
+ * Display Question String
+ * @remarks Originally called 'writetp'
+ */
+void MortevielleEngine::displayQuestionText(Common::String s, int cmd) {
+ if (_resolutionScaler == 2)
+ _screenSurface.drawString(s, cmd);
+ else
+ _screenSurface.drawString(copy(s, 1, 25), cmd);
+}
+
+/**
+ * Display animation frame
+ * @remarks Originally called 'aniof'
+ */
+void MortevielleEngine::displayAnimFrame(int frameNum, int animId) {
+ if ((_caff == BATHROOM) && ((animId == 4) || (animId == 5)))
+ return;
+
+ if ((_caff == DINING_ROOM) && (animId == 7))
+ animId = 6;
+ else if (_caff == KITCHEN) {
+ if (animId == 3)
+ animId = 4;
+ else if (animId == 4)
+ animId = 3;
+ }
+
+ int offset = getAnimOffset(frameNum, animId);
+
+ GfxSurface surface;
+ surface.decode(&_curAnim[offset]);
+ _screenSurface.drawPicture(surface, 0, 12);
+
+ prepareScreenType1();
+}
+
+/**
+ * Draw Picture
+ * @remarks Originally called 'dessin'
+ */
+void MortevielleEngine::drawPicture() {
+ clearUpperLeftPart();
+ if (_caff > 99) {
+ draw(60, 33);
+ _screenSurface.drawBox(118, 32, 291, 122, 15); // Medium box
+ } else if (_caff > 69) {
+ draw(112, 48); // Heads
+ _screenSurface.drawBox(222, 47, 155, 92, 15);
+ } else {
+ draw(0, 12);
+ prepareScreenType1();
+ if ((_caff < 30) || (_caff > 32)) {
+ for (int cx = 1; cx <= 6; ++cx) {
+ if (_openObjects[cx] != 0)
+ displayAnimFrame(1, _openObjects[cx]);
+ }
+
+ if (_caff == ATTIC) {
+ if (_coreVar._atticBallHoleObjectId == 141)
+ displayAnimFrame(1, 7);
+
+ if (_coreVar._atticRodHoleObjectId == 159)
+ displayAnimFrame(1, 6);
+ } else if ((_caff == CELLAR) && (_coreVar._cellarObjectId == 151))
+ displayAnimFrame(1, 2);
+ else if ((_caff == SECRET_PASSAGE) && (_coreVar._secretPassageObjectId == 143))
+ displayAnimFrame(1, 1);
+ else if ((_caff == WELL) && (_coreVar._wellObjectId != 0))
+ displayAnimFrame(1, 1);
+ }
+
+ if (_caff < ROOM26)
+ startMusicOrSpeech(1);
+ }
+}
+
+void MortevielleEngine::drawPictureWithText() {
+ _text.taffich();
+ drawPicture();
+ _destinationOk = false;
+}
+
+/**
+ * Engine function - Place
+ * @remarks Originally called 'tkey1'
+ */
+void MortevielleEngine::testKey(bool d) {
+ bool quest = false;
+ int x, y;
+ bool click;
+
+ _mouse.hideMouse();
+ displayStatusInDescriptionBar('K');
+
+ // Wait for release from any key or mouse button
+ while (keyPressed())
+ _key = gettKeyPressed();
+
+ do {
+ _mouse.getMousePosition(x, y, click);
+ keyPressed();
+ } while (click);
+
+ // Event loop
+ do {
+ if (d)
+ prepareRoom();
+ quest = keyPressed();
+ _mouse.getMousePosition(x, y, click);
+ if (shouldQuit())
+ return;
+ } while (!(quest || (click) || (d && _anyone)));
+ if (quest)
+ gettKeyPressed();
+ setMouseClick(false);
+ _mouse.showMouse();
+}
+
+void MortevielleEngine::tlu(int af, int ob) {
+ _caff = 32;
+ drawPictureWithText();
+ handleDescriptionText(6, ob + 4000);
+ handleDescriptionText(2, 999);
+ testKey(true);
+ _caff = af;
+ _currMenu = OPCODE_NONE;
+ _crep = 998;
+}
+
+/**
+ * Prepare Display Text
+ * @remarks Originally called 'affrep'
+ */
+void MortevielleEngine::prepareDisplayText() {
+ _caff = _coreVar._currPlace;
+ _crep = _coreVar._currPlace;
+}
+
+/**
+ * Exit room
+ * @remarks Originally called 'tsort'
+ */
+void MortevielleEngine::exitRoom() {
+ if ((_openObjCount > 0) && (_coreVar._currPlace != OWN_ROOM)) {
+ if (_coreVar._faithScore < 50)
+ _coreVar._faithScore += 2;
+ else
+ _coreVar._faithScore += (_coreVar._faithScore / 10);
+ }
+
+ resetOpenObjects();
+
+ _roomDoorId = OWN_ROOM;
+ _mchai = 0;
+ resetRoomVariables(_coreVar._currPlace);
+}
+
+/**
+ * get 'read' description
+ * @remarks Originally called 'st4'
+ */
+void MortevielleEngine::getReadDescription(int objId) {
+ _crep = 997;
+
+ switch (objId) {
+ case 114 :
+ _crep = 109;
+ break;
+ case 110 :
+ _crep = 107;
+ break;
+ case 158 :
+ _crep = 113;
+ break;
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ case 156:
+ case 150:
+ case 100:
+ case 157:
+ case 160:
+ case 161 :
+ tlu(_caff, objId);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * get 'search' description
+ * @remarks Originally called 'st7'
+ */
+void MortevielleEngine::getSearchDescription(int objId) {
+ switch (objId) {
+ case 116:
+ case 144:
+ _crep = 104;
+ break;
+ case 126:
+ case 111:
+ _crep = 108;
+ break;
+ case 132:
+ _crep = 111;
+ break;
+ case 142:
+ _crep = 112;
+ break;
+ default:
+ _crep = 183;
+ getReadDescription(objId);
+ }
+}
+
+void MortevielleEngine::mennor() {
+ _menu.menuUp(_currMenu);
+}
+
+void MortevielleEngine::premtet() {
+ draw(10, 80);
+ _screenSurface.drawBox(18, 79, 155, 92, 15);
+}
+
+void MortevielleEngine::ajchai() {
+ int cy = kAcha + ((_mchai - 1) * 10) - 1;
+ int cx = 0;
+ do {
+ ++cx;
+ } while ((cx <= 9) && (_tabdon[cy + cx] != 0));
+
+ if (_tabdon[cy + cx] == 0)
+ _tabdon[cy + cx] = _coreVar._selectedObjectId;
+ else
+ _crep = 192;
+}
+
+/**
+ * Check if inventory is full and, if not, add object in it.
+ * @remarks Originally called 'ajjer'
+ */
+void MortevielleEngine::addObjectToInventory(int objectId) {
+ int i = 0;
+ do {
+ ++i;
+ } while ((i <= 5) && (_coreVar._inventory[i] != 0));
+
+ if (_coreVar._inventory[i] == 0) {
+ _coreVar._inventory[i] = objectId;
+ _menu.setInventoryText();
+ } else
+ // Inventory is full
+ _crep = 139;
+}
+
+/**
+ * Interact with NPC
+ * @remarks Originally called 'quelquun'
+ */
+void MortevielleEngine::interactNPC() {
+ if (_menu._menuDisplayed)
+ _menu.eraseMenu();
+
+ endSearch();
+ _crep = 997;
+L1:
+ if (!_hiddenHero) {
+ if (_crep == 997)
+ _crep = 138;
+ handleDescriptionText(2, _crep);
+ if (_crep == 138)
+ _speechManager.startSpeech(5, 2, 1);
+ else
+ _speechManager.startSpeech(4, 4, 1);
+
+ if (_openObjCount == 0)
+ _coreVar._faithScore += 2;
+ else if (_coreVar._faithScore < 50)
+ _coreVar._faithScore += 4;
+ else
+ _coreVar._faithScore += 3 * (_coreVar._faithScore / 10);
+ exitRoom();
+ _menu.setDestinationText(LANDING);
+ int cx = convertBitIndexToCharacterIndex(_currBitIndex);
+ _caff = 69 + cx;
+ _crep = _caff;
+ _currMenu = MENU_DISCUSS;
+ _currAction = (_menu._discussMenu[cx]._menuId << 8) | _menu._discussMenu[cx]._actionId;
+ _syn = true;
+ _col = true;
+ } else {
+ if (getRandomNumber(1, 3) == 2) {
+ _hiddenHero = false;
+ _crep = 137;
+ goto L1;
+ } else {
+ handleDescriptionText(2, 136);
+ int rand = (getRandomNumber(0, 4)) - 2;
+ _speechManager.startSpeech(3, rand, 1);
+ clearDescriptionBar();
+ displayAloneText();
+ resetRoomVariables(MANOR_FRONT);
+ prepareDisplayText();
+ }
+ }
+ if (_menu._menuDisplayed)
+ _menu.drawMenu();
+}
+
+void MortevielleEngine::tsuiv() {
+ int tbcl;
+ int cy = kAcha + ((_mchai - 1) * 10) - 1;
+ int cx = 0;
+ do {
+ ++cx;
+ ++_searchCount;
+ int cl = cy + _searchCount;
+ tbcl = _tabdon[cl];
+ } while ((tbcl == 0) && (_searchCount <= 9));
+
+ if ((tbcl != 0) && (_searchCount < 11)) {
+ _caff = tbcl;
+ _crep = _caff + 400;
+ if (_currBitIndex != 0)
+ _coreVar._faithScore += 2;
+ } else {
+ prepareDisplayText();
+ endSearch();
+ if (cx > 9)
+ _crep = 131;
+ }
+}
+
+/**
+ * Display Arrow status
+ * @remarks Originally called 'tfleche'
+ */
+void MortevielleEngine::displayStatusArrow() {
+ bool qust;
+ char touch;
+
+ if (_num == 9999)
+ return;
+
+ displayStatusInDescriptionBar((unsigned char)152);
+ bool inRect = false;
+ do {
+ touch = '\0';
+
+ do {
+ _mouse.moveMouse(qust, touch);
+ if (shouldQuit())
+ return;
+
+ if (getMouseClick())
+ inRect = (_mouse._pos.x < 256 * _resolutionScaler) && (_mouse._pos.y < 176) && (_mouse._pos.y > 12);
+ prepareRoom();
+ } while (!(qust || inRect || _anyone));
+
+ if (qust && (touch == '\103'))
+ _dialogManager.show(_hintPctMessage, 1);
+ } while (!((touch == '\73') || ((touch == '\104') && (_x != 0) && (_y != 0)) || (_anyone) || (inRect)));
+
+ if (touch == '\73')
+ _keyPressedEsc = true;
+
+ if (inRect) {
+ _x = _mouse._pos.x;
+ _y = _mouse._pos.y;
+ }
+}
+
+/**
+ * Set coordinates
+ * @remarks Originally called 'tcoord'
+ */
+void MortevielleEngine::setCoordinates(int sx) {
+ int sy, ix, iy;
+ int ib;
+
+
+ _num = 0;
+ _crep = 999;
+ int a = 0;
+ int atdon = kAmzon + 3;
+ int cy = 0;
+ while (cy < _caff) {
+ a += _tabdon[atdon];
+ atdon += 4;
+ ++cy;
+ }
+
+ if (_tabdon[atdon] == 0) {
+ _crep = 997;
+ return;
+ }
+
+ a += kFleche;
+ int cb = 0;
+ for (cy = 0; cy <= (sx - 2); ++cy) {
+ ib = (_tabdon[a + cb] << 8) + _tabdon[(a + cb + 1)];
+ cb += (ib * 4) + 2;
+ }
+ ib = (_tabdon[a + cb] << 8) + _tabdon[(a + cb + 1)];
+ if (ib == 0) {
+ _crep = 997;
+ return;
+ }
+
+ cy = 1;
+ do {
+ cb += 2;
+ sx = _tabdon[a + cb] * _resolutionScaler;
+ sy = _tabdon[(a + cb + 1)];
+ cb += 2;
+ ix = _tabdon[a + cb] * _resolutionScaler;
+ iy = _tabdon[(a + cb + 1)];
+ ++cy;
+ } while (!(((_x >= sx) && (_x <= ix) && (_y >= sy) && (_y <= iy)) || (cy > ib)));
+
+ if ((_x >= sx) && (_x <= ix) && (_y >= sy) && (_y <= iy)) {
+ _num = cy - 1;
+ return;
+ }
+
+ _crep = 997;
+}
+
+void MortevielleEngine::treg(int objId) {
+ int mdes = _caff;
+ _caff = objId;
+
+ if (((_caff > 29) && (_caff < 33)) || (_caff == 144) || (_caff == 147) || (_caff == 149) || (_currAction == OPCODE_SLOOK)) {
+ drawPictureWithText();
+ if ((_caff > 29) && (_caff < 33))
+ handleDescriptionText(2, _caff);
+ else
+ handleDescriptionText(2, _caff + 400);
+ testKey(true);
+ _caff = mdes;
+ _currMenu = MENU_NONE;
+ _crep = 998;
+ } else {
+ _obpart = true;
+ _crep = _caff + 400;
+ _menu.setSearchMenu();
+ }
+}
+
+/**
+ * Engine function - Put in hand
+ * @remarks Originally called 'avpoing'
+ */
+void MortevielleEngine::putInHand(int &objId) {
+ _crep = 999;
+ if (_coreVar._selectedObjectId != 0)
+ addObjectToInventory(_coreVar._selectedObjectId);
+
+ // If inventory wasn't full
+ if (_crep != 139) {
+ displayItemInHand(objId + 400);
+ _coreVar._selectedObjectId = objId;
+ objId = 0;
+ }
+}
+
+int MortevielleEngine::rechai() {
+ int tmpPlace = _coreVar._currPlace;
+
+ if (_coreVar._currPlace == CRYPT)
+ tmpPlace = CELLAR;
+
+ return _tabdon[kAchai + (tmpPlace * 7) + _num - 1];
+}
+
+/**
+ * Check before leaving the secret passage
+ * @remarks Originally called 't23coul'
+ */
+int MortevielleEngine::checkLeaveSecretPassage() {
+ if (!checkInventory(143)) {
+ _crep = 1512;
+ loseGame();
+ }
+
+ return CELLAR;
+}
+
+/**
+ * Display status character in description bar
+ * @remarks Originally called 'fenat'
+ */
+void MortevielleEngine::displayStatusInDescriptionBar(char stat) {
+ int color;
+
+ _mouse.hideMouse();
+ if (_currGraphicalDevice == MODE_CGA)
+ color = 2;
+ else if (_currGraphicalDevice == MODE_HERCULES)
+ color = 1;
+ else
+ color = 12;
+
+ _screenSurface.writeCharacter(Common::Point(306, 193), stat, color);
+ _screenSurface.drawBox(300, 191, 16, 8, 15);
+ _mouse.showMouse();
+}
+
+/**
+ * Test Keyboard
+ * @remarks Originally called 'teskbd'
+ */
+void MortevielleEngine::testKeyboard() {
+ if (keyPressed())
+ gettKeyPressed();
+}
+
+/**
+ * Test Key Pressed
+ * @remarks Originally called 'testou'
+ */
+int MortevielleEngine::gettKeyPressed() {
+ char ch = getChar();
+
+ switch (ch) {
+ case '\23' :
+ _soundOff = !_soundOff;
+ break;
+ case '\26' :
+ if ((_x26KeyCount == 1) || (_x26KeyCount == 2)) {
+ decodeNumber(&_cfiecBuffer[161 * 16], (_cfiecBufferSize - (161 * 16)) / 64);
+ ++_x26KeyCount;
+
+ return 61;
+ }
+ break;
+ case '\33' :
+ if (keyPressed())
+ ch = getChar();
+ break;
+ default:
+ break;
+ }
+
+ return (int)ch;
+}
+
+} // End of namespace Mortevielle
diff --git a/engines/neverhood/background.cpp b/engines/neverhood/background.cpp
index e9e5325e77..d6a9900d38 100644
--- a/engines/neverhood/background.cpp
+++ b/engines/neverhood/background.cpp
@@ -33,11 +33,11 @@ Background::Background(NeverhoodEngine *vm, int objectPriority)
Background::Background(NeverhoodEngine *vm, uint32 fileHash, int objectPriority, int surfacePriority)
: Entity(vm, objectPriority), _surface(NULL), _spriteResource(vm) {
-
+
_spriteResource.load(fileHash);
createSurface(surfacePriority, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height);
_surface->drawSpriteResource(_spriteResource);
-
+
}
Background::~Background() {
diff --git a/engines/neverhood/blbarchive.cpp b/engines/neverhood/blbarchive.cpp
index 9f5f46487c..d730d75718 100644
--- a/engines/neverhood/blbarchive.cpp
+++ b/engines/neverhood/blbarchive.cpp
@@ -58,8 +58,8 @@ BlbArchive::~BlbArchive() {
void BlbArchive::open(const Common::String &filename) {
BlbHeader header;
uint16 *extDataOffsets;
-
- _entries.clear();
+
+ _entries.clear();
if (!_fd.open(filename))
error("BlbArchive::open() Could not open %s", filename.c_str());
@@ -83,16 +83,16 @@ void BlbArchive::open(const Common::String &filename) {
entry.fileHash = _fd.readUint32LE();
_entries.push_back(entry);
}
-
+
extDataOffsets = new uint16[header.fileCount];
-
+
// Load file records
for (uint i = 0; i < header.fileCount; i++) {
BlbArchiveEntry &entry = _entries[i];
entry.type = _fd.readByte();
entry.comprType = _fd.readByte();
entry.extData = NULL;
- extDataOffsets[i] = _fd.readUint16LE();
+ extDataOffsets[i] = _fd.readUint16LE();
entry.timeStamp = _fd.readUint32LE();
entry.offset = _fd.readUint32LE();
entry.diskSize = _fd.readUint32LE();
@@ -101,7 +101,7 @@ void BlbArchive::open(const Common::String &filename) {
entry.fileHash, entry.type, entry.comprType, extDataOffsets[i], entry.timeStamp,
entry.offset, entry.diskSize, entry.size);
}
-
+
// Load ext data
if (header.extDataSize > 0) {
_extData = new byte[header.extDataSize];
@@ -120,9 +120,9 @@ void BlbArchive::load(uint index, byte *buffer, uint32 size) {
void BlbArchive::load(BlbArchiveEntry *entry, byte *buffer, uint32 size) {
Common::StackLock lock(_mutex);
-
+
_fd.seek(entry->offset);
-
+
switch (entry->comprType) {
case 1: // Uncompressed
if (size == 0)
diff --git a/engines/neverhood/console.cpp b/engines/neverhood/console.cpp
index a4dd50ce4b..733d7dd8a4 100644
--- a/engines/neverhood/console.cpp
+++ b/engines/neverhood/console.cpp
@@ -25,6 +25,7 @@
#include "neverhood/neverhood.h"
#include "neverhood/gamemodule.h"
#include "neverhood/scene.h"
+#include "neverhood/sound.h"
#include "neverhood/modules/module1600.h"
namespace Neverhood {
@@ -34,6 +35,7 @@ Console::Console(NeverhoodEngine *vm) : GUI::Debugger(), _vm(vm) {
DCmd_Register("dumpvars", WRAP_METHOD(Console, Cmd_Dumpvars));
DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room));
DCmd_Register("surfaces", WRAP_METHOD(Console, Cmd_Surfaces));
+ DCmd_Register("playsound", WRAP_METHOD(Console, Cmd_PlaySound));
}
Console::~Console() {
@@ -79,7 +81,7 @@ bool Console::Cmd_Cheat(int argc, const char **argv) {
DebugPrintf(" music - shows the correct index in the radio music puzzle, module 2800, scene 1\n");
DebugPrintf(" radio - enables the radio, module 3000, scene 9 - same as pulling the rightmost cord in the flytrap room\n");
DebugPrintf(" symbols - solves the symbols puzzle, module 1600, scene 8. Only available in that room\n");
- DebugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n");
+ DebugPrintf(" tubes - shows the correct test tube combination in module 2800, scenes 7 and 10\n");
return true;
}
@@ -169,4 +171,21 @@ bool Console::Cmd_Dumpvars(int argc, const char **argv) {
return true;
}
+bool Console::Cmd_PlaySound(int argc, const char **argv) {
+ if (argc < 2) {
+ DebugPrintf("Usage: %s <sound hash>\n", argv[0]);
+ } else {
+ uint32 soundHash = strtol(argv[1], NULL, 0);
+ AudioResourceManSoundItem *soundItem = new AudioResourceManSoundItem(_vm, soundHash);
+ soundItem->setVolume(100);
+ soundItem->playSound(false);
+ while (soundItem->isPlaying()) {
+ _vm->_system->delayMillis(10);
+ }
+ delete soundItem;
+ }
+
+ return true;
+}
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/console.h b/engines/neverhood/console.h
index 40c11b50e3..62d65bd693 100644
--- a/engines/neverhood/console.h
+++ b/engines/neverhood/console.h
@@ -41,6 +41,7 @@ private:
bool Cmd_Surfaces(int argc, const char **argv);
bool Cmd_Cheat(int argc, const char **argv);
bool Cmd_Dumpvars(int argc, const char **argv);
+ bool Cmd_PlaySound(int argc, const char **argv);
};
} // End of namespace Neverhood
diff --git a/engines/neverhood/diskplayerscene.cpp b/engines/neverhood/diskplayerscene.cpp
index 94a68a7526..ef2b856b2f 100644
--- a/engines/neverhood/diskplayerscene.cpp
+++ b/engines/neverhood/diskplayerscene.cpp
@@ -61,7 +61,7 @@ static const uint32 kDiskplayerSmackerFileHashes[] = {
0x04002810
};
-static const uint32 kDiskplayerSlotFileHashes1[] = {
+static const uint32 kDiskplayerSlotFileHashes1[] = {
0x81312280,
0x01312281,
0x01312282,
@@ -84,7 +84,7 @@ static const uint32 kDiskplayerSlotFileHashes1[] = {
0x04312281
};
-static const uint32 kDiskplayerSlotFileHashes2[] = {
+static const uint32 kDiskplayerSlotFileHashes2[] = {
0x90443A00,
0x90443A18,
0x90443A28,
@@ -107,8 +107,8 @@ static const uint32 kDiskplayerSlotFileHashes2[] = {
0xC0443A18
};
-static const uint32 kDiskplayerSlotFileHashes3[] = {
- 0x10357320,
+static const uint32 kDiskplayerSlotFileHashes3[] = {
+ 0x10357320,
0x10557320,
0x10957320,
0x11157320,
@@ -130,7 +130,7 @@ static const uint32 kDiskplayerSlotFileHashes3[] = {
0x10543320
};
-static const uint32 kDiskplayerSlotFileHashes4[] = {
+static const uint32 kDiskplayerSlotFileHashes4[] = {
0xDC8020E4,
0xDC802164,
0xDC802264,
@@ -155,7 +155,7 @@ static const uint32 kDiskplayerSlotFileHashes4[] = {
AsDiskplayerSceneKey::AsDiskplayerSceneKey(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1100) {
-
+
createSurface1(0x100B90B4, 1200);
_x = 211;
_y = 195;
@@ -193,7 +193,7 @@ void AsDiskplayerSceneKey::stDropKeyDone() {
DiskplayerPlayButton::DiskplayerPlayButton(NeverhoodEngine *vm, DiskplayerScene *diskplayerScene)
: StaticSprite(vm, 1400), _diskplayerScene(diskplayerScene), _isPlaying(false) {
-
+
loadSprite(0x24A4A664, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
setVisible(false);
loadSound(0, 0x44043000);
@@ -317,10 +317,10 @@ void DiskplayerSlot::stop() {
DiskplayerScene::DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int paletteIndex)
: Scene(vm, parentModule), _diskIndex(0), _appearCountdown(0), _tuneInCountdown(0),
- _hasAllDisks(false), _dropKey(false), _inputDisabled(true), _updateStatus(kUSStopped) {
+ _hasAllDisks(false), _dropKey(false), _inputDisabled(true), _updateStatus(kUSStopped) {
int availableDisksCount = 0;
-
+
setBackground(0x8A000044);
setPalette(kDiskplayerPaletteFileHashes[paletteIndex]);
@@ -344,7 +344,7 @@ DiskplayerScene::DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int
}
_hasAllDisks = availableDisksCount == 20;
-
+
if (_hasAllDisks && !getGlobalVar(V_HAS_FINAL_KEY))
_dropKey = true;
@@ -360,8 +360,8 @@ DiskplayerScene::DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int
_palette->usePalette();
- SetMessageHandler(&DiskplayerScene::handleMessage);
- SetUpdateHandler(&DiskplayerScene::update);
+ SetMessageHandler(&DiskplayerScene::handleMessage);
+ SetUpdateHandler(&DiskplayerScene::update);
_appearCountdown = 6;
}
@@ -417,7 +417,7 @@ void DiskplayerScene::update() {
}
_diskIndex++;
while (!_diskAvailable[_diskIndex] && _diskIndex < 19)
- _diskIndex++;
+ _diskIndex++;
if (_diskIndex < 20) {
_appearCountdown = 1;
} else {
@@ -448,7 +448,7 @@ uint32 DiskplayerScene::handleMessage(int messageNum, const MessageParam &param,
} else if (!_dropKey &&
param.asPoint().x > 38 && param.asPoint().x < 598 &&
param.asPoint().y > 400 && param.asPoint().y < 460) {
-
+
_diskSlots[_diskIndex]->stop();
_diskIndex = (param.asPoint().x - 38) / 28;
_diskSlots[_diskIndex]->activate();
@@ -462,10 +462,10 @@ uint32 DiskplayerScene::handleMessage(int messageNum, const MessageParam &param,
break;
case 0x2000:
tuneIn();
- break;
+ break;
case 0x2001:
stop();
- break;
+ break;
}
}
return 0;
diff --git a/engines/neverhood/diskplayerscene.h b/engines/neverhood/diskplayerscene.h
index 4afaf8af9f..150d5c58ed 100644
--- a/engines/neverhood/diskplayerscene.h
+++ b/engines/neverhood/diskplayerscene.h
@@ -36,7 +36,7 @@ class AsDiskplayerSceneKey : public AnimatedSprite {
public:
AsDiskplayerSceneKey(NeverhoodEngine *vm);
void stDropKey();
-protected:
+protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
void stDropKeyDone();
};
@@ -47,7 +47,7 @@ public:
void press();
void release();
protected:
- DiskplayerScene *_diskplayerScene;
+ DiskplayerScene *_diskplayerScene;
bool _isPlaying;
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
@@ -69,7 +69,7 @@ protected:
int _blinkCountdown;
bool _isLocked;
bool _isBlinking;
- void update();
+ void update();
};
enum {
diff --git a/engines/neverhood/entity.cpp b/engines/neverhood/entity.cpp
index 8b1298916c..1ebf1dcf6c 100644
--- a/engines/neverhood/entity.cpp
+++ b/engines/neverhood/entity.cpp
@@ -25,29 +25,29 @@
namespace Neverhood {
-uint32 MessageParam::asInteger() const {
- assert(_type == mptInteger);
- return _integer;
+uint32 MessageParam::asInteger() const {
+ assert(_type == mptInteger);
+ return _integer;
}
-NPoint MessageParam::asPoint() const {
+NPoint MessageParam::asPoint() const {
assert(_type == mptInteger || _type == mptPoint);
if (_type == mptInteger) {
NPoint pt;
pt.x = _integer & 0xFFFF;
- pt.y = (_integer >> 16) & 0xFFFF;
+ pt.y = (_integer >> 16) & 0xFFFF;
return pt;
- }
- return _point;
+ }
+ return _point;
}
Entity *MessageParam::asEntity() const {
- assert(_type == mptEntity);
- return _entity;
+ assert(_type == mptEntity);
+ return _entity;
}
Entity::Entity(NeverhoodEngine *vm, int priority)
- : _vm(vm), _updateHandlerCb(NULL), _messageHandlerCb(NULL), _priority(priority), _soundResources(NULL) {
+ : _vm(vm), _updateHandlerCb(NULL), _messageHandlerCb(nullptr), _priority(priority), _soundResources(NULL) {
}
Entity::~Entity() {
diff --git a/engines/neverhood/entity.h b/engines/neverhood/entity.h
index cba1bb9a7f..5c29bf8a4f 100644
--- a/engines/neverhood/entity.h
+++ b/engines/neverhood/entity.h
@@ -98,7 +98,7 @@ public:
void incGlobalVar(uint32 nameHash, int incrValue);
void incSubVar(uint32 nameHash, uint32 subNameHash, int incrValue);
int getPriority() const { return _priority; }
- bool hasMessageHandler() const { return _messageHandlerCb != NULL; }
+ bool hasMessageHandler() const { return _messageHandlerCb != nullptr; }
protected:
void (Entity::*_updateHandlerCb)();
uint32 (Entity::*_messageHandlerCb)(int messageNum, const MessageParam &param, Entity *sender);
diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp
index b3589837df..47cc818fea 100644
--- a/engines/neverhood/gamemodule.cpp
+++ b/engines/neverhood/gamemodule.cpp
@@ -77,7 +77,7 @@ GameModule::GameModule(NeverhoodEngine *vm)
: Module(vm, NULL), _moduleNum(-1), _prevChildObject(NULL), _prevModuleNum(-1),
_restoreGameRequested(false), _restartGameRequested(false), _canRequestMainMenu(true),
_mainMenuRequested(false) {
-
+
// Other initializations moved to actual engine class
_vm->_soundMan->playSoundThree(0x002D0031, 0x8861079);
SetMessageHandler(&GameModule::handleMessage);
@@ -96,7 +96,7 @@ void GameModule::handleMouseMove(int16 x, int16 y) {
mousePos.y = y;
debug(2, "GameModule::handleMouseMove(%d, %d)", x, y);
sendPointMessage(_childObject, 0, mousePos);
- }
+ }
}
void GameModule::handleMouseDown(int16 x, int16 y) {
@@ -106,7 +106,7 @@ void GameModule::handleMouseDown(int16 x, int16 y) {
mousePos.y = y;
debug(2, "GameModule::handleMouseDown(%d, %d)", x, y);
sendPointMessage(_childObject, 0x0001, mousePos);
- }
+ }
}
void GameModule::handleMouseUp(int16 x, int16 y) {
@@ -116,21 +116,21 @@ void GameModule::handleMouseUp(int16 x, int16 y) {
mousePos.y = y;
debug(2, "GameModule::handleMouseUp(%d, %d)", x, y);
sendPointMessage(_childObject, 0x0002, mousePos);
- }
+ }
}
void GameModule::handleSpaceKey() {
if (_childObject) {
debug(2, "GameModule::handleSpaceKey()");
sendMessage(_childObject, 0x0009, 0);
- }
+ }
}
void GameModule::handleAsciiKey(char key) {
if (_childObject) {
debug(2, "GameModule::handleAsciiKey()");
sendMessage(_childObject, 0x000A, (uint32)key);
- }
+ }
}
void GameModule::handleKeyDown(Common::KeyCode keyCode) {
@@ -141,7 +141,7 @@ void GameModule::handleKeyDown(Common::KeyCode keyCode) {
handleSpaceKey();
debug(2, "GameModule::handleKeyDown()");
sendMessage(_childObject, 0x000B, keyCode);
- }
+ }
}
void GameModule::handleEscapeKey() {
@@ -166,7 +166,7 @@ void GameModule::initKeySlotsPuzzle() {
void GameModule::initMemoryPuzzle() {
if (!getSubVar(VA_IS_PUZZLE_INIT, 0xC8606803)) {
- NonRepeatingRandomNumbers diceIndices(_vm->_rnd, 3);
+ NonRepeatingRandomNumbers diceIndices(_vm->_rnd, 3);
NonRepeatingRandomNumbers availableTiles(_vm->_rnd, 48);
NonRepeatingRandomNumbers tileSymbols(_vm->_rnd, 10);
for (uint32 i = 0; i < 3; i++)
@@ -320,11 +320,11 @@ uint32 GameModule::handleMessage(int messageNum, const MessageParam &param, Enti
switch (messageNum) {
case 0x0800:
_canRequestMainMenu = true;
- break;
+ break;
case 0x1009:
_moduleResult = param.asInteger();
_done = true;
- break;
+ break;
}
return messageResult;
}
diff --git a/engines/neverhood/gamemodule.h b/engines/neverhood/gamemodule.h
index 1fb3557b81..2f2fecf463 100644
--- a/engines/neverhood/gamemodule.h
+++ b/engines/neverhood/gamemodule.h
@@ -49,7 +49,7 @@ public:
void initWaterPipesPuzzle();
void initRadioPuzzle();
void initTestTubes1Puzzle();
- void initTestTubes2Puzzle();
+ void initTestTubes2Puzzle();
void initCannonSymbolsPuzzle();
void initCodeSymbolsPuzzle();
void initCubeSymbolsPuzzle();
diff --git a/engines/neverhood/gamevars.cpp b/engines/neverhood/gamevars.cpp
index dc25f74e56..9c080fea24 100644
--- a/engines/neverhood/gamevars.cpp
+++ b/engines/neverhood/gamevars.cpp
@@ -75,7 +75,7 @@ uint32 GameVars::getSubVar(uint32 nameHash, uint32 subNameHash) {
int16 subVarIndex = findSubVarIndex(varIndex, subNameHash);
if (subVarIndex != -1)
value = _vars[subVarIndex].value;
- }
+ }
return value;
}
diff --git a/engines/neverhood/gamevars.h b/engines/neverhood/gamevars.h
index de9ffb8ec5..3aec4d1da4 100644
--- a/engines/neverhood/gamevars.h
+++ b/engines/neverhood/gamevars.h
@@ -160,7 +160,7 @@ enum {
VA_HAS_KEY = 0x0090EA95,
VA_IS_KEY_INSERTED = 0x08D0AB11,
VA_LOCKS_DISABLED = 0x14800353,
- V_END_
+ V_END_
};
struct GameVar {
diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp
index 66a7999e59..490959020f 100644
--- a/engines/neverhood/graphics.cpp
+++ b/engines/neverhood/graphics.cpp
@@ -29,7 +29,7 @@ namespace Neverhood {
BaseSurface::BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 height, Common::String name)
: _vm(vm), _priority(priority), _visible(true), _transparent(true),
_clipRects(NULL), _clipRectsCount(0), _version(0), _name(name) {
-
+
_drawRect.x = 0;
_drawRect.y = 0;
_drawRect.width = width;
@@ -68,7 +68,7 @@ void BaseSurface::clear() {
}
void BaseSurface::drawSpriteResource(SpriteResource &spriteResource) {
- if (spriteResource.getDimensions().width <= _drawRect.width &&
+ if (spriteResource.getDimensions().width <= _drawRect.width &&
spriteResource.getDimensions().height <= _drawRect.height) {
clear();
spriteResource.draw(_surface, false, false);
@@ -77,7 +77,7 @@ void BaseSurface::drawSpriteResource(SpriteResource &spriteResource) {
}
void BaseSurface::drawSpriteResourceEx(SpriteResource &spriteResource, bool flipX, bool flipY, int16 width, int16 height) {
- if (spriteResource.getDimensions().width <= _sysRect.width &&
+ if (spriteResource.getDimensions().width <= _sysRect.width &&
spriteResource.getDimensions().height <= _sysRect.height) {
if (width > 0 && width <= _sysRect.width)
_drawRect.width = width;
@@ -145,7 +145,7 @@ void ShadowSurface::draw() {
FontSurface::FontSurface(NeverhoodEngine *vm, NPointArray *tracking, uint charsPerRow, uint16 numRows, byte firstChar, uint16 charWidth, uint16 charHeight)
: BaseSurface(vm, 0, charWidth * charsPerRow, charHeight * numRows, "font"), _charsPerRow(charsPerRow), _numRows(numRows),
_firstChar(firstChar), _charWidth(charWidth), _charHeight(charHeight), _tracking(NULL) {
-
+
_tracking = new NPointArray();
*_tracking = *tracking;
@@ -154,7 +154,7 @@ FontSurface::FontSurface(NeverhoodEngine *vm, NPointArray *tracking, uint charsP
FontSurface::FontSurface(NeverhoodEngine *vm, uint32 fileHash, uint charsPerRow, uint16 numRows, byte firstChar, uint16 charWidth, uint16 charHeight)
: BaseSurface(vm, 0, charWidth * charsPerRow, charHeight * numRows, "font"), _charsPerRow(charsPerRow), _numRows(numRows),
_firstChar(firstChar), _charWidth(charWidth), _charHeight(charHeight), _tracking(NULL) {
-
+
SpriteResource fontSpriteResource(_vm);
fontSpriteResource.load(fileHash, true);
drawSpriteResourceEx(fontSpriteResource, false, false, 0, 0);
@@ -182,7 +182,7 @@ void FontSurface::drawString(BaseSurface *destSurface, int16 x, int16 y, const b
for (; stringLen > 0; --stringLen, ++string) {
drawChar(destSurface, x, y, *string);
x += _tracking ? (*_tracking)[*string - _firstChar].x : _charWidth;
- }
+ }
}
@@ -201,7 +201,7 @@ FontSurface *FontSurface::createFontSurface(NeverhoodEngine *vm, uint32 fileHash
uint16 charHeight = fontData.getPoint(calcHash("meCharHeight")).x;
NPointArray *tracking = fontData.getPointArray(calcHash("meTracking"));
fontSprite.load(fileHash, true);
- fontSurface = new FontSurface(vm, tracking, 16, numRows, firstChar, charWidth, charHeight);
+ fontSurface = new FontSurface(vm, tracking, 16, numRows, firstChar, charWidth, charHeight);
fontSurface->drawSpriteResourceEx(fontSprite, false, false, 0, 0);
return fontSurface;
}
@@ -219,7 +219,7 @@ enum BitmapFlags {
void parseBitmapResource(const byte *sprite, bool *rle, NDimensions *dimensions, NPoint *position, const byte **palette, const byte **pixels) {
uint16 flags;
-
+
flags = READ_LE_UINT16(sprite);
sprite += 2;
@@ -278,7 +278,7 @@ void unpackSpriteRle(const byte *source, int width, int height, byte *dest, int
rows = READ_LE_UINT16(source);
chunks = READ_LE_UINT16(source + 2);
source += 4;
-
+
do {
if (chunks == 0) {
dest += rows * destPitch;
@@ -316,7 +316,7 @@ void unpackSpriteRle(const byte *source, int width, int height, byte *dest, int
void unpackSpriteNormal(const byte *source, int width, int height, byte *dest, int destPitch, bool flipX, bool flipY) {
const int sourcePitch = (width + 3) & 0xFFFC;
-
+
if (flipY) {
dest += destPitch * (height - 1);
destPitch = -destPitch;
diff --git a/engines/neverhood/graphics.h b/engines/neverhood/graphics.h
index 9ab0d87ab9..703e274576 100644
--- a/engines/neverhood/graphics.h
+++ b/engines/neverhood/graphics.h
@@ -62,12 +62,12 @@ struct NRect {
typedef Common::Array<NRect> NRectArray;
-// TODO: Use Common::Rect
+// TODO: Use Common::Rect
struct NDrawRect {
int16 x, y, width, height;
NDrawRect() : x(0), y(0), width(0), height(0) {}
NDrawRect(int16 x0, int16 y0, int16 width0, int16 height0) : x(x0), y(y0), width(width0), height(height0) {}
- int16 x2() { return x + width; }
+ int16 x2() { return x + width; }
int16 y2() { return y + height; }
void set(int16 x0, int16 y0, int16 width0, int16 height0) {
x = x0;
diff --git a/engines/neverhood/klaymen.cpp b/engines/neverhood/klaymen.cpp
index 70567806fa..8ed27c825a 100644
--- a/engines/neverhood/klaymen.cpp
+++ b/engines/neverhood/klaymen.cpp
@@ -33,19 +33,19 @@ static const KlaymenIdleTableItem klaymenIdleTable1[] = {
{1, kIdleArms},
{1, kIdleChest},
{1, kIdleHeadOff}
-};
+};
static const KlaymenIdleTableItem klaymenIdleTable2[] = {
{1, kIdlePickEar},
{1, kIdleSpinHead},
{1, kIdleChest},
{1, kIdleHeadOff}
-};
+};
static const KlaymenIdleTableItem klaymenIdleTable3[] = {
{1, kIdleTeleporterHands},
{1, kIdleTeleporterHands2}
-};
+};
static const KlaymenIdleTableItem klaymenIdleTable4[] = {
{1, kIdleSpinHead},
@@ -56,7 +56,7 @@ static const KlaymenIdleTableItem klaymenIdleTable4[] = {
static const KlaymenIdleTableItem klaymenIdleTable1002[] = {
{1, kIdlePickEar},
{2, kIdleWonderAbout}
-};
+};
// Klaymen
@@ -66,7 +66,7 @@ Klaymen::Klaymen(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRec
_attachedSprite(NULL), _isWalking(false), _actionStatus(1), _parentScene(parentScene), _isSneaking(false), _isLargeStep(false),
_doYHitIncr(false), _isLeverDown(false), _isSittingInTeleporter(false), _actionStatusChanged(false), _ladderStatus(0), _pathPoints(NULL), _soundFlag(false),
_idleTableNum(0), _otherSprite(NULL), _moveObjectCountdown(0), _readyToSpit(false), _walkResumeFrameIncr(0) {
-
+
createSurface(1000, 320, 200);
_x = x;
_y = y;
@@ -447,7 +447,7 @@ void Klaymen::upIdleAnimation() {
bool Klaymen::stStartActionFromIdle(AnimationCb callback) {
if (_busyStatus == 2) {
_busyStatus = 1;
- _acceptInput = false;
+ _acceptInput = false;
startAnimation(0x9A7020B8, 0, -1);
SetUpdateHandler(&Klaymen::update);
SetMessageHandler(&Klaymen::hmStartAction);
@@ -684,35 +684,35 @@ void Klaymen::suAction() {
_x += _deltaX;
}
_deltaX = 0;
-
+
if (_doDeltaY) {
_y -= _deltaY;
} else {
_y += _deltaY;
}
_deltaY = 0;
-
+
if (_frameChanged) {
if (xdiff > 6)
_x += 6;
else if (xdiff < -6)
_x -= 6;
else
- _x = _destX;
+ _x = _destX;
}
-
+
updateBounds();
-
+
}
void Klaymen::suSneaking() {
-
+
int16 xdiff = _destX - _x;
-
+
if (_currFrameIndex == 9) {
if (xdiff > 26)
_deltaX += xdiff - 26;
- else if (xdiff < -26)
+ else if (xdiff < -26)
_deltaX -= xdiff + 26;
}
@@ -720,7 +720,7 @@ void Klaymen::suSneaking() {
xdiff = _deltaX;
else if (xdiff < -_deltaX)
xdiff = -_deltaX;
- _deltaX = 0;
+ _deltaX = 0;
if (_destX != _x) {
HitRect *hitRectPrev = _parentScene->findHitRectAtPos(_x, _y);
@@ -749,7 +749,7 @@ void Klaymen::suSneaking() {
}
updateBounds();
}
-
+
}
void Klaymen::stSneak() {
@@ -761,7 +761,7 @@ void Klaymen::stSneak() {
SetUpdateHandler(&Klaymen::update);
SetMessageHandler(&Klaymen::hmSneaking);
SetSpriteUpdate(&Klaymen::suSneaking);
- FinalizeState(&Klaymen::evSneakingDone);
+ FinalizeState(&Klaymen::evSneakingDone);
}
void Klaymen::evSneakingDone() {
@@ -801,7 +801,7 @@ void Klaymen::stStartWalking() {
SetMessageHandler(&Klaymen::hmStartWalking);
SetSpriteUpdate(&Klaymen::suWalkingTestExit);
NextState(&Klaymen::stWalkingFirst);
- FinalizeState(&Klaymen::evStartWalkingDone);
+ FinalizeState(&Klaymen::evStartWalkingDone);
}
}
@@ -832,7 +832,7 @@ void Klaymen::stWalkingFirst() {
SetMessageHandler(&Klaymen::hmWalking);
SetSpriteUpdate(&Klaymen::suWalkingFirst);
NextState(&Klaymen::stUpdateWalkingFirst);
- FinalizeState(&Klaymen::evStartWalkingDone);
+ FinalizeState(&Klaymen::evStartWalkingDone);
}
void Klaymen::suWalkingFirst() {
@@ -882,20 +882,20 @@ void Klaymen::stUpdateWalkingFirst() {
SetUpdateHandler(&Klaymen::update);
SetMessageHandler(&Klaymen::hmSneaking);
SetSpriteUpdate(&Klaymen::suSneaking);
- FinalizeState(&Klaymen::evSneakingDone);
+ FinalizeState(&Klaymen::evSneakingDone);
}
}
void Klaymen::suWalkingTestExit() {
int16 xdiff = ABS(_destX - _x);
int16 xdelta = _destX - _x;
-
+
if (xdelta > _deltaX)
xdelta = _deltaX;
else if (xdelta < -_deltaX)
xdelta = -_deltaX;
-
- _deltaX = 0;
+
+ _deltaX = 0;
if (xdiff == 0 ||
(_actionStatus != 2 && _actionStatus != 3 && xdiff <= 42 && _currFrameIndex >= 5 && _currFrameIndex <= 11) ||
@@ -928,7 +928,7 @@ void Klaymen::suWalkingTestExit() {
}
updateBounds();
}
-
+
}
uint32 Klaymen::hmLever(int messageNum, const MessageParam &param, Entity *sender) {
@@ -1363,7 +1363,7 @@ void Klaymen::stLargeStep() {
SetUpdateHandler(&Klaymen::update);
SetMessageHandler(&Klaymen::hmLargeStep);
SetSpriteUpdate(&Klaymen::suLargeStep);
- FinalizeState(&Klaymen::evLargeStepDone);
+ FinalizeState(&Klaymen::evLargeStepDone);
}
void Klaymen::evLargeStepDone() {
@@ -1372,11 +1372,11 @@ void Klaymen::evLargeStepDone() {
void Klaymen::suLargeStep() {
int16 xdiff = _destX - _x;
-
+
if (_doDeltaX) {
_deltaX = -_deltaX;
}
-
+
if (_currFrameIndex == 7) {
_deltaX = xdiff;
}
@@ -1385,7 +1385,7 @@ void Klaymen::suLargeStep() {
xdiff = _deltaX;
_deltaX = 0;
-
+
if (_x != _destX) {
HitRect *hitRectPrev = _parentScene->findHitRectAtPos(_x, _y);
_x += xdiff;
@@ -1420,7 +1420,7 @@ uint32 Klaymen::hmLargeStep(int messageNum, const MessageParam &param, Entity *s
case 0x3002:
_x = _destX;
gotoNextStateExt();
- break;
+ break;
}
return messageResult;
}
@@ -1681,7 +1681,7 @@ void Klaymen::stStartClimbLadderDown() {
_ladderStatus = 2;
_acceptInput = true;
startAnimation(0x122D1505, 29 - _currFrameIndex, -1);
- }
+ }
}
}
@@ -1979,7 +1979,7 @@ uint32 Klaymen::hmMoveObjectTurn(int messageNum, const MessageParam &param, Enti
break;
case 0x480A:
_isMoveObjectRequested = true;
- return 0;
+ return 0;
}
return hmLowLevelAnimation(messageNum, param, sender);
}
@@ -2521,7 +2521,7 @@ void Klaymen::stInsertKey() {
more = true;
} while (more);
_keysToInsert++;
- }
+ }
}
if (_keysToInsert == 0) {
GotoState(NULL);
@@ -3049,7 +3049,7 @@ void Klaymen::stFallSkipJump() {
void Klaymen::upMoveObject() {
if (_x >= 380)
gotoNextStateExt();
- Klaymen::update();
+ Klaymen::update();
}
uint32 Klaymen::hmMatch(int messageNum, const MessageParam &param, Entity *sender) {
@@ -3165,7 +3165,7 @@ void Klaymen::stTumbleHeadless() {
void Klaymen::stCloseEyes() {
if (!stStartActionFromIdle(AnimationCallback(&Klaymen::stCloseEyes))) {
_busyStatus = 1;
- _acceptInput = false;
+ _acceptInput = false;
startAnimation(0x5420E254, 0, -1);
SetUpdateHandler(&Klaymen::update);
SetMessageHandler(&Klaymen::hmLowLevel);
@@ -3358,7 +3358,7 @@ uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x4004:
GotoState(&Klaymen::stTryStandIdle);
- break;
+ break;
case 0x4804:
if (param.asInteger() == 2)
GotoState(&Klaymen::stSleeping);
@@ -3380,7 +3380,7 @@ uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481B:
if (param.asPoint().y != 0)
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
@@ -3408,10 +3408,10 @@ uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam &param) {
sendMessage(_parentScene, 0x2002, 0);
GotoState(&Klaymen::stWakeUp);
}
- break;
+ break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -3423,7 +3423,7 @@ uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1002::KmScene1002(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
+
setKlaymenIdleTable1();
}
@@ -3438,7 +3438,7 @@ void KmScene1002::xUpdate() {
_idleTableNum = 0;
}
}
-
+
uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam &param) {
switch (messageNum) {
case 0x2001:
@@ -3451,7 +3451,7 @@ uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4800:
startWalkToX(param.asPoint().x, false);
break;
- case 0x4004:
+ case 0x4004:
GotoState(&Klaymen::stTryStandIdle);
break;
case 0x4803:
@@ -3479,42 +3479,42 @@ uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam &param) {
break;
}
break;
- case 0x480A:
+ case 0x480A:
GotoState(&Klaymen::stMoveVenusFlyTrap);
break;
- case 0x480D:
+ case 0x480D:
GotoState(&Klaymen::stJumpToRingVenusFlyTrap);
break;
- case 0x4816:
+ case 0x4816:
if (param.asInteger() == 0)
GotoState(&Klaymen::stPressDoorButton);
break;
- case 0x4817:
+ case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
break;
- case 0x481B:
+ case 0x481B:
startWalkToAttachedSpriteXDistance(param.asInteger());
break;
- case 0x4820:
+ case 0x4820:
sendMessage(_parentScene, 0x2005, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
break;
- case 0x4821:
+ case 0x4821:
sendMessage(_parentScene, 0x2005, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
+ GotoState(&Klaymen::stStartClimbLadderDown);
break;
- case 0x4822:
+ case 0x4822:
sendMessage(_parentScene, 0x2005, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
+ GotoState(&Klaymen::stStartClimbLadderUp);
break;
case 0x4823:
sendMessage(_parentScene, 0x2006, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
+ GotoState(&Klaymen::stClimbLadderHalf);
break;
- case 0x482E:
+ case 0x482E:
if (param.asInteger() == 1)
GotoState(&Klaymen::stWalkToFrontNoStep);
else
@@ -3529,7 +3529,7 @@ uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x483F:
startSpecialWalkRight(param.asInteger());
break;
- case 0x4840:
+ case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
}
@@ -3540,8 +3540,8 @@ uint32 KmScene1002::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1004::KmScene1004(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
- _dataResource.load(0x01900A04);
+
+ _dataResource.load(0x01900A04);
}
uint32 KmScene1004::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -3606,7 +3606,7 @@ uint32 KmScene1004::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1109::KmScene1109(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
+
// Empty
}
@@ -3615,7 +3615,7 @@ uint32 KmScene1109::xHandleMessage(int messageNum, const MessageParam &param) {
switch (messageNum) {
case 0x2000:
_isSittingInTeleporter = param.asInteger() != 0;
- messageResult = 1;
+ messageResult = 1;
break;
case 0x4001:
case 0x4800:
@@ -3653,7 +3653,7 @@ uint32 KmScene1109::xHandleMessage(int messageNum, const MessageParam &param) {
sendMessage(_parentScene, 0x2000, 1);
_isSittingInTeleporter = true;
GotoState(&Klaymen::stSitInTeleporter);
- break;
+ break;
case 0x4836:
sendMessage(_parentScene, 0x2000, 0);
_isSittingInTeleporter = false;
@@ -3673,7 +3673,7 @@ uint32 KmScene1109::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1201::KmScene1201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
+
setKlaymenIdleTable(klaymenIdleTable4, ARRAYSIZE(klaymenIdleTable4));
_doYHitIncr = true;
}
@@ -3741,7 +3741,7 @@ uint32 KmScene1201::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1303::KmScene1303(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
+
// Empty
}
@@ -3762,8 +3762,8 @@ uint32 KmScene1303::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1304::KmScene1304(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
- // Empty
+
+ // Empty
}
uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -3774,7 +3774,7 @@ uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x4004:
GotoState(&Klaymen::stTryStandIdle);
- break;
+ break;
case 0x4812:
if (param.asInteger() == 2)
GotoState(&Klaymen::stPickUpNeedle);
@@ -3792,7 +3792,7 @@ uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam &param) {
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
else
startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
+ break;
case 0x481F:
if (param.asInteger() == 1)
GotoState(&Klaymen::stTurnAwayFromUse);
@@ -3803,7 +3803,7 @@ uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -3814,7 +3814,7 @@ uint32 KmScene1304::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1305::KmScene1305(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
- // Empty
+ // Empty
}
uint32 KmScene1305::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -3825,10 +3825,10 @@ uint32 KmScene1305::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x4004:
GotoState(&Klaymen::stTryStandIdle);
- break;
+ break;
case 0x4804:
GotoState(&Klaymen::stCrashDown);
- break;
+ break;
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
@@ -3839,7 +3839,7 @@ uint32 KmScene1305::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1306::KmScene1306(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
+
// Empty
}
@@ -3879,9 +3879,9 @@ uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
+ GotoState(&Klaymen::stInsertDisk);
break;
case 0x481B:
if (param.asPoint().y != 0)
@@ -3936,7 +3936,7 @@ uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam &param) {
sendMessage(_parentScene, 0x2000, 1);
_isSittingInTeleporter = true;
GotoState(&Klaymen::stSitInTeleporter);
- break;
+ break;
case 0x4836:
sendMessage(_parentScene, 0x2000, 0);
_isSittingInTeleporter = false;
@@ -3944,13 +3944,13 @@ uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483D:
teleporterAppear(0xEE084A04);
- break;
+ break;
case 0x483E:
teleporterDisappear(0xB86A4274);
- break;
+ break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -3961,7 +3961,7 @@ uint32 KmScene1306::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1308::KmScene1308(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
- // Empty
+ // Empty
}
uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -3978,7 +3978,7 @@ uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam &param) {
GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
else
GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
+ break;
case 0x480D:
GotoState(&Klaymen::stUseLever);
break;
@@ -3993,12 +3993,12 @@ uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481A:
if (param.asInteger() == 1)
- GotoState(&Klaymen::stInsertKey);
+ GotoState(&Klaymen::stInsertKey);
else
- GotoState(&Klaymen::stInsertDisk);
+ GotoState(&Klaymen::stInsertDisk);
break;
case 0x481B:
if (param.asPoint().y != 0)
@@ -4020,7 +4020,7 @@ uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -4032,8 +4032,8 @@ uint32 KmScene1308::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1401::KmScene1401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
- // Empty
+
+ // Empty
}
uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -4044,13 +4044,13 @@ uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x4004:
GotoState(&Klaymen::stTryStandIdle);
- break;
+ break;
case 0x480A:
if (param.asInteger() == 1)
GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
else
GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
+ break;
case 0x4816:
if (param.asInteger() == 1)
GotoState(&Klaymen::stPressButton);
@@ -4068,7 +4068,7 @@ uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam &param) {
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
else
startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
+ break;
case 0x481F:
if (param.asInteger() == 1)
GotoState(&Klaymen::stTurnAwayFromUse);
@@ -4101,8 +4101,8 @@ uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1402::KmScene1402(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
- SetFilterY(&Sprite::defFilterY);
+
+ SetFilterY(&Sprite::defFilterY);
}
uint32 KmScene1402::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -4113,13 +4113,13 @@ uint32 KmScene1402::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x4004:
GotoState(&Klaymen::stTryStandIdle);
- break;
+ break;
case 0x480A:
if (param.asInteger() == 1)
GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
else
GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
+ break;
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
@@ -4129,7 +4129,7 @@ uint32 KmScene1402::xHandleMessage(int messageNum, const MessageParam &param) {
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
else
startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
+ break;
case 0x481D:
GotoState(&Klaymen::stTurnToUse);
break;
@@ -4162,7 +4162,7 @@ uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam &param) {
GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
else
GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
+ break;
case 0x480D:
GotoState(&Klaymen::stUseLever);
break;
@@ -4177,7 +4177,7 @@ uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481B:
if (param.asPoint().y != 0)
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
@@ -4189,7 +4189,7 @@ uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -4202,7 +4202,7 @@ uint32 KmScene1403::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1404::KmScene1404(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
- // Empty
+ // Empty
}
uint32 KmScene1404::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -4219,7 +4219,7 @@ uint32 KmScene1404::xHandleMessage(int messageNum, const MessageParam &param) {
GotoState(&Klaymen::stMoveObjectSkipTurnFaceObject);
else
GotoState(&Klaymen::stMoveObjectFaceObject);
- break;
+ break;
case 0x4812:
if (param.asInteger() == 2)
GotoState(&Klaymen::stPickUpNeedle);
@@ -4233,7 +4233,7 @@ uint32 KmScene1404::xHandleMessage(int messageNum, const MessageParam &param) {
gotoNextStateExt();
break;
case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
+ GotoState(&Klaymen::stInsertDisk);
break;
case 0x481B:
if (param.asPoint().y != 0)
@@ -4307,7 +4307,7 @@ uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481B:
if (param.asPoint().y != 0)
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
@@ -4345,7 +4345,7 @@ uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam &param) {
sendMessage(_parentScene, 0x2032, 1);
_isSittingInTeleporter = true;
GotoState(&Klaymen::stSitInTeleporter);
- break;
+ break;
case 0x4836:
sendMessage(_parentScene, 0x2032, 0);
_isSittingInTeleporter = false;
@@ -4353,7 +4353,7 @@ uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -4366,7 +4366,7 @@ uint32 KmScene1608::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1705::KmScene1705(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
- // Empty
+ // Empty
}
uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -4388,7 +4388,7 @@ uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x4803:
GotoState(&Klaymen::stFallSkipJump);
- break;
+ break;
case 0x4812:
if (param.asInteger() == 2)
GotoState(&Klaymen::stPickUpNeedle);
@@ -4435,7 +4435,7 @@ uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam &param) {
sendMessage(_parentScene, 0x2000, 1);
_isSittingInTeleporter = true;
GotoState(&Klaymen::stSitInTeleporter);
- break;
+ break;
case 0x4836:
sendMessage(_parentScene, 0x2000, 0);
_isSittingInTeleporter = false;
@@ -4443,10 +4443,10 @@ uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483D:
teleporterAppear(0x5E0A4905);
- break;
+ break;
case 0x483E:
teleporterDisappear(0xD86E4477);
- break;
+ break;
}
return messageResult;
}
@@ -4454,7 +4454,7 @@ uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene1901::KmScene1901(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
- // Empty
+ // Empty
}
uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -4469,7 +4469,7 @@ uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481D:
GotoState(&Klaymen::stTurnToUse);
break;
@@ -4482,7 +4482,7 @@ uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -4493,7 +4493,7 @@ uint32 KmScene1901::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene2001::KmScene2001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
- // Empty
+ // Empty
}
uint32 KmScene2001::xHandleMessage(int messageNum, const MessageParam &param) {
@@ -4557,7 +4557,7 @@ uint32 KmScene2001::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene2101::KmScene2101(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
+
// Empty
}
@@ -4600,7 +4600,7 @@ uint32 KmScene2101::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481B:
if (param.asPoint().y != 0)
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
@@ -4622,7 +4622,7 @@ uint32 KmScene2101::xHandleMessage(int messageNum, const MessageParam &param) {
sendMessage(_parentScene, 0x2000, 1);
_isSittingInTeleporter = true;
GotoState(&Klaymen::stSitInTeleporter);
- break;
+ break;
case 0x4836:
sendMessage(_parentScene, 0x2000, 0);
_isSittingInTeleporter = false;
@@ -4635,7 +4635,7 @@ uint32 KmScene2101::xHandleMessage(int messageNum, const MessageParam &param) {
teleporterDisappear(0x9A28CA1C);
break;
}
- return messageResult;
+ return messageResult;
}
KmScene2201::KmScene2201(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount)
@@ -4684,7 +4684,7 @@ uint32 KmScene2201::xHandleMessage(int messageNum, const MessageParam &param) {
setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
gotoNextStateExt();
break;
- case 0x482E:
+ case 0x482E:
if (param.asInteger() == 1)
GotoState(&Klaymen::stWalkToFrontNoStep);
else
@@ -4698,12 +4698,12 @@ uint32 KmScene2201::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
}
- return 0;
+ return 0;
}
KmScene2203::KmScene2203(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
@@ -4711,7 +4711,7 @@ KmScene2203::KmScene2203(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16
// Empty
}
-
+
uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam &param) {
switch (messageNum) {
case 0x4001:
@@ -4740,7 +4740,7 @@ uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x4818:
startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
break;
@@ -4748,7 +4748,7 @@ uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam &param) {
GotoState(&Klaymen::stClayDoorOpen);
break;
case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
+ GotoState(&Klaymen::stInsertDisk);
break;
case 0x481B:
if (param.asPoint().y != 0)
@@ -4768,7 +4768,7 @@ uint32 KmScene2203::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -4785,7 +4785,7 @@ KmScene2205::KmScene2205(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16
void KmScene2205::xUpdate() {
setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
}
-
+
uint32 KmScene2205::xHandleMessage(int messageNum, const MessageParam &param) {
switch (messageNum) {
case 0x4001:
@@ -4809,13 +4809,13 @@ uint32 KmScene2205::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x4818:
startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -4837,7 +4837,7 @@ KmScene2206::~KmScene2206() {
void KmScene2206::xUpdate() {
setGlobalVar(V_KLAYMEN_FRAMEINDEX, _currFrameIndex);
}
-
+
uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam &param) {
switch (messageNum) {
case 0x4001:
@@ -4874,7 +4874,7 @@ uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481B:
if (param.asPoint().y != 0)
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
@@ -4897,7 +4897,7 @@ uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam &param) {
setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
gotoNextStateExt();
break;
- case 0x482E:
+ case 0x482E:
if (param.asInteger() == 1)
GotoState(&Klaymen::stWalkToFrontNoStep);
else
@@ -4914,7 +4914,7 @@ uint32 KmScene2206::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -4927,7 +4927,7 @@ KmScene2207::KmScene2207(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16
// Empty
}
-
+
uint32 KmScene2207::xHandleMessage(int messageNum, const MessageParam &param) {
switch (messageNum) {
case 0x2001:
@@ -4961,7 +4961,7 @@ uint32 KmScene2207::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481B:
if (param.asPoint().y != 0)
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
@@ -4977,7 +4977,7 @@ uint32 KmScene2207::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -5022,7 +5022,7 @@ uint32 KmScene2242::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481B:
if (param.asPoint().y != 0)
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
@@ -5080,7 +5080,7 @@ uint32 KmHallOfRecords::xHandleMessage(int messageNum, const MessageParam &param
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481F:
if (param.asInteger() == 0)
GotoState(&Klaymen::stWonderAboutHalf);
@@ -5133,7 +5133,7 @@ uint32 KmScene2247::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481F:
if (param.asInteger() == 0)
GotoState(&Klaymen::stWonderAboutHalf);
@@ -5156,13 +5156,13 @@ uint32 KmScene2247::xHandleMessage(int messageNum, const MessageParam &param) {
}
return 0;
}
-
+
KmScene2401::KmScene2401(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
// Empty
}
-
+
uint32 KmScene2401::xHandleMessage(int messageNum, const MessageParam &param) {
uint32 messageResult = 0;
switch (messageNum) {
@@ -5184,7 +5184,7 @@ uint32 KmScene2401::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481B:
if (param.asPoint().y != 0)
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
@@ -5203,7 +5203,7 @@ uint32 KmScene2401::xHandleMessage(int messageNum, const MessageParam &param) {
setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
gotoNextStateExt();
break;
- case 0x482E:
+ case 0x482E:
if (param.asInteger() == 1)
GotoState(&Klaymen::stWalkToFrontNoStep);
else
@@ -5228,7 +5228,7 @@ uint32 KmScene2401::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
- break;
+ break;
case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
@@ -5357,23 +5357,23 @@ uint32 KmScene2403::xHandleMessage(int messageNum, const MessageParam &param) {
else
GotoState(&Klaymen::stWonderAbout);
break;
- case 0x4820:
+ case 0x4820:
sendMessage(_parentScene, 0x2000, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
break;
- case 0x4821:
+ case 0x4821:
sendMessage(_parentScene, 0x2000, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
+ GotoState(&Klaymen::stStartClimbLadderDown);
break;
- case 0x4822:
+ case 0x4822:
sendMessage(_parentScene, 0x2000, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
+ GotoState(&Klaymen::stStartClimbLadderUp);
break;
case 0x4823:
sendMessage(_parentScene, 0x2001, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
+ GotoState(&Klaymen::stClimbLadderHalf);
break;
case 0x482D:
setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
@@ -5382,16 +5382,16 @@ uint32 KmScene2403::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x483F:
startSpecialWalkRight(param.asInteger());
break;
- case 0x4840:
+ case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
}
return messageResult;
}
-
+
KmScene2406::KmScene2406(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount)
: Klaymen(vm, parentScene, x, y) {
-
+
_surface->setClipRects(clipRects, clipRectsCount);
}
@@ -5425,7 +5425,7 @@ uint32 KmScene2406::xHandleMessage(int messageNum, const MessageParam &param) {
gotoNextStateExt();
break;
case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
+ GotoState(&Klaymen::stInsertDisk);
break;
case 0x481B:
if (param.asPoint().y != 0)
@@ -5451,40 +5451,40 @@ uint32 KmScene2406::xHandleMessage(int messageNum, const MessageParam &param) {
else
GotoState(&Klaymen::stWonderAbout);
break;
- case 0x4820:
+ case 0x4820:
sendMessage(_parentScene, 0x2000, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
break;
- case 0x4821:
+ case 0x4821:
sendMessage(_parentScene, 0x2000, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
+ GotoState(&Klaymen::stStartClimbLadderDown);
break;
- case 0x4822:
+ case 0x4822:
sendMessage(_parentScene, 0x2000, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
+ GotoState(&Klaymen::stStartClimbLadderUp);
break;
case 0x4823:
sendMessage(_parentScene, 0x2001, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
+ GotoState(&Klaymen::stClimbLadderHalf);
break;
case 0x483F:
startSpecialWalkRight(param.asInteger());
break;
- case 0x4840:
+ case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
}
return messageResult;
}
-
+
KmScene2501::KmScene2501(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
// Empty
}
-
+
uint32 KmScene2501::xHandleMessage(int messageNum, const MessageParam &param) {
uint32 messageResult = 0;
switch (messageNum) {
@@ -5505,7 +5505,7 @@ uint32 KmScene2501::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481D:
if (_isSittingInTeleporter)
GotoState(&Klaymen::stTurnToUseInTeleporter);
@@ -5521,7 +5521,7 @@ uint32 KmScene2501::xHandleMessage(int messageNum, const MessageParam &param) {
sendMessage(_parentScene, 0x2000, 1);
_isSittingInTeleporter = true;
GotoState(&Klaymen::stSitInTeleporter);
- break;
+ break;
case 0x4836:
sendMessage(_parentScene, 0x2000, 0);
_isSittingInTeleporter = false;
@@ -5536,7 +5536,7 @@ KmScene2732::KmScene2732(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16
// Empty
}
-
+
uint32 KmScene2732::xHandleMessage(int messageNum, const MessageParam &param) {
switch (messageNum) {
case 0x4804:
@@ -5570,13 +5570,13 @@ uint32 KmScene2801::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481B:
if (param.asPoint().y != 0)
startWalkToXDistance(param.asPoint().y, param.asPoint().x);
else
startWalkToAttachedSpriteXDistance(param.asPoint().x);
- break;
+ break;
case 0x481D:
GotoState(&Klaymen::stTurnToUse);
break;
@@ -5599,7 +5599,7 @@ uint32 KmScene2801::xHandleMessage(int messageNum, const MessageParam &param) {
setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
gotoNextStateExt();
break;
- case 0x482E:
+ case 0x482E:
if (param.asInteger() == 1)
GotoState(&Klaymen::stWalkToFrontNoStep);
else
@@ -5620,7 +5620,7 @@ uint32 KmScene2801::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene2803::KmScene2803(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, NRect *clipRects, int clipRectsCount)
: Klaymen(vm, parentScene, x, y) {
-
+
_surface->setClipRects(clipRects, clipRectsCount);
_dataResource.load(0x00900849);
}
@@ -5648,7 +5648,7 @@ uint32 KmScene2803::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x4818:
startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
break;
@@ -5664,7 +5664,7 @@ uint32 KmScene2803::xHandleMessage(int messageNum, const MessageParam &param) {
else
GotoState(&Klaymen::stWonderAboutHalf);
break;
- case 0x482E:
+ case 0x482E:
GotoState(&Klaymen::stWalkToFront);
break;
case 0x482F:
@@ -5682,7 +5682,7 @@ uint32 KmScene2803::xHandleMessage(int messageNum, const MessageParam &param) {
KmScene2803Small::KmScene2803Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
-
+
_dataResource.load(0x81120132);
}
@@ -5759,7 +5759,7 @@ uint32 KmScene2805::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x481D:
if (_isSittingInTeleporter)
GotoState(&Klaymen::stTurnToUseInTeleporter);
@@ -5775,7 +5775,7 @@ uint32 KmScene2805::xHandleMessage(int messageNum, const MessageParam &param) {
sendMessage(_parentScene, 0x2000, 1);
_isSittingInTeleporter = true;
GotoState(&Klaymen::stSitInTeleporter);
- break;
+ break;
case 0x4836:
sendMessage(_parentScene, 0x2000, 0);
_isSittingInTeleporter = false;
@@ -5805,7 +5805,7 @@ KmScene2806::KmScene2806(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16
loadSound(6, 0x166FC6E0);
loadSound(7, 0x00018040);
}
-
+
_dataResource.load(0x98182003);
_surface->setClipRects(clipRects, clipRectsCount);
}
@@ -5827,12 +5827,12 @@ uint32 KmScene2806::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x4816:
if (param.asInteger() == 0)
- GotoState(&Klaymen::stPressButtonSide);
+ GotoState(&Klaymen::stPressButtonSide);
break;
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x4818:
startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
break;
@@ -5885,12 +5885,12 @@ uint32 KmScene2809::xHandleMessage(int messageNum, const MessageParam &param) {
break;
case 0x4816:
if (param.asInteger() == 0)
- GotoState(&Klaymen::stPressButtonSide);
+ GotoState(&Klaymen::stPressButtonSide);
break;
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x4818:
startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
break;
@@ -5907,7 +5907,7 @@ uint32 KmScene2809::xHandleMessage(int messageNum, const MessageParam &param) {
return 0;
}
-KmScene2810Small::KmScene2810Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+KmScene2810Small::KmScene2810Small(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: Klaymen(vm, parentScene, x, y) {
// Empty
@@ -5925,7 +5925,7 @@ uint32 KmScene2810Small::xHandleMessage(int messageNum, const MessageParam &para
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x4818:
startWalkToXSmall(_dataResource.getPoint(param.asInteger()).x);
break;
@@ -5937,7 +5937,7 @@ uint32 KmScene2810Small::xHandleMessage(int messageNum, const MessageParam &para
else
GotoState(&Klaymen::stWonderAboutSmall);
break;
- case 0x482E:
+ case 0x482E:
if (param.asInteger() == 1)
GotoState(&Klaymen::stWalkToFrontNoStepSmall);
else
@@ -5961,7 +5961,7 @@ KmScene2810::KmScene2810(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16
_surface->setClipRects(clipRects, clipRectsCount);
}
-
+
uint32 KmScene2810::xHandleMessage(int messageNum, const MessageParam &param) {
switch (messageNum) {
case 0x4001:
@@ -5985,7 +5985,7 @@ uint32 KmScene2810::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x4817:
setDoDeltaX(param.asInteger());
gotoNextStateExt();
- break;
+ break;
case 0x4818:
startWalkToX(_dataResource.getPoint(param.asInteger()).x, false);
break;
@@ -6009,23 +6009,23 @@ uint32 KmScene2810::xHandleMessage(int messageNum, const MessageParam &param) {
else
GotoState(&Klaymen::stWonderAbout);
break;
- case 0x4820:
+ case 0x4820:
sendMessage(_parentScene, 0x2000, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
break;
- case 0x4821:
+ case 0x4821:
sendMessage(_parentScene, 0x2000, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
+ GotoState(&Klaymen::stStartClimbLadderDown);
break;
- case 0x4822:
+ case 0x4822:
sendMessage(_parentScene, 0x2000, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
+ GotoState(&Klaymen::stStartClimbLadderUp);
break;
case 0x4823:
sendMessage(_parentScene, 0x2001, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
+ GotoState(&Klaymen::stClimbLadderHalf);
break;
case 0x4824:
sendMessage(_parentScene, 0x2000, 0);
@@ -6080,7 +6080,7 @@ uint32 KmScene2812::xHandleMessage(int messageNum, const MessageParam &param) {
gotoNextStateExt();
break;
case 0x481A:
- GotoState(&Klaymen::stInsertDisk);
+ GotoState(&Klaymen::stInsertDisk);
break;
case 0x481B:
if (param.asPoint().y != 0)
@@ -6094,29 +6094,29 @@ uint32 KmScene2812::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x481E:
GotoState(&Klaymen::stReturnFromUse);
break;
- case 0x4820:
+ case 0x4820:
sendMessage(_parentScene, 0x2001, 0);
- GotoState(&Klaymen::stContinueClimbLadderUp);
+ GotoState(&Klaymen::stContinueClimbLadderUp);
break;
- case 0x4821:
+ case 0x4821:
sendMessage(_parentScene, 0x2001, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderDown);
+ GotoState(&Klaymen::stStartClimbLadderDown);
break;
- case 0x4822:
+ case 0x4822:
sendMessage(_parentScene, 0x2001, 0);
_destY = param.asInteger();
- GotoState(&Klaymen::stStartClimbLadderUp);
+ GotoState(&Klaymen::stStartClimbLadderUp);
break;
case 0x4823:
sendMessage(_parentScene, 0x2002, 0);
- GotoState(&Klaymen::stClimbLadderHalf);
+ GotoState(&Klaymen::stClimbLadderHalf);
break;
case 0x482D:
setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0);
gotoNextStateExt();
break;
- case 0x482E:
+ case 0x482E:
if (param.asInteger() == 1)
GotoState(&Klaymen::stWalkToFrontNoStep);
else
@@ -6131,7 +6131,7 @@ uint32 KmScene2812::xHandleMessage(int messageNum, const MessageParam &param) {
case 0x483F:
startSpecialWalkRight(param.asInteger());
break;
- case 0x4840:
+ case 0x4840:
startSpecialWalkLeft(param.asInteger());
break;
}
diff --git a/engines/neverhood/klaymen.h b/engines/neverhood/klaymen.h
index 25443b5a35..9e461a9c9c 100644
--- a/engines/neverhood/klaymen.h
+++ b/engines/neverhood/klaymen.h
@@ -77,24 +77,24 @@ public:
void stIdleArms();
void evIdleArmsDone();
uint32 hmIdleArms(int messageNum, const MessageParam &param, Entity *sender);
-
+
void stIdleChest();
uint32 hmIdleChest(int messageNum, const MessageParam &param, Entity *sender);
-
+
void stIdleHeadOff();
uint32 hmIdleHeadOff(int messageNum, const MessageParam &param, Entity *sender);
void stIdleWonderAbout();
void stIdleTeleporterHands();
-
+
void stIdleTeleporterHands2();
void stTryStandIdle();
void stStandAround();
void upStandIdle();
void stIdleBlink();
-
+
bool stStartAction(AnimationCb callback3);
bool stStartActionFromIdle(AnimationCb callback);
uint32 hmStartAction(int messageNum, const MessageParam &param, Entity *sender);
@@ -134,7 +134,7 @@ public:
void stPickUpTube();
uint32 hmPickUpTube(int messageNum, const MessageParam &param, Entity *sender);
-
+
void stTurnToUse();
void stTurnToUseHalf();
void stTurnAwayFromUse();
@@ -263,10 +263,10 @@ public:
void stJumpToGrabFall();
uint32 hmJumpToGrab(int messageNum, const MessageParam &param, Entity *sender);
void suJumpToGrab();
-
+
void stJumpToGrabRelease();
uint32 hmJumpToGrabRelease(int messageNum, const MessageParam &param, Entity *sender);
-
+
void stSitInTeleporter();
uint32 hmSitInTeleporter(int messageNum, const MessageParam &param, Entity *sender);
@@ -326,7 +326,7 @@ public:
void stFinishGrow();
uint32 hmFinishGrow(int messageNum, const MessageParam &param, Entity *sender);
-
+
void stJumpToRingVenusFlyTrap();
uint32 hmJumpToRingVenusFlyTrap(int messageNum, const MessageParam &param, Entity *sender);
@@ -363,7 +363,7 @@ public:
////////////////////////////////////////////////////////////////////////////
void stopWalking();
-
+
void suAction();
void suUpdateDestX();
void suWalkingTestExit();
@@ -375,7 +375,7 @@ public:
void setKlaymenIdleTable1();
void setKlaymenIdleTable2();
void setKlaymenIdleTable3();
-
+
void setSoundFlag(bool value) { _soundFlag = value; }
void spitIntoPipe();
@@ -416,7 +416,7 @@ protected:
NPointArray *_pathPoints;
bool _soundFlag;
-
+
int16 _spitOutCountdown;
bool _isSittingInTeleporter;
@@ -456,16 +456,16 @@ protected:
void stStartWalkingSmall();
uint32 hmWalkingSmall(int messageNum, const MessageParam &param, Entity *sender);
-
+
void enterIdleAnimation(uint idleAnimation);
void walkAlongPathPoints();
-
+
};
class KmScene1001 : public Klaymen {
public:
KmScene1001(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-protected:
+protected:
uint32 xHandleMessage(int messageNum, const MessageParam &param);
};
@@ -473,7 +473,7 @@ class KmScene1002 : public Klaymen {
public:
KmScene1002(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
protected:
- void xUpdate();
+ void xUpdate();
uint32 xHandleMessage(int messageNum, const MessageParam &param);
};
diff --git a/engines/neverhood/menumodule.cpp b/engines/neverhood/menumodule.cpp
index 8814401f5e..d59afa4ba5 100644
--- a/engines/neverhood/menumodule.cpp
+++ b/engines/neverhood/menumodule.cpp
@@ -73,9 +73,9 @@ static const uint32 kMakingOfSmackerFileHashList[] = {
MenuModule::MenuModule(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule), _savegameList(NULL) {
-
+
SetMessageHandler(&MenuModule::handleMessage);
-
+
_savedPaletteData = _vm->_screen->getPaletteData();
_vm->_mixer->pauseAll(true);
_vm->toggleSoundUpdate(false);
@@ -266,7 +266,7 @@ void MenuModule::loadSavegameList() {
Neverhood::NeverhoodEngine::SaveHeader header;
Common::String pattern = _vm->getTargetName();
pattern += ".???";
-
+
Common::StringArray filenames;
filenames = saveFileMan->listSavefiles(pattern.c_str());
Common::sort(filenames.begin(), filenames.end());
@@ -324,7 +324,7 @@ uint32 MenuButton::handleMessage(int messageNum, const MessageParam &param, Enti
MainMenu::MainMenu(NeverhoodEngine *vm, Module *parentModule)
: Scene(vm, parentModule) {
-
+
static const uint32 kMenuButtonFileHashes[] = {
0x36C62120,
0x56C62120,
@@ -336,7 +336,7 @@ MainMenu::MainMenu(NeverhoodEngine *vm, Module *parentModule)
0x16C62130,
0x16C62100
};
-
+
static const NRect kMenuButtonCollisionBounds[] = {
NRect(52, 121, 110, 156),
NRect(52, 192, 109, 222),
@@ -348,14 +348,14 @@ MainMenu::MainMenu(NeverhoodEngine *vm, Module *parentModule)
NRect(527, 384, 580, 412),
NRect(522, 255, 580, 289)
};
-
+
setBackground(0x08C0020C);
setPalette(0x08C0020C);
insertScreenMouse(0x00208084);
-
+
insertStaticSprite(0x41137051, 100);
insertStaticSprite(0xC10B2015, 100);
-
+
// TODO Only if music is enabled
_musicOnButton = insertStaticSprite(0x0C24C0EE, 100);
@@ -364,9 +364,9 @@ MainMenu::MainMenu(NeverhoodEngine *vm, Module *parentModule)
kMenuButtonFileHashes[buttonIndex], kMenuButtonCollisionBounds[buttonIndex]);
addCollisionSprite(menuButton);
}
-
- SetUpdateHandler(&Scene::update);
- SetMessageHandler(&MainMenu::handleMessage);
+
+ SetUpdateHandler(&Scene::update);
+ SetMessageHandler(&MainMenu::handleMessage);
}
@@ -396,18 +396,18 @@ CreditsScene::CreditsScene(NeverhoodEngine *vm, Module *parentModule, bool canAb
: Scene(vm, parentModule), _canAbort(canAbort), _screenIndex(0), _ticksDuration(0),
_countdown(216) {
- SetUpdateHandler(&CreditsScene::update);
+ SetUpdateHandler(&CreditsScene::update);
SetMessageHandler(&CreditsScene::handleMessage);
-
+
setBackground(0x6081128C);
setPalette(0x6081128C);
_ticksTime = _vm->_system->getMillis() + 202100;
-
+
_musicResource = new MusicResource(_vm);
_musicResource->load(0x30812225);
_musicResource->play(0);
-
+
}
CreditsScene::~CreditsScene() {
@@ -469,7 +469,7 @@ Widget::Widget(NeverhoodEngine *vm, int16 x, int16 y, GameStateMenu *parentScene
SetUpdateHandler(&Widget::update);
SetMessageHandler(&Widget::handleMessage);
-
+
setPosition(x, y);
}
@@ -532,7 +532,7 @@ TextLabelWidget::TextLabelWidget(NeverhoodEngine *vm, int16 x, int16 y, GameStat
const byte *string, int stringLen, BaseSurface *drawSurface, int16 tx, int16 ty, FontSurface *fontSurface)
: Widget(vm, x, y, parentScene, baseObjectPriority, baseSurfacePriority),
_string(string), _stringLen(stringLen), _drawSurface(drawSurface), _tx(tx), _ty(ty), _fontSurface(fontSurface) {
-
+
}
void TextLabelWidget::initialize() {
@@ -573,7 +573,7 @@ TextEditWidget::TextEditWidget(NeverhoodEngine *vm, int16 x, int16 y, GameStateM
_maxVisibleChars = (_rect.x2 - _rect.x1) / _fontSurface->getCharWidth();
_cursorPos = 0;
-
+
SetUpdateHandler(&TextEditWidget::update);
SetMessageHandler(&TextEditWidget::handleMessage);
}
@@ -766,9 +766,7 @@ void SavegameListBox::onClick() {
mousePos.y -= _y + _rect.y1;
if (mousePos.x >= 0 && mousePos.x <= _rect.x2 - _rect.x1 &&
mousePos.y >= 0 && mousePos.y <= _rect.y2 - _rect.y1) {
- // We add 1 to the char height to ensure that the correct entry is chosen if the
- // user clicks at the bottom the text entry
- int newIndex = _firstVisibleItem + mousePos.y / (_fontSurface->getCharHeight() + 1);
+ int newIndex = _firstVisibleItem + mousePos.y / _fontSurface->getCharHeight();
if (newIndex <= _lastVisibleItem) {
_currIndex = newIndex;
refresh();
@@ -806,7 +804,7 @@ void SavegameListBox::buildItems() {
void SavegameListBox::drawItems() {
for (int i = 0; i < (int)_textLabelItems.size(); ++i) {
- TextLabelWidget *label = _textLabelItems[i];
+ TextLabelWidget *label = _textLabelItems[i];
if (i >= _firstVisibleItem && i <= _lastVisibleItem) {
label->setY(_rect.y1 + (i - _firstVisibleItem) * _fontSurface->getCharHeight());
label->updateBounds();
@@ -888,12 +886,12 @@ int GameStateMenu::scummVMSaveLoadDialog(bool isSave, Common::String &saveDesc)
GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList,
const uint32 *buttonFileHashes, const NRect *buttonCollisionBounds,
uint32 backgroundFileHash, uint32 fontFileHash,
- uint32 mouseFileHash, const NRect *mouseRect,
+ uint32 mouseFileHash, const NRect *mouseRect,
uint32 listBoxBackgroundFileHash, int16 listBoxX, int16 listBoxY, const NRect &listBoxRect,
uint32 textEditBackgroundFileHash, uint32 textEditCursorFileHash, int16 textEditX, int16 textEditY, const NRect &textEditRect,
- uint32 textFileHash1, uint32 textFileHash2)
+ uint32 textFileHash1, uint32 textFileHash2)
: Scene(vm, parentModule), _currWidget(NULL), _savegameList(savegameList) {
-
+
bool isSave = (textEditCursorFileHash != 0);
_fontSurface = new FontSurface(_vm, fontFileHash, 32, 7, 32, 11, 17);
@@ -935,7 +933,7 @@ GameStateMenu::GameStateMenu(NeverhoodEngine *vm, Module *parentModule, Savegame
_textEditWidget->setReadOnly(true);
_textEditWidget->initialize();
setCurrWidget(_textEditWidget);
-
+
for (uint buttonIndex = 0; buttonIndex < 6; ++buttonIndex) {
Sprite *menuButton = insertSprite<MenuButton>(this, buttonIndex,
buttonFileHashes[buttonIndex], buttonCollisionBounds[buttonIndex]);
@@ -1109,7 +1107,7 @@ static const NRect kDeleteGameMenuTextEditRect(0, 0, 320, 17);
DeleteGameMenu::DeleteGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList)
: GameStateMenu(vm, parentModule, savegameList, kDeleteGameMenuButtonFileHashes, kDeleteGameMenuButtonCollisionBounds,
0x4080E01C, 0x728523ED,
- 0x0E018400, NULL,
+ 0x0E018400, NULL,
0xA5584211, 61, 64, kDeleteGameMenuListBoxRect,
0x250A3060, 0, 49, 414, kDeleteGameMenuTextEditRect,
0x80083C01, 0x84181E81) {
@@ -1133,7 +1131,7 @@ QueryOverwriteMenu::QueryOverwriteMenu(NeverhoodEngine *vm, Module *parentModule
NRect(145, 334, 260, 385),
NRect(365, 340, 477, 388)
};
-
+
setBackground(0x043692C4);
setPalette(0x043692C4);
insertScreenMouse(0x692C004B);
@@ -1156,7 +1154,7 @@ QueryOverwriteMenu::QueryOverwriteMenu(NeverhoodEngine *vm, Module *parentModule
fontSurface->drawString(_background->getSurface(), 106 + (423 - textLines[i].size() * 11) / 2,
127 + 31 + i * 17, (const byte*)textLines[i].c_str());
delete fontSurface;
-
+
SetUpdateHandler(&Scene::update);
SetMessageHandler(&QueryOverwriteMenu::handleMessage);
}
diff --git a/engines/neverhood/menumodule.h b/engines/neverhood/menumodule.h
index 6ee990de67..f201654ceb 100644
--- a/engines/neverhood/menumodule.h
+++ b/engines/neverhood/menumodule.h
@@ -124,8 +124,8 @@ protected:
class TextLabelWidget : public Widget {
public:
TextLabelWidget(NeverhoodEngine *vm, int16 x, int16 y, GameStateMenu *parentScene,
- int baseObjectPriority, int baseSurfacePriority,
- const byte *string, int stringLen, BaseSurface *drawSurface, int16 tx, int16 ty, FontSurface *fontSurface);
+ int baseObjectPriority, int baseSurfacePriority,
+ const byte *string, int stringLen, BaseSurface *drawSurface, int16 tx, int16 ty, FontSurface *fontSurface);
virtual void initialize();
virtual int16 getWidth();
virtual int16 getHeight();
@@ -206,13 +206,13 @@ protected:
uint _currIndex;
int _maxVisibleItemsCount;
};
-
+
class GameStateMenu : public Scene {
public:
GameStateMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList,
const uint32 *buttonFileHashes, const NRect *buttonCollisionBounds,
uint32 backgroundFileHash, uint32 fontFileHash,
- uint32 mouseFileHash, const NRect *mouseRect,
+ uint32 mouseFileHash, const NRect *mouseRect,
uint32 listBoxBackgroundFileHash, int16 listBoxX, int16 listBoxY, const NRect &listBoxRect,
uint32 textEditBackgroundFileHash, uint32 textEditCursorFileHash, int16 textEditX, int16 textEditY, const NRect &textEditRect,
uint32 textFileHash1, uint32 textFileHash2);
diff --git a/engines/neverhood/module.cpp b/engines/neverhood/module.cpp
index e384b5a4d2..d1578e680c 100644
--- a/engines/neverhood/module.cpp
+++ b/engines/neverhood/module.cpp
@@ -31,9 +31,9 @@ namespace Neverhood {
Module::Module(NeverhoodEngine *vm, Module *parentModule)
: Entity(vm, 0), _parentModule(parentModule), _childObject(NULL),
_done(false), _sceneType(kSceneTypeNormal) {
-
+
SetMessageHandler(&Module::handleMessage);
-
+
}
Module::~Module() {
diff --git a/engines/neverhood/modules/module1000.cpp b/engines/neverhood/modules/module1000.cpp
index a28d934cf6..f65b89899d 100644
--- a/engines/neverhood/modules/module1000.cpp
+++ b/engines/neverhood/modules/module1000.cpp
@@ -26,8 +26,8 @@ namespace Neverhood {
Module1000::Module1000(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
- _musicFileHash = getGlobalVar(V_ENTRANCE_OPEN) ? 0x81106480 : 0x00103144;
+
+ _musicFileHash = getGlobalVar(V_ENTRANCE_OPEN) ? 0x81106480 : 0x00103144;
_vm->_soundMan->addMusic(0x03294419, 0x061880C6);
_vm->_soundMan->addMusic(0x03294419, _musicFileHash);
@@ -118,11 +118,11 @@ void Module1000::updateScene() {
}
}
-// Scene1001
+// Scene1001
AsScene1001Door::AsScene1001Door(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1100) {
-
+
createSurface(800, 137, 242);
_x = 726;
_y = 440;
@@ -151,16 +151,16 @@ void AsScene1001Door::hammerHitsDoor() {
case 1:
playSound(0, 0x65482F03);
startAnimation(0x624C0498, 1, 3);
- NextState(&AsScene1001Door::stShowIdleDoor);
+ NextState(&AsScene1001Door::stShowIdleDoor);
break;
case 2:
playSound(1);
startAnimation(0x624C0498, 6, 6);
- NextState(&AsScene1001Door::stBustedDoorMove);
+ NextState(&AsScene1001Door::stBustedDoorMove);
break;
default:
// Nothing
- break;
+ break;
}
incGlobalVar(V_DOOR_STATUS, 1);
}
@@ -196,9 +196,9 @@ void AsScene1001Door::stBustedDoorMove() {
void AsScene1001Door::stBustedDoorGone() {
playSound(0);
stopAnimation();
- setVisible(false);
+ setVisible(false);
}
-
+
AsScene1001Hammer::AsScene1001Hammer(NeverhoodEngine *vm, Sprite *asDoor)
: AnimatedSprite(vm, 1100), _asDoor(asDoor) {
@@ -262,7 +262,7 @@ uint32 AsScene1001Window::handleMessage(int messageNum, const MessageParam &para
AsScene1001Lever::AsScene1001Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int deltaXType)
: AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
+
createSurface(1010, 71, 73);
setDoDeltaX(deltaXType);
startAnimation(0x04A98C36, 0, -1);
@@ -302,22 +302,22 @@ uint32 AsScene1001Lever::handleMessage(int messageNum, const MessageParam &param
}
return messageResult;
}
-
+
SsCommonButtonSprite::SsCommonButtonSprite(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, int surfacePriority, uint32 soundFileHash)
: StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene), _countdown(0) {
_priority = 1100;
- _soundFileHash = soundFileHash ? soundFileHash : 0x44141000;
+ _soundFileHash = soundFileHash ? soundFileHash : 0x44141000;
setVisible(false);
SetUpdateHandler(&SsCommonButtonSprite::update);
SetMessageHandler(&SsCommonButtonSprite::handleMessage);
}
-
+
void SsCommonButtonSprite::update() {
if (_countdown != 0 && (--_countdown) == 0)
setVisible(false);
}
-
+
uint32 SsCommonButtonSprite::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
switch (messageNum) {
@@ -330,19 +330,19 @@ uint32 SsCommonButtonSprite::handleMessage(int messageNum, const MessageParam &p
}
return messageResult;
}
-
+
Scene1001::Scene1001(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _asDoor(NULL), _asWindow(NULL) {
Sprite *tempSprite;
SetMessageHandler(&Scene1001::handleMessage);
-
+
setHitRects(0x004B4860);
setBackground(0x4086520E);
setPalette(0x4086520E);
insertScreenMouse(0x6520A400);
-
+
if (which < 0) {
// Restoring game
setRectList(0x004B49F0);
@@ -373,7 +373,7 @@ Scene1001::Scene1001(NeverhoodEngine *vm, Module *parentModule, int which)
tempSprite = insertStaticSprite(0x2080A3A8, 1300);
_klaymen->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480);
-
+
if (!getGlobalVar(V_DOOR_BUSTED)) {
_asDoor = insertSprite<AsScene1001Door>();
_asDoor->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480);
@@ -445,7 +445,7 @@ AsScene1002Ring::AsScene1002Ring(NeverhoodEngine *vm, Scene *parentScene, bool i
: AnimatedSprite(vm, 1100), _parentScene(parentScene), _isSpecial(isSpecial) {
SetUpdateHandler(&AsScene1002Ring::update);
-
+
if (_isSpecial) {
createSurface(990, 68, 314);
if (isRingLow) {
@@ -581,7 +581,7 @@ uint32 AsScene1002Ring::hmRingReleased(int messageNum, const MessageParam &param
AsScene1002Door::AsScene1002Door(NeverhoodEngine *vm, NRect &clipRect)
: StaticSprite(vm, 1200) {
-
+
loadSprite(0x1052370F, kSLFDefDrawOffset | kSLFSetPosition, 800, 526, getGlobalVar(V_FLYTRAP_RING_DOOR) ? 49 : 239);
setClipRect(clipRect);
SetUpdateHandler(&AsScene1002Door::update);
@@ -637,7 +637,7 @@ AsScene1002BoxingGloveHitEffect::AsScene1002BoxingGloveHitEffect(NeverhoodEngine
createSurface(1025, 88, 165);
setVisible(false);
SetUpdateHandler(&AnimatedSprite::update);
- SetMessageHandler(&AsScene1002BoxingGloveHitEffect::handleMessage);
+ SetMessageHandler(&AsScene1002BoxingGloveHitEffect::handleMessage);
}
uint32 AsScene1002BoxingGloveHitEffect::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -716,7 +716,7 @@ void AsScene1002DoorSpy::stDoorSpyBoxingGlove() {
NextState(&AsScene1002DoorSpy::stDoorSpyIdle);
}
-SsCommonPressButton::SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash)
+SsCommonPressButton::SsCommonPressButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash)
: StaticSprite(vm, 1100), _parentScene(parentScene), _status(0), _countdown(0) {
_soundFileHash = soundFileHash != 0 ? soundFileHash : 0x44141000;
@@ -788,7 +788,7 @@ AsScene1002VenusFlyTrap::AsScene1002VenusFlyTrap(NeverhoodEngine *vm, Scene *par
stRingGrabbed();
} else {
stIdle();
- }
+ }
}
_flags = 4;
SetUpdateHandler(&AsScene1002VenusFlyTrap::update);
@@ -850,12 +850,12 @@ uint32 AsScene1002VenusFlyTrap::handleMessage(int messageNum, const MessageParam
if (_isSecond) {
if (_x >= 154 && _x <= 346)
messageResult = 1;
- else
+ else
messageResult = 0;
} else {
if (_x >= 174 && _x <= 430)
messageResult = 1;
- else
+ else
messageResult = 0;
}
break;
@@ -1023,7 +1023,7 @@ AsScene1002OutsideDoorBackground::AsScene1002OutsideDoorBackground(NeverhoodEngi
} else
setVisible(false);
SetUpdateHandler(&AsScene1002OutsideDoorBackground::update);
- SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage);
+ SetMessageHandler(&AsScene1002OutsideDoorBackground::handleMessage);
}
void AsScene1002OutsideDoorBackground::update() {
@@ -1083,7 +1083,7 @@ void AsScene1002OutsideDoorBackground::stDoorClosed() {
AsScene1002KlaymenLadderHands::AsScene1002KlaymenLadderHands(NeverhoodEngine *vm, Klaymen *klaymen)
: AnimatedSprite(vm, 1200), _klaymen(klaymen) {
-
+
createSurface(1200, 40, 163);
setVisible(false);
SetUpdateHandler(&AsScene1002KlaymenLadderHands::update);
@@ -1095,15 +1095,15 @@ void AsScene1002KlaymenLadderHands::update() {
startAnimation(0xBA280522, _klaymen->getFrameIndex(), -1);
_newStickFrameIndex = _klaymen->getFrameIndex();
setVisible(true);
- _x = _klaymen->getX();
- _y = _klaymen->getY();
+ _x = _klaymen->getX();
+ _y = _klaymen->getY();
setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0);
} else if (_klaymen->getCurrAnimFileHash() == 0x122D1505) {
startAnimation(0x1319150C, _klaymen->getFrameIndex(), -1);
_newStickFrameIndex = _klaymen->getFrameIndex();
setVisible(true);
- _x = _klaymen->getX();
- _y = _klaymen->getY();
+ _x = _klaymen->getX();
+ _y = _klaymen->getY();
setDoDeltaX(_klaymen->isDoDeltaX() ? 1 : 0);
} else
setVisible(false);
@@ -1113,7 +1113,7 @@ void AsScene1002KlaymenLadderHands::update() {
AsScene1002KlaymenPeekHand::AsScene1002KlaymenPeekHand(NeverhoodEngine *vm, Scene *parentScene, Klaymen *klaymen)
: AnimatedSprite(vm, 1200), _parentScene(parentScene), _klaymen(klaymen),
_isClipRectSaved(false) {
-
+
createSurface(1000, 33, 41);
setVisible(false);
SetUpdateHandler(&AsScene1002KlaymenPeekHand::update);
@@ -1245,7 +1245,7 @@ Scene1002::Scene1002(NeverhoodEngine *vm, Module *parentModule, int which)
sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap);
_asOutsideDoorBackground = insertSprite<AsScene1002OutsideDoorBackground>();
-
+
setRectList(0x004B43A0);
loadSound(1, 0x60755842);
@@ -1322,11 +1322,11 @@ uint32 Scene1002::handleMessage(int messageNum, const MessageParam &param, Entit
break;
case 0x2002:
_messageList = NULL;
- break;
+ break;
case 0x2005:
_isClimbingLadder = true;
setRectList(0x004B4418);
- break;
+ break;
case 0x2006:
_isClimbingLadder = false;
setRectList(0x004B43A0);
@@ -1360,11 +1360,11 @@ uint32 Scene1002::handleMessage(int messageNum, const MessageParam &param, Entit
if (getGlobalVar(V_FLYTRAP_RING_DOOR)) {
sendMessage(_asRing3, 0x4807, 0);
}
- }
+ }
break;
case 0x480B:
sendEntityMessage(_klaymen, 0x1014, _asDoorSpy);
- break;
+ break;
case 0x480F:
setGlobalVar(V_RADIO_ENABLED, 0);
playSound(1);
@@ -1379,7 +1379,7 @@ uint32 Scene1002::handleMessage(int messageNum, const MessageParam &param, Entit
setSpriteSurfacePriority(_ssCeiling, 1015);
setSpriteSurfacePriority(_ssLadderArch, 1015);
break;
- }
+ }
return messageResult;
}
@@ -1389,7 +1389,7 @@ StaticScene::StaticScene(NeverhoodEngine *vm, Module *parentModule, uint32 backg
: Scene(vm, parentModule) {
SetMessageHandler(&StaticScene::handleMessage);
-
+
setBackground(backgroundFileHash);
setPalette(backgroundFileHash);
insertPuzzleMouse(cursorFileHash, 20, 620);
@@ -1442,7 +1442,7 @@ Scene1004::Scene1004(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _paletteAreaStatus(-1) {
Sprite *tempSprite;
-
+
SetUpdateHandler(&Scene1004::update);
SetMessageHandler(&Scene1004::handleMessage);
@@ -1475,16 +1475,16 @@ Scene1004::Scene1004(NeverhoodEngine *vm, Module *parentModule, int which)
insertKlaymen<KmScene1004>(_dataResource.getPoint(0x80052A29).x, 27);
setMessageList(0x004B7BF0);
}
-
+
updatePaletteArea();
-
+
_asKlaymenLadderHands = insertSprite<AsScene1002KlaymenLadderHands>(_klaymen);
insertStaticSprite(0x800034A0, 1100);
insertStaticSprite(0x64402020, 1100);
insertStaticSprite(0x3060222E, 1300);
tempSprite = insertStaticSprite(0x0E002004, 1300);
-
+
_klaymen->setClipRect(0, tempSprite->getDrawRect().y, 640, 480);
_asKlaymenLadderHands->setClipRect(_klaymen->getClipRect());
@@ -1518,7 +1518,7 @@ uint32 Scene1004::handleMessage(int messageNum, const MessageParam &param, Entit
break;
}
return messageResult;
-}
+}
void Scene1004::updatePaletteArea() {
if (_klaymen->getY() < 150) {
@@ -1557,7 +1557,7 @@ Scene1005::Scene1005(NeverhoodEngine *vm, Module *parentModule, int which)
}
drawTextToBackground();
-
+
}
uint32 Scene1005::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -1565,7 +1565,7 @@ uint32 Scene1005::handleMessage(int messageNum, const MessageParam &param, Entit
switch (messageNum) {
case 0x0001:
if (param.asPoint().x <= 20 || param.asPoint().x >= 620)
- leaveScene(0);
+ leaveScene(0);
break;
}
return 0;
@@ -1614,19 +1614,19 @@ uint32 Scene1005::getTextIndex1() {
textIndex = 23;
else if (!getSubVar(VA_HAS_KEY, 0) && !getSubVar(VA_IS_KEY_INSERTED, 0))
textIndex = 24;
- else if (!getGlobalVar(V_HAS_FINAL_KEY))
+ else if (!getGlobalVar(V_HAS_FINAL_KEY))
textIndex = 26;
else if (!getSubVar(VA_HAS_KEY, 1) && !getSubVar(VA_IS_KEY_INSERTED, 1))
textIndex = 27;
- else if (!getGlobalVar(V_HAS_FINAL_KEY))
+ else if (!getGlobalVar(V_HAS_FINAL_KEY))
textIndex = 28;
- else
+ else
textIndex = 29;
} else if (!getGlobalVar(V_FELL_DOWN_HOLE))
textIndex = 20;
else if (!getGlobalVar(V_SEEN_SYMBOLS_NO_LIGHT))
textIndex = 21;
- else
+ else
textIndex = 22;
} else if (getGlobalVar(V_BOLT_DOOR_UNLOCKED)) {
if (!getGlobalVar(V_WALL_BROKEN))
@@ -1641,7 +1641,7 @@ uint32 Scene1005::getTextIndex1() {
textIndex = 15;
else if (!getGlobalVar(V_BEEN_STATUE_ROOM))
textIndex = 16;
- else
+ else
textIndex = 17;
} else if (!getGlobalVar(V_FLYTRAP_RING_EATEN)) {
textIndex = 0;
@@ -1660,7 +1660,7 @@ uint32 Scene1005::getTextIndex1() {
textIndex = 9;
else if (!getSubVar(VA_LOCKS_DISABLED, 0x01180951))
textIndex = 10;
- else
+ else
textIndex = 11;
} else if (!getGlobalVar(V_CREATURE_ANGRY)) {
textIndex = 1;
diff --git a/engines/neverhood/modules/module1000.h b/engines/neverhood/modules/module1000.h
index 9977590a6a..8461ecfc6f 100644
--- a/engines/neverhood/modules/module1000.h
+++ b/engines/neverhood/modules/module1000.h
@@ -85,7 +85,7 @@ protected:
Scene *_parentScene;
uint32 _soundFileHash;
int16 _countdown;
- void update();
+ void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
diff --git a/engines/neverhood/modules/module1100.cpp b/engines/neverhood/modules/module1100.cpp
index dbd8c60210..03810915dd 100644
--- a/engines/neverhood/modules/module1100.cpp
+++ b/engines/neverhood/modules/module1100.cpp
@@ -40,7 +40,7 @@ static const uint32 kModule1100SoundList[] = {
Module1100::Module1100(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
if (which < 0) {
createScene(_vm->gameState().sceneNum, -1);
} else if (which == 1) {
@@ -271,7 +271,7 @@ static const uint32 kSsScene1105SymbolDieFileHashes[] = {
SsScene1105Button::SsScene1105Button(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash, NRect &collisionBounds)
: StaticSprite(vm, fileHash, 200), _parentScene(parentScene), _countdown(0) {
-
+
_collisionBounds = collisionBounds;
SetMessageHandler(&SsScene1105Button::handleMessage);
SetUpdateHandler(&SsScene1105Button::update);
@@ -347,7 +347,7 @@ void SsScene1105SymbolDie::hide() {
AsScene1105TeddyBear::AsScene1105TeddyBear(NeverhoodEngine *vm, Scene *parentScene)
: AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
+
createSurface(100, 556, 328);
_x = 320;
_y = 240;
@@ -396,7 +396,7 @@ void AsScene1105TeddyBear::hide() {
SsScene1105OpenButton::SsScene1105OpenButton(NeverhoodEngine *vm, Scene *parentScene)
: StaticSprite(vm, 900), _parentScene(parentScene), _countdown(0), _isClicked(false) {
-
+
loadSprite(0x8228A46C, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
setVisible(false);
loadSound(0, 0x44045140);
@@ -432,26 +432,26 @@ uint32 SsScene1105OpenButton::handleMessage(int messageNum, const MessageParam &
Scene1105::Scene1105(NeverhoodEngine *vm, Module *parentModule)
: Scene(vm, parentModule), _countdown(0), _isPanelOpen(false), _isActionButtonClicked(false), _doMoveTeddy(false),
_isClosePanelDone(false), _leaveResult(0), _backgroundIndex(0) {
-
+
Sprite *ssOpenButton;
-
+
_vm->gameModule()->initMemoryPuzzle();
-
+
SetUpdateHandler(&Scene1105::update);
SetMessageHandler(&Scene1105::handleMessage);
-
+
setBackground(0x20010002);
setPalette(0x20010002);
-
+
_asTeddyBear = insertSprite<AsScene1105TeddyBear>(this);
ssOpenButton = insertSprite<SsScene1105OpenButton>(this);
addCollisionSprite(ssOpenButton);
insertPuzzleMouse(0x10006208, 20, 620);
-
+
loadSound(0, 0x48442057);
loadSound(1, 0xC025014F);
loadSound(2, 0x68E25540);
-
+
}
uint32 Scene1105::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -569,13 +569,13 @@ void Scene1105::createObjects() {
addCollisionSprite(_ssSymbol3DownButton);
_ssActionButton = insertSprite<SsScene1105Button>(this, 0x8248AD35, NRect(280, 170, 354, 245));
addCollisionSprite(_ssActionButton);
-
+
_isPanelOpen = true;
-
+
_asTeddyBear->show();
insertPuzzleMouse(0x18666208, 20, 620);
-
+
}
void Scene1105::upOpenPanel() {
@@ -639,13 +639,13 @@ void Scene1105::update() {
Scene1109::Scene1109(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
SetMessageHandler(&Scene1109::handleMessage);
-
+
setBackground(0x8449E02F);
setPalette(0x8449E02F);
insertScreenMouse(0x9E02B84C);
-
+
_sprite1 = insertStaticSprite(0x600CEF01, 1100);
if (which < 0) {
diff --git a/engines/neverhood/modules/module1200.cpp b/engines/neverhood/modules/module1200.cpp
index 3e67ddb35a..e7766419f9 100644
--- a/engines/neverhood/modules/module1200.cpp
+++ b/engines/neverhood/modules/module1200.cpp
@@ -26,7 +26,7 @@ namespace Neverhood {
Module1200::Module1200(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
SetMessageHandler(&Module1200::handleMessage);
if (which < 0)
@@ -124,7 +124,7 @@ static const uint32 kScene1201TntFileHashList2[] = {
0xB140A1E6, 0x5088A068, 0x5088A068,
0x74C4C866, 0x3192C059, 0x3192C059
};
-
+
SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2)
: StaticSprite(vm, 900) {
@@ -133,13 +133,13 @@ SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 poi
if (x < 300)
loadSprite(kScene1201TntFileHashList1[elemIndex], kSLFDefDrawOffset | kSLFDefPosition, 50);
else
- loadSprite(kScene1201TntFileHashList2[elemIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 50, x, y);
+ loadSprite(kScene1201TntFileHashList2[elemIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 50, x, y - 20);
setClipRect(0, 0, 640, clipY2);
}
-
+
AsScene1201Tape::AsScene1201Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 nameHash, int surfacePriority, int16 x, int16 y, uint32 fileHash)
: AnimatedSprite(vm, fileHash, surfacePriority, x, y), _parentScene(parentScene), _nameHash(nameHash) {
-
+
if (!getSubVar(VA_HAS_TAPE, _nameHash) && !getSubVar(VA_IS_TAPE_INSERTED, _nameHash)) {
SetMessageHandler(&AsScene1201Tape::handleMessage);
} else {
@@ -253,10 +253,10 @@ void AsScene1201RightDoor::stCloseDoorDone() {
stopAnimation();
setVisible(false);
}
-
+
AsScene1201KlaymenHead::AsScene1201KlaymenHead(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1200) {
-
+
createSurface(1200, 69, 98);
SetUpdateHandler(&AnimatedSprite::update);
SetMessageHandler(&AsScene1201KlaymenHead::handleMessage);
@@ -301,7 +301,7 @@ AsScene1201TntMan::AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sp
AsScene1201TntMan::~AsScene1201TntMan() {
_vm->_soundMan->deleteSoundGroup(0x01D00560);
-}
+}
uint32 AsScene1201TntMan::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
@@ -396,7 +396,7 @@ void AsScene1201TntManFlame::suUpdate() {
AsScene1201Match::AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene)
: AnimatedSprite(vm, 1100), _parentScene(parentScene), _countdown(0) {
-
+
createSurface(1100, 57, 60);
SetUpdateHandler(&AsScene1201Match::update);
SetMessageHandler(&AsScene1201Match::hmOnDoorFrameAboutToMove);
@@ -518,7 +518,7 @@ AsScene1201Creature::AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene
: AnimatedSprite(vm, 900), _parentScene(parentScene), _klaymen(klaymen), _klaymenTooClose(false) {
// NOTE: _countdown2 and _countdown3 were unused/without effect and thus removed
-
+
createSurface(1100, 203, 199);
SetUpdateHandler(&AsScene1201Creature::update);
SetMessageHandler(&AsScene1201Creature::hmWaiting);
@@ -664,7 +664,7 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
SetMessageHandler(&Scene1201::handleMessage);
setHitRects(0x004AEBD0);
-
+
if (!getSubVar(VA_IS_PUZZLE_INIT, 0xE8058B52)) {
setSubVar(VA_IS_PUZZLE_INIT, 0xE8058B52, 1);
for (uint32 index = 0; index < 18; index++)
@@ -672,25 +672,25 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
}
insertScreenMouse(0x9A2C0409);
-
+
_asTape = insertSprite<AsScene1201Tape>(this, 3, 1100, 243, 340, 0x9148A011);
addCollisionSprite(_asTape);
-
+
tempSprite = insertStaticSprite(0x03C82530, 100);
- topY1 = tempSprite->getY() + tempSprite->getDrawRect().height;
+ topY1 = tempSprite->getY() + tempSprite->getDrawRect().height;
tempSprite = insertStaticSprite(0x88182069, 200);
- topY2 = tempSprite->getY() + tempSprite->getDrawRect().height;
+ topY2 = tempSprite->getY() + tempSprite->getDrawRect().height;
tempSprite = insertStaticSprite(0x476014E0, 300);
- topY3 = tempSprite->getY() + tempSprite->getDrawRect().height;
+ topY3 = tempSprite->getY() + tempSprite->getDrawRect().height;
tempSprite = insertStaticSprite(0x04063110, 500);
- topY4 = tempSprite->getY() + 1;
+ topY4 = tempSprite->getY() + 1;
_asTntManRope = insertSprite<AsScene1201TntManRope>(getGlobalVar(V_TNT_DUMMY_BUILT) && which != 1);
_asTntManRope->setClipRect(0, topY4, 640, 480);
-
+
insertStaticSprite(0x400B04B0, 1200);
tempSprite = insertStaticSprite(0x40295462, 1200);
@@ -735,7 +735,7 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
_klaymen->setClipRect(x1, 0, x2, 480);
_klaymen->setRepl(64, 0);
-
+
if (getGlobalVar(V_CREATURE_ANGRY) && !getGlobalVar(V_CREATURE_EXPLODED)) {
setBackground(0x4019A2C4);
setPalette(0x4019A2C4);
@@ -756,8 +756,8 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
tempSprite = insertSprite<AsScene1201TntManFlame>(_asTntMan);
tempSprite->setClipRect(x1, 0, x2, 480);
}
-
- uint32 tntIndex = 1;
+
+ uint32 tntIndex = 1;
while (tntIndex < 18) {
uint32 elemIndex = getSubVar(VA_TNT_POSITIONS, tntIndex);
int16 clipY2;
@@ -783,10 +783,10 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
setRectList(0x004AEE58);
} else {
setRectList(0x004AEDC8);
- }
-
+ }
+
} else {
-
+
insertStaticSprite(0x8E8A1981, 900);
uint32 tntIndex = 0;
@@ -795,7 +795,7 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
int16 clipY2;
if (kScene1201PointArray[elemIndex].x < 300) {
clipY2 = 480;
- } else {
+ } else {
if (kScene1201PointArray[elemIndex].y < 175)
clipY2 = topY1;
else if (kScene1201PointArray[elemIndex].y < 230)
@@ -811,7 +811,7 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which)
setRectList(0x004AEE18);
else
setRectList(0x004AED88);
-
+
}
tempSprite = insertStaticSprite(0x63D400BC, 900);
@@ -875,7 +875,7 @@ uint32 Scene1201::handleMessage(int messageNum, const MessageParam &param, Entit
setMessageList2(0x004AECC0);
}
break;
- case 0x2002:
+ case 0x2002:
if (getGlobalVar(V_TNT_DUMMY_FUSE_LIT)) {
// Move the TNT dummy if the fuse is burning
sendEntityMessage(_klaymen, 0x1014, _asTntMan);
@@ -903,7 +903,7 @@ uint32 Scene1201::handleMessage(int messageNum, const MessageParam &param, Entit
break;
case 0x8000:
sendMessage(_asKlaymenHead, 0x2006, 0);
- break;
+ break;
}
return messageResult;
}
@@ -956,7 +956,7 @@ uint32 AsScene1202TntItem::hmShowIdle(int messageNum, const MessageParam &param,
case 0x2001:
_newPosition = (int)param.asInteger();
stChangePositionFadeOut();
- break;
+ break;
}
return messageResult;
}
@@ -998,7 +998,7 @@ void AsScene1202TntItem::stChangePositionDone() {
}
Scene1202::Scene1202(NeverhoodEngine *vm, Module *parentModule)
- : Scene(vm, parentModule), _paletteResource(vm),
+ : Scene(vm, parentModule), _paletteResource(vm),
_soundToggle(true), _isPuzzleSolved(false), _counter(0), _clickedIndex(-1) {
SetMessageHandler(&Scene1202::handleMessage);
@@ -1093,8 +1093,8 @@ uint32 Scene1202::hmSolved(int messageNum, const MessageParam &param, Entity *se
}
bool Scene1202::isSolved() {
- return
- getSubVar(VA_TNT_POSITIONS, 0) == 0 && getSubVar(VA_TNT_POSITIONS, 3) == 3 &&
+ return
+ getSubVar(VA_TNT_POSITIONS, 0) == 0 && getSubVar(VA_TNT_POSITIONS, 3) == 3 &&
getSubVar(VA_TNT_POSITIONS, 6) == 6 && getSubVar(VA_TNT_POSITIONS, 9) == 9 &&
getSubVar(VA_TNT_POSITIONS, 12) == 12 && getSubVar(VA_TNT_POSITIONS, 15) == 15;
}
diff --git a/engines/neverhood/modules/module1300.cpp b/engines/neverhood/modules/module1300.cpp
index cc5c22085c..c8a561af76 100644
--- a/engines/neverhood/modules/module1300.cpp
+++ b/engines/neverhood/modules/module1300.cpp
@@ -45,7 +45,7 @@ static const uint32 kModule1300SoundList[] = {
Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
_vm->_soundMan->addMusic(0x61C090, 0x00203197);
_vm->_soundMan->addSoundList(0x61C090, kModule1300SoundList);
_vm->_soundMan->setSoundListParams(kModule1300SoundList, false, 50, 600, 20, 150);
@@ -56,7 +56,7 @@ Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which)
if (which < 0) {
if (_vm->gameState().sceneNum >= 1 && _vm->gameState().sceneNum <= 17)
createScene(_vm->gameState().sceneNum, -1);
- else
+ else
createScene(11, 0);
} else {
switch (which) {
@@ -101,7 +101,7 @@ Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which)
break;
}
}
-
+
}
Module1300::~Module1300() {
@@ -218,7 +218,7 @@ void Module1300::createScene(int sceneNum, int which) {
SetUpdateHandler(&Module1300::updateScene);
_childObject->handleUpdate();
}
-
+
void Module1300::updateScene() {
if (!updateChild()) {
switch (_sceneNum) {
@@ -274,7 +274,7 @@ void Module1300::updateScene() {
createScene(11, 1);
break;
case 12:
- if (_moduleResult == 0)
+ if (_moduleResult == 0)
createScene(14, 1);
else if (_moduleResult == 1)
createScene(15, 1);
@@ -367,7 +367,7 @@ void AsScene1302Bridge::cbLowerBridgeEvent() {
SsScene1302Fence::SsScene1302Fence(NeverhoodEngine *vm)
: StaticSprite(vm, 0x11122122, 200) {
-
+
_firstY = _y;
if (getGlobalVar(V_FLYTRAP_RING_FENCE))
_y += 152;
@@ -459,7 +459,7 @@ Scene1302::Scene1302(NeverhoodEngine *vm, Module *parentModule, int which)
addCollisionSprite(_asVenusFlyTrap);
sendEntityMessage(_klaymen, 0x2007, _asVenusFlyTrap);
-
+
}
uint32 Scene1302::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -513,7 +513,7 @@ uint32 Scene1302::handleMessage(int messageNum, const MessageParam &param, Entit
case 0x2000:
if (_klaymen->getY() > 360) {
sendEntityMessage(_klaymen, 0x1014, _asVenusFlyTrap);
- setMessageList2(0x004B08F0);
+ setMessageList2(0x004B08F0);
} else
setMessageList2(0x004B0920);
break;
@@ -583,7 +583,7 @@ uint32 Scene1302::handleMessage(int messageNum, const MessageParam &param, Entit
AsScene1303Balloon::AsScene1303Balloon(NeverhoodEngine *vm, Scene *parentScene)
: AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
+
createSurface(200, 128, 315);
_x = 289;
_y = 390;
@@ -643,7 +643,7 @@ Scene1303::Scene1303(NeverhoodEngine *vm, Module *parentModule)
_asBalloon = insertSprite<AsScene1303Balloon>(this);
addCollisionSprite(_asBalloon);
}
-
+
_sprite1 = insertStaticSprite(0xA014216B, 1100);
insertKlaymen<KmScene1303>(207, 332);
@@ -671,7 +671,7 @@ uint32 Scene1303::handleMessage(int messageNum, const MessageParam &param, Entit
AsScene1304Needle::AsScene1304Needle(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, int16 x, int16 y)
: AnimatedSprite(vm, 0x548E9411, surfacePriority, x, y), _parentScene(parentScene) {
- // NOTE: Skipped check if Klaymen already has the needle since that's done in the scene itself
+ // NOTE: Skipped check if Klaymen already has the needle since that's done in the scene itself
SetMessageHandler(&AsScene1304Needle::handleMessage);
}
@@ -693,14 +693,14 @@ uint32 AsScene1304Needle::handleMessage(int messageNum, const MessageParam &para
Scene1304::Scene1304(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _asNeedle(NULL) {
-
+
SetMessageHandler(&Scene1304::handleMessage);
setRectList(0x004B91A8);
setBackground(0x062C0214);
setPalette(0x062C0214);
insertScreenMouse(0xC021006A);
-
+
if (getGlobalVar(V_BALLOON_POPPED)) {
_asKey = insertSprite<AsCommonKey>(this, 0, 1100, 278, 347);
addCollisionSprite(_asKey);
@@ -774,7 +774,7 @@ Scene1305::Scene1305(NeverhoodEngine *vm, Module *parentModule, int which)
insertKlaymen<KmScene1305>(212, 441);
setMessageList(0x004B6E48);
}
-
+
}
uint32 Scene1305::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -800,7 +800,7 @@ void AsScene1306Elevator::update() {
if (_isUp && _countdown != 0 && (--_countdown == 0))
stGoingDown();
AnimatedSprite::update();
- if (_currFrameIndex == 7) {
+ if (_currFrameIndex == 7 && _asElevatorDoor->getVisible()) {
playSound(1);
_asElevatorDoor->setVisible(false);
}
@@ -868,10 +868,10 @@ void AsScene1306Elevator::cbGoingDownEvent() {
Scene1306::Scene1306(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0)
setGlobalVar(V_KEY3_LOCATION, 4);
-
+
SetMessageHandler(&Scene1306::handleMessage);
setBackground(0x05303114);
@@ -949,7 +949,7 @@ Scene1306::Scene1306(NeverhoodEngine *vm, Module *parentModule, int which)
}
}
-
+
Scene1306::~Scene1306() {
setGlobalVar(V_KLAYMEN_IS_DELTA_X, _klaymen->isDoDeltaX() ? 1 : 0);
}
@@ -1073,7 +1073,7 @@ static const NPoint kAsScene1307KeyPoints[] = {
const uint kAsScene1307KeyFrameIndicesCount = 20;
static const int16 kAsScene1307KeyFrameIndices[] = {
- 1, 4, 8, 11, 15, 16, 17, 17, 17, 16,
+ 1, 4, 8, 11, 15, 16, 17, 17, 17, 16,
15, 14, 12, 10, 9, 7, 5, 3, 2, 1
};
@@ -1084,10 +1084,10 @@ const int16 kAsScene1307KeyYDelta = -12;
AsScene1307Key::AsScene1307Key(NeverhoodEngine *vm, Scene *parentScene, uint keyIndex, NRect *clipRects)
: AnimatedSprite(vm, 1100), _parentScene(parentScene), _keyIndex(keyIndex), _clipRects(clipRects),
_isClickable(true) {
-
+
NPoint pt;
- const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
-
+ const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
+
_dataResource.load(0x22102142);
_pointList = _dataResource.getPointArray(0xAC849240);
pt = (*_pointList)[getSubVar(VA_CURR_KEY_SLOT_NUMBERS, _keyIndex)];
@@ -1173,7 +1173,7 @@ void AsScene1307Key::suMoveKey() {
}
void AsScene1307Key::stRemoveKey() {
- const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
+ const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
_pointIndex = 0;
startAnimation(fileHashes[0], 0, -1);
playSound(1);
@@ -1199,7 +1199,7 @@ void AsScene1307Key::stMoveKey() {
if (newX == _x && newY == _y) {
stInsertKey();
} else {
- const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
+ const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
_pointIndex = 0;
_frameIndex = 0;
_deltaX = newX - _x;
@@ -1210,13 +1210,13 @@ void AsScene1307Key::stMoveKey() {
}
void AsScene1307Key::stUnlock() {
- const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
+ const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
startAnimation(fileHashes[1], 0, -1);
_newStickFrameIndex = STICK_LAST_FRAME;
}
void AsScene1307Key::stInsert() {
- const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
+ const uint32 *fileHashes = kAsScene1307KeyResourceLists[_keyIndex];
startAnimation(fileHashes[2], 0, -1);
_newStickFrameIndex = STICK_LAST_FRAME;
}
@@ -1226,9 +1226,9 @@ Scene1307::Scene1307(NeverhoodEngine *vm, Module *parentModule)
_isInsertingKey(false), _doLeaveScene(false), _isPuzzleSolved(false) {
Sprite *tempSprite;
-
+
_vm->gameModule()->initKeySlotsPuzzle();
-
+
_dataResource.load(0x22102142);
_keyHolePoints = _dataResource.getPointArray(0xAC849240);
@@ -1279,7 +1279,7 @@ void Scene1307::update() {
if (_doLeaveScene && !isSoundPlaying(0)) {
leaveScene(1);
setGlobalVar(V_KEYDOOR_UNLOCKED, 1);
- }
+ }
}
uint32 Scene1307::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -1294,7 +1294,7 @@ uint32 Scene1307::handleMessage(int messageNum, const MessageParam &param, Entit
int16 mouseY = param.asPoint().y;
uint clickedKeyHoleIndex;
for (clickedKeyHoleIndex = 0; clickedKeyHoleIndex < 16; clickedKeyHoleIndex++) {
- if (mouseX >= _keyHoleRects[clickedKeyHoleIndex].x1 && mouseX <= _keyHoleRects[clickedKeyHoleIndex].x2 &&
+ if (mouseX >= _keyHoleRects[clickedKeyHoleIndex].x1 && mouseX <= _keyHoleRects[clickedKeyHoleIndex].x2 &&
mouseY >= _keyHoleRects[clickedKeyHoleIndex].y1 && mouseY <= _keyHoleRects[clickedKeyHoleIndex].y2)
break;
}
@@ -1362,7 +1362,7 @@ static const uint32 kScene1308NumberFileHashes[] = {
AsScene1308JaggyDoor::AsScene1308JaggyDoor(NeverhoodEngine *vm, Scene *parentScene)
: AnimatedSprite(vm, 0xBA0AE050, 1100, 320, 240), _parentScene(parentScene) {
-
+
setVisible(false);
stopAnimation();
SetMessageHandler(&AsScene1308JaggyDoor::handleMessage);
@@ -1412,12 +1412,12 @@ void AsScene1308JaggyDoor::stCloseDoorDone() {
AsScene1308KeyboardDoor::AsScene1308KeyboardDoor(NeverhoodEngine *vm, Scene *parentScene)
: AnimatedSprite(vm, 0xA08A0851, 1100, 320, 240), _parentScene(parentScene) {
-
+
playSound(0, 0x51456049);
SetMessageHandler(&AsScene1308KeyboardDoor::handleMessage);
NextState(&AsScene1308KeyboardDoor::stFallingKeys);
}
-
+
uint32 AsScene1308KeyboardDoor::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
switch (messageNum) {
@@ -1443,7 +1443,7 @@ void AsScene1308KeyboardDoor::stFallingKeysDone() {
AsScene1308LightWallSymbols::AsScene1308LightWallSymbols(NeverhoodEngine *vm, Scene *parentScene)
: AnimatedSprite(vm, 0x80180A10, 100, 320, 240), _parentScene(parentScene) {
-
+
setVisible(false);
stopAnimation();
Entity::_priority = 1200;
@@ -1486,7 +1486,7 @@ void AsScene1308LightWallSymbols::stFadeOutDone() {
SsScene1308Number::SsScene1308Number(NeverhoodEngine *vm, uint32 fileHash, int index)
: StaticSprite(vm, fileHash, 100) {
-
+
setVisible(false);
_x = _spriteResource.getPosition().x + index * 20;
updatePosition();
@@ -1520,11 +1520,11 @@ uint32 AsScene1308Mouse::handleMessage(int messageNum, const MessageParam &param
Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _isProjecting(false), _asProjector(NULL) {
-
+
_vm->gameModule()->initKeySlotsPuzzle();
SetMessageHandler(&Scene1308::handleMessage);
-
+
setBackground(0x41024202);
setPalette(0x41024202);
insertScreenMouse(0x24206418);
@@ -1536,7 +1536,7 @@ Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which)
insertSprite<AsScene1308Mouse>();
insertSprite<AnimatedSprite>(0x461A1490, 200, 235, 429);
}
-
+
_sprite1 = insertStaticSprite(0x0A042060, 1100);
_asJaggyDoor = insertSprite<AsScene1308JaggyDoor>(this);
_asLightWallSymbols = insertSprite<AsScene1308LightWallSymbols>(this);
@@ -1546,7 +1546,7 @@ Scene1308::Scene1308(NeverhoodEngine *vm, Module *parentModule, int which)
_sprite2 = insertStaticSprite(0x40043120, 995);
_sprite3 = insertStaticSprite(0x43003100, 995);
_sprite4 = NULL;
-
+
if (which < 0) {
// Restoring game
insertKlaymen<KmScene1308>(380, 440);
@@ -1698,7 +1698,7 @@ uint32 Scene1308::handleMessage(int messageNum, const MessageParam &param, Entit
Scene1317::Scene1317(NeverhoodEngine *vm, Module *parentModule)
: Scene(vm, parentModule) {
-
+
SetMessageHandler(&Scene1317::handleMessage);
_smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x08982841, true, false));
_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
@@ -1720,7 +1720,7 @@ void Scene1317::update() {
void Scene1317::upChooseKing() {
if (!_klaymenBlinks && _klaymenBlinkCountdown != 0 && (--_klaymenBlinkCountdown == 0))
_klaymenBlinks = true;
-
+
if (!_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 2) {
_smackerPlayer->rewind();
} else if (_klaymenBlinks && _smackerPlayer->getFrameNumber() + 1 >= 6) {
@@ -1731,7 +1731,7 @@ void Scene1317::upChooseKing() {
if (!_klaymenBlinks && _decisionCountdown != 0 && (--_decisionCountdown == 0))
stNoDecisionYet();
-
+
if (_smackerFileHash) {
_smackerPlayer->open(_smackerFileHash, _keepLastSmackerFrame);
_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
@@ -1739,7 +1739,7 @@ void Scene1317::upChooseKing() {
}
Scene::update();
-
+
}
uint32 Scene1317::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -1751,7 +1751,7 @@ uint32 Scene1317::handleMessage(int messageNum, const MessageParam &param, Entit
}
return messageResult;
}
-
+
uint32 Scene1317::hmChooseKing(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = Scene::handleMessage(messageNum, param, sender);
switch (messageNum) {
diff --git a/engines/neverhood/modules/module1400.cpp b/engines/neverhood/modules/module1400.cpp
index 56c6ca5f13..0a029632b6 100644
--- a/engines/neverhood/modules/module1400.cpp
+++ b/engines/neverhood/modules/module1400.cpp
@@ -31,7 +31,7 @@ namespace Neverhood {
Module1400::Module1400(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
_vm->_soundMan->addMusic(0x00AD0012, 0x06333232);
_vm->_soundMan->addMusic(0x00AD0012, 0x624A220E);
@@ -139,7 +139,7 @@ void Module1400::updateScene() {
AsScene1401Pipe::AsScene1401Pipe(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1100), _countdown1(0), _countdown2(0) {
-
+
createSurface(900, 152, 147);
_x = 454;
_y = 217;
@@ -179,10 +179,10 @@ uint32 AsScene1401Pipe::handleMessage(int messageNum, const MessageParam &param,
_countdown1 = 70;
_countdown2 = 8;
stStartSucking();
- break;
+ break;
case 0x483A:
stSuckInProjector();
- break;
+ break;
}
return messageResult;
}
@@ -221,7 +221,7 @@ void AsScene1401Pipe::stSuckInProjector() {
AsScene1401Mouse::AsScene1401Mouse(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1100) {
-
+
createSurface(100, 71, 41);
_x = 478;
_y = 433;
@@ -243,7 +243,7 @@ uint32 AsScene1401Mouse::handleMessage(int messageNum, const MessageParam &param
break;
case 0x4839:
stSuckedIn();
- break;
+ break;
}
return messageResult;
}
@@ -280,7 +280,7 @@ uint32 AsScene1401Cheese::handleMessage(int messageNum, const MessageParam &para
switch (messageNum) {
case 0x4839:
stSuckedIn();
- break;
+ break;
}
return messageResult;
}
@@ -332,7 +332,7 @@ uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam &pa
case 0x2001:
if (_isOpen)
_countdown = 168;
- messageResult = _isOpen ? 1 : 0;
+ messageResult = _isOpen ? 1 : 0;
break;
case 0x3002:
gotoNextState();
@@ -341,7 +341,7 @@ uint32 AsScene1401BackDoor::handleMessage(int messageNum, const MessageParam &pa
_countdown = 168;
if (!_isOpen)
stOpenDoor();
- break;
+ break;
}
return messageResult;
}
@@ -540,7 +540,7 @@ void AsCommonProjector::moveProjector() {
playSound(1, 0x5440E474);
_lockedInSlot = true;
}
-
+
}
void AsCommonProjector::stSuckedIn() {
@@ -627,8 +627,8 @@ void AsCommonProjector::stStartSuckedIn() {
}
Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which)
- : Scene(vm, parentModule), _projectorBorderFlag(false), _ssFloorButton(NULL), _asProjector(NULL),
- _asPipe(NULL), _asMouse(NULL), _asCheese(NULL), _asBackDoor(NULL),
+ : Scene(vm, parentModule), _projectorBorderFlag(false), _ssFloorButton(NULL), _asProjector(NULL),
+ _asPipe(NULL), _asMouse(NULL), _asCheese(NULL), _asBackDoor(NULL),
_sprite1(NULL), _sprite2(NULL), _sprite3(NULL), _ssButton(NULL) {
SetMessageHandler(&Scene1401::handleMessage);
@@ -638,7 +638,7 @@ Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which)
setBackground(0x08221FA5);
setPalette(0x08221FA5);
insertScreenMouse(0x21FA108A);
-
+
_ssFloorButton = insertSprite<SsCommonFloorButton>(this, 0x980F3124, 0x12192892, 100, 0);
_asPipe = insertSprite<AsScene1401Pipe>();
@@ -692,7 +692,7 @@ Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which)
}
_asProjector->setClipRect(_sprite3->getDrawRect().x, _sprite2->getDrawRect().y, 640, 480);
}
-
+
_klaymen->setClipRect(_sprite3->getDrawRect().x, 0, 640, 480);
if (which == 0 && _asProjector)
@@ -752,7 +752,7 @@ uint32 Scene1401::handleMessage(int messageNum, const MessageParam &param, Entit
setMessageList2(0x004B6658);
} else
setMessageList2(0x004B65F0);
- }
+ }
break;
case 0x482A:
_sprite1->setVisible(true);
@@ -772,7 +772,7 @@ uint32 Scene1401::handleMessage(int messageNum, const MessageParam &param, Entit
SsScene1402BridgePart::SsScene1402BridgePart(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority)
: StaticSprite(vm, fileHash, surfacePriority) {
-
+
SetFilterY(&Sprite::defFilterY);
SetUpdateHandler(&StaticSprite::updatePosition);
}
@@ -892,7 +892,7 @@ Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which)
startShaking();
}
}
-
+
if (_asPuzzleBox)
_asPuzzleBox->setClipRect(0, 0, 640, _ssBridgePart3->getDrawRect().y2());
@@ -914,7 +914,7 @@ Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which)
}
_klaymen->setClipRect(_ssBridgePart1->getDrawRect().x, 0, _ssBridgePart2->getDrawRect().x2(), _ssBridgePart3->getDrawRect().y2());
-
+
}
void Scene1402::upShaking() {
@@ -1082,7 +1082,7 @@ static const struct {
AsScene1407Mouse::AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene)
: AnimatedSprite(vm, 1100), _parentScene(parentScene), _currSectionIndex(0) {
-
+
createSurface(100, 117, 45);
_x = 108;
_y = 106;
@@ -1096,7 +1096,7 @@ void AsScene1407Mouse::suWalkTo() {
xdelta = _deltaX;
else if (xdelta < -_deltaX)
xdelta = -_deltaX;
- _deltaX = 0;
+ _deltaX = 0;
if (_walkDestX == _x)
sendMessage(this, 0x1019, 0);
else {
@@ -1231,7 +1231,7 @@ Scene1407::Scene1407(NeverhoodEngine *vm, Module *parentModule)
_asMouse = insertSprite<AsScene1407Mouse>(this);
_ssResetButton = insertStaticSprite(0x12006600, 100);
- _ssResetButton->setVisible(false);
+ _ssResetButton->setVisible(false);
}
@@ -1279,9 +1279,9 @@ uint32 Scene1407::handleMessage(int messageNum, const MessageParam &param, Entit
Scene1403::Scene1403(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _asProjector(NULL), _isProjecting(false) {
-
+
SetMessageHandler(&Scene1403::handleMessage);
-
+
setRectList(0x004B1FF8);
setBackground(0x2110A234);
setPalette(0x2110A234);
@@ -1383,10 +1383,10 @@ uint32 Scene1403::handleMessage(int messageNum, const MessageParam &param, Entit
Scene1404::Scene1404(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _asProjector(NULL), _asKey(NULL) {
-
+
if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0)
setGlobalVar(V_KEY3_LOCATION, 5);
-
+
SetMessageHandler(&Scene1404::handleMessage);
setRectList(0x004B8D80);
@@ -1555,14 +1555,14 @@ Scene1405::Scene1405(NeverhoodEngine *vm, Module *parentModule)
: Scene(vm, parentModule), _selectFirstTile(true), _tilesLeft(48), _countdown(0) {
_vm->gameModule()->initMemoryPuzzle();
-
+
SetUpdateHandler(&Scene1405::update);
SetMessageHandler(&Scene1405::handleMessage);
setBackground(0x0C0C007D);
setPalette(0x0C0C007D);
insertPuzzleMouse(0xC00790C8, 20, 620);
-
+
for (uint32 tileIndex = 0; tileIndex < 48; tileIndex++) {
_tiles[tileIndex] = insertSprite<AsScene1405Tile>(this, tileIndex);
addCollisionSprite(_tiles[tileIndex]);
diff --git a/engines/neverhood/modules/module1500.cpp b/engines/neverhood/modules/module1500.cpp
index 00d64a8c2d..3ce9783b69 100644
--- a/engines/neverhood/modules/module1500.cpp
+++ b/engines/neverhood/modules/module1500.cpp
@@ -26,7 +26,7 @@ namespace Neverhood {
Module1500::Module1500(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
if (which < 0)
createScene(_vm->gameState().sceneNum, -1);
else
@@ -86,7 +86,7 @@ Scene1501::Scene1501(NeverhoodEngine *vm, Module *parentModule, uint32 backgroun
SetUpdateHandler(&Scene1501::update);
SetMessageHandler(&Scene1501::handleMessage);
-
+
setBackground(backgroundFileHash);
setPalette();
addEntity(_palette);
@@ -118,7 +118,7 @@ void Scene1501::update() {
_countdown1 = 12;
_palette->startFadeToBlack(11);
}
-
+
}
uint32 Scene1501::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
diff --git a/engines/neverhood/modules/module1600.cpp b/engines/neverhood/modules/module1600.cpp
index 40faa1e82d..a5a785e130 100644
--- a/engines/neverhood/modules/module1600.cpp
+++ b/engines/neverhood/modules/module1600.cpp
@@ -34,7 +34,7 @@ static const uint32 kModule1600SoundList[] = {
Module1600::Module1600(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
if (which < 0)
createScene(_vm->gameState().sceneNum, -1);
else if (which == 1)
@@ -109,7 +109,7 @@ void Module1600::createScene(int sceneNum, int which) {
if (getGlobalVar(V_TALK_COUNTING_INDEX) >= 2)
setGlobalVar(V_TALK_COUNTING_INDEX, 0);
else
- incGlobalVar(V_TALK_COUNTING_INDEX, +1);
+ incGlobalVar(V_TALK_COUNTING_INDEX, +1);
break;
}
SetUpdateHandler(&Module1600::updateScene);
@@ -185,11 +185,11 @@ void Module1600::updateScene() {
AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
: AnimatedSprite(vm, 1000), _parentScene(parentScene) {
-
+
createSurface(200, 556, 328);
_x = x;
_y = y;
-
+
_inMainArea = false;
_exitDirection = 0;
_currPointIndex = 0;
@@ -207,7 +207,7 @@ AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16
_soundCounter = 0;
_pathPoints = NULL;
_currMoveDirection = 0;
-
+
startAnimation(0xD4220027, 0, -1);
setDoDeltaX(getGlobalVar(V_CAR_DELTA_X));
@@ -517,7 +517,7 @@ void AsCommonCar::moveToNextPoint() {
if (ABS(nextPt.y - currPt.y) <= ABS(nextPt.x - currPt.x) &&
((_currMoveDirection == 2 && nextPt.x < currPt.x) ||
(_currMoveDirection == 4 && nextPt.x >= currPt.x))) {
- if (_currMoveDirection == 2)
+ if (_currMoveDirection == 2)
_currMoveDirection = 4;
else if (_currMoveDirection == 4)
_currMoveDirection = 2;
@@ -605,7 +605,7 @@ void AsCommonCar::moveToPrevPoint() {
if (ABS(prevPt.y - currPt.y) <= ABS(prevPt.x - currPt.x) &&
((_currMoveDirection == 2 && prevPt.x < currPt.x) ||
(_currMoveDirection == 4 && prevPt.x >= currPt.x))) {
- if (_currMoveDirection == 2)
+ if (_currMoveDirection == 2)
_currMoveDirection = 4;
else if (_currMoveDirection == 4)
_currMoveDirection = 2;
@@ -668,7 +668,7 @@ void AsCommonCar::suMoveToNextPoint() {
bool firstTime = true;
_ySteps = _steps;
int stepsCtr = _steps;
-
+
while (stepsCtr > 0) {
NPoint pt1;
NPoint pt2 = pathPoint(_currPointIndex);
@@ -739,7 +739,7 @@ void AsCommonCar::suMoveToNextPoint() {
stepsCtr = 0;
}
}
- firstTime = false;
+ firstTime = false;
}
if (_yMoveTotalSteps != 0) {
@@ -811,7 +811,7 @@ void AsCommonCar::suMoveToPrevPoint() {
bool firstTime = true;
_ySteps = _steps;
int stepsCtr = _steps;
-
+
while (stepsCtr > 0) {
if (_stepError == 0)
_currPointIndex--;
@@ -884,7 +884,7 @@ void AsCommonCar::suMoveToPrevPoint() {
stepsCtr = 0;
}
}
- firstTime = false;
+ firstTime = false;
}
if (_yMoveTotalSteps != 0) {
@@ -971,7 +971,7 @@ AsCommonIdleCarFull::AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y)
AsCommonCarConnector::AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar)
: AnimatedSprite(vm, 1100), _asCar(asCar) {
-
+
createSurface1(0x60281C10, 150);
startAnimation(0x60281C10, -1, -1);
_newStickFrameIndex = STICK_LAST_FRAME;
@@ -1006,9 +1006,9 @@ Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _asCar(NULL), _countdown1(0) {
setGlobalVar(V_CAR_DELTA_X, 1);
-
+
SetMessageHandler(&Scene1608::hmLowerFloor);
-
+
_asKey = insertSprite<AsCommonKey>(this, 1, 1100, 198, 220);
addCollisionSprite(_asKey);
@@ -1092,9 +1092,9 @@ Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which)
_carClipFlag = false;
_carStatus = 0;
setRectList(0x004B4810);
- }
+ }
- // NOTE: Not in the else because 'which' is set to 1 in the true branch
+ // NOTE: Not in the else because 'which' is set to 1 in the true branch
if (which == 1) {
// Klaymen riding the car
_vm->gameState().which = 1;
@@ -1134,9 +1134,9 @@ Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which)
_carClipFlag = true;
_carStatus = 0;
}
-
+
_palette->addPalette("paKlayRed", 0, 64, 0);
-
+
}
Scene1608::~Scene1608() {
@@ -1308,7 +1308,7 @@ uint32 Scene1608::hmCarAtHome(int messageNum, const MessageParam &param, Entity
}
return 0;
}
-
+
void Scene1608::updateKlaymenCliprect() {
if (_kmScene1608->getX() <= 375)
_kmScene1608->setClipRect(_clipRect1);
@@ -1321,17 +1321,17 @@ Scene1609::Scene1609(NeverhoodEngine *vm, Module *parentModule)
_vm->gameModule()->initCodeSymbolsPuzzle();
_noisySymbolIndex = getGlobalVar(V_NOISY_SYMBOL_INDEX);
-
+
SetMessageHandler(&Scene1609::handleMessage);
SetUpdateHandler(&Scene1609::update);
-
+
setBackground(0x92124A14);
setPalette(0x92124A14);
insertPuzzleMouse(0x24A10929, 20, 620);
-
+
for (int symbolPosition = 0; symbolPosition < 12; symbolPosition++)
_asSymbols[symbolPosition] = insertSprite<AsScene3011Symbol>(symbolPosition, false);
-
+
_ssButton = insertSprite<SsScene3011Button>(this, true);
addCollisionSprite(_ssButton);
loadSound(0, 0x68E25540);
@@ -1408,5 +1408,5 @@ bool Scene1609::testVars() {
return true;
}
-
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1700.cpp b/engines/neverhood/modules/module1700.cpp
index 38ed561d51..2aeae466ff 100644
--- a/engines/neverhood/modules/module1700.cpp
+++ b/engines/neverhood/modules/module1700.cpp
@@ -36,7 +36,7 @@ static const uint32 kModule1700SoundList[] = {
Module1700::Module1700(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
_vm->_soundMan->addMusic(0x04212331, 0x31114225);
_vm->_soundMan->addSoundList(0x04212331, kModule1700SoundList);
_vm->_soundMan->setSoundListParams(kModule1700SoundList, true, 50, 600, 5, 150);
@@ -125,7 +125,7 @@ void Module1700::updateScene() {
}
}
}
-
+
// Scene1705
static const uint32 kScene1705FileHashes[] = {
@@ -137,7 +137,7 @@ static const uint32 kScene1705FileHashes[] = {
SsScene1705WallSymbol::SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex)
: StaticSprite(vm, fileHash, 100) {
-
+
_x = _spriteResource.getPosition().x + symbolIndex * 30;
_y = _spriteResource.getPosition().y + 160;
updatePosition();
@@ -171,7 +171,7 @@ uint32 SsScene1705Tape::handleMessage(int messageNum, const MessageParam &param,
setSubVar(VA_HAS_TAPE, _tapeIndex, 1);
setVisible(false);
SetMessageHandler(NULL);
- break;
+ break;
}
return messageResult;
}
@@ -180,7 +180,7 @@ Scene1705::Scene1705(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _paletteArea(1) {
Sprite *tempSprite;
-
+
setGlobalVar(V_FELL_DOWN_HOLE, 1);
_vm->gameModule()->initCannonSymbolsPuzzle();
@@ -271,7 +271,7 @@ uint32 Scene1705::handleMessage(int messageNum, const MessageParam &param, Entit
sendEntityMessage(_klaymen, 0x1014, sender);
setMessageList(0x004B6AC0);
}
- break;
+ break;
}
return 0;
}
diff --git a/engines/neverhood/modules/module1700.h b/engines/neverhood/modules/module1700.h
index f57c411a18..deb5573f2b 100644
--- a/engines/neverhood/modules/module1700.h
+++ b/engines/neverhood/modules/module1700.h
@@ -50,7 +50,7 @@ public:
class SsScene1705Tape : public StaticSprite {
public:
SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash);
-protected:
+protected:
Scene *_parentScene;
uint32 _tapeIndex;
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
diff --git a/engines/neverhood/modules/module1800.cpp b/engines/neverhood/modules/module1800.cpp
index b7371c9a4a..b312678467 100644
--- a/engines/neverhood/modules/module1800.cpp
+++ b/engines/neverhood/modules/module1800.cpp
@@ -38,7 +38,7 @@ static const uint32 kModule1800SoundList[] = {
Module1800::Module1800(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
_vm->_soundMan->addSoundList(0x04A14718, kModule1800SoundList);
_vm->_soundMan->setSoundListParams(kModule1800SoundList, true, 50, 600, 10, 150);
_vm->_soundMan->playTwoSounds(0x04A14718, 0x8A382B55, 0x0C242F1D, 0);
@@ -177,5 +177,5 @@ void Module1800::updateScene() {
}
}
}
-
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1900.cpp b/engines/neverhood/modules/module1900.cpp
index 7f08b01d3f..29c20083f9 100644
--- a/engines/neverhood/modules/module1900.cpp
+++ b/engines/neverhood/modules/module1900.cpp
@@ -35,8 +35,8 @@ static const uint32 kModule1900SoundList[] = {
Module1900::Module1900(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
- // NOTE: The original has a Scene1908 here as well but it's not used here but in another module...
-
+ // NOTE: The original has a Scene1908 here as well but it's not used here but in another module...
+
if (which < 0)
createScene(_vm->gameState().sceneNum, -1);
else
@@ -88,7 +88,7 @@ void Module1900::updateScene() {
Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
Sprite *tempSprite;
setRectList(0x004B34C8);
@@ -98,7 +98,7 @@ Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which)
insertScreenMouse(0x0322301B);
insertStaticSprite(0x42213133, 1100);
-
+
if (!getGlobalVar(V_STAIRS_PUZZLE_SOLVED))
insertStaticSprite(0x40A40168, 100);
else if (getGlobalVar(V_STAIRS_DOWN)) {
@@ -132,16 +132,16 @@ static const NPoint kAsScene1907SymbolGroundPositions[] = {
{400, 375}, {370, 435}, {475, 415}
};
-static const NPoint kAsScene1907SymbolPluggedInPositions[] = {
+static const NPoint kAsScene1907SymbolPluggedInPositions[] = {
{275, 125}, {244, 125}, {238, 131},
{221, 135}, {199, 136}, {168, 149},
{145, 152}, {123, 154}, {103, 157}
};
static const NPoint kAsScene1907SymbolGroundHitPositions[] = {
- {275, 299}, {244, 299}, {238, 305},
- {221, 309}, {199, 310}, {168, 323},
- {145, 326}, {123, 328}, {103, 331}
+ {275, 299}, {244, 299}, {238, 305},
+ {221, 309}, {199, 310}, {168, 323},
+ {145, 326}, {123, 328}, {103, 331}
};
static const NPoint kAsScene1907SymbolPluggedInDownPositions[] = {
@@ -164,7 +164,7 @@ AsScene1907Symbol::AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene
_plugInFailed = false;
_plugInTryCount = 0;
-
+
if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
_isPluggedIn = true;
_currPositionIndex = elementIndex;
@@ -289,7 +289,7 @@ void AsScene1907Symbol::suMoveDown() {
_y = kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y;
_isMoving = false;
SetSpriteUpdate(NULL);
- }
+ }
}
void AsScene1907Symbol::suMoveUp() {
@@ -423,7 +423,7 @@ void AsScene1907Symbol::moveDown() {
SsScene1907UpDownButton::SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol)
: StaticSprite(vm, 1400), _parentScene(parentScene), _asScene1907Symbol(asScene1907Symbol),
_countdown1(0) {
-
+
loadSprite(0x64516424, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1400);
setVisible(false);
loadSound(0, 0x44061000);
@@ -474,7 +474,7 @@ void SsScene1907UpDownButton::setToDownPosition() {
AsScene1907WaterHint::AsScene1907WaterHint(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1400) {
-
+
createSurface1(0x110A1061, 1500);
_x = 320;
_y = 240;
@@ -515,10 +515,10 @@ void AsScene1907WaterHint::hide() {
SetMessageHandler(&Sprite::handleMessage);
}
-Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule)
- : Scene(vm, parentModule), _currMovingSymbolIndex(0), _pluggedInCount(0),
+Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule)
+ : Scene(vm, parentModule), _currMovingSymbolIndex(0), _pluggedInCount(0),
_moveDownCountdown(0), _moveUpCountdown(0), _countdown3(0), _hasPlugInFailed(false) {
-
+
setBackground(0x20628E05);
setPalette(0x20628E05);
@@ -529,12 +529,12 @@ Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule)
_asSymbols[i] = insertSprite<AsScene1907Symbol>(this, i, getRandomPositionIndex());
addCollisionSprite(_asSymbols[i]);
}
-
+
_ssUpDownButton = insertSprite<SsScene1907UpDownButton>(this, _asSymbols[8]);
addCollisionSprite(_ssUpDownButton);
_asWaterHint = insertSprite<AsScene1907WaterHint>();
-
+
insertPuzzleMouse(0x28E0120E, 20, 620);
SetMessageHandler(&Scene1907::handleMessage);
@@ -542,7 +542,7 @@ Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule)
if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED))
_pluggedInCount = 9;
-
+
loadSound(0, 0x72004A10);
loadSound(1, 0x22082A12);
loadSound(2, 0x21100A10);
@@ -552,7 +552,7 @@ Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule)
void Scene1907::update() {
Scene::update();
-
+
if (_hasPlugInFailed) {
int fallOffDelay = 0;
_hasPlugInFailed = false;
@@ -619,7 +619,7 @@ uint32 Scene1907::handleMessage(int messageNum, const MessageParam &param, Entit
playSound(3);
setGlobalVar(V_STAIRS_PUZZLE_SOLVED, 1);
break;
- }
+ }
return 0;
}
diff --git a/engines/neverhood/modules/module2000.cpp b/engines/neverhood/modules/module2000.cpp
index 644b7c479a..fcccdefbdd 100644
--- a/engines/neverhood/modules/module2000.cpp
+++ b/engines/neverhood/modules/module2000.cpp
@@ -28,7 +28,7 @@ namespace Neverhood {
Module2000::Module2000(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
if (which < 0)
createScene(_vm->gameState().sceneNum, -1);
else if (which == 0)
@@ -137,9 +137,9 @@ Scene2001::Scene2001(NeverhoodEngine *vm, Module *parentModule, int which)
sendMessage(this, 0x2000, 0);
_klaymen->setDoDeltaX(1);
}
-
+
_klaymen->setClipRect(tempSprite->getDrawRect().x, 0, 640, 480);
-
+
}
uint32 Scene2001::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -153,7 +153,7 @@ uint32 Scene2001::handleMessage(int messageNum, const MessageParam &param, Entit
setRectList(0x004B3670);
_klaymen->setKlaymenIdleTable1();
}
- }
+ }
return 0;
}
diff --git a/engines/neverhood/modules/module2100.cpp b/engines/neverhood/modules/module2100.cpp
index b664e93dde..bcff9d9d1b 100644
--- a/engines/neverhood/modules/module2100.cpp
+++ b/engines/neverhood/modules/module2100.cpp
@@ -30,7 +30,7 @@ Module2100::Module2100(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
_vm->_soundMan->addMusic(0x10A10C14, 0x11482B95);
-
+
if (which < 0)
createScene(_vm->gameState().sceneNum, -1);
else if (which == 1)
@@ -129,7 +129,7 @@ void AsScene2101Door::stCloseDoorDone() {
AsScene2101HitByDoorEffect::AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen)
: AnimatedSprite(vm, 1400), _klaymen(klaymen) {
-
+
SetUpdateHandler(&AnimatedSprite::update);
SetMessageHandler(&AsScene2101HitByDoorEffect::handleMessage);
createSurface(1200, 88, 165);
@@ -176,8 +176,8 @@ void SsCommonFloorButton::update() {
else
setVisible(false);
}
-}
-
+}
+
uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
switch (messageNum) {
@@ -195,12 +195,12 @@ uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam &pa
Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
Sprite *tempSprite;
-
+
SetMessageHandler(&Scene2101::handleMessage);
SetUpdateHandler(&Scene2101::update);
-
+
setBackground(0x44242305);
setPalette(0x44242305);
insertScreenMouse(0x4230144A);
@@ -210,9 +210,9 @@ Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which)
_ssFloorButton = insertSprite<SsCommonFloorButton>(this, 0x72427010, 0x32423010, 200, 0);
_asTape1 = insertSprite<AsScene1201Tape>(this, 18, 1100, 412, 443, 0x9148A011);
addCollisionSprite(_asTape1);
- _asTape2 = insertSprite<AsScene1201Tape>(this, 11, 1100, 441, 443, 0x9148A011);
+ _asTape2 = insertSprite<AsScene1201Tape>(this, 11, 1100, 441, 443, 0x9048A093);
addCollisionSprite(_asTape2);
-
+
if (which < 0) {
insertKlaymen<KmScene2101>(380, 438);
setMessageList(0x004B8E48);
@@ -256,10 +256,10 @@ Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which)
_doorStatus = 1;
_countdown1 = 0;
}
-
+
_asHitByDoorEffect = insertSprite<AsScene2101HitByDoorEffect>(_klaymen);
_klaymen->setClipRect(0, 0, tempSprite->getDrawRect().x2(), 480);
-
+
}
void Scene2101::update() {
diff --git a/engines/neverhood/modules/module2100.h b/engines/neverhood/modules/module2100.h
index 369f5ac0cc..d76bed0780 100644
--- a/engines/neverhood/modules/module2100.h
+++ b/engines/neverhood/modules/module2100.h
@@ -68,7 +68,7 @@ protected:
uint32 _soundFileHash;
uint32 _fileHash1, _fileHash2;
int16 _countdown;
- void update();
+ void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
diff --git a/engines/neverhood/modules/module2200.cpp b/engines/neverhood/modules/module2200.cpp
index 04e3f0bfee..99f21cad74 100644
--- a/engines/neverhood/modules/module2200.cpp
+++ b/engines/neverhood/modules/module2200.cpp
@@ -30,8 +30,8 @@ namespace Neverhood {
Module2200::Module2200(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
- _vm->_soundMan->addMusic(0x11391412, 0x601C908C);
+
+ _vm->_soundMan->addMusic(0x11391412, 0x601C908C);
if (which < 0)
createScene(_vm->gameState().sceneNum, -1);
@@ -440,7 +440,7 @@ void Module2200::updateScene() {
}
#undef HallOfRecordsSceneLink
-
+
void Module2200::createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId) {
_childObject = new HallOfRecordsScene(_vm, this, which, hallOfRecordsInfoId);
}
@@ -461,7 +461,7 @@ AsScene2201Door::AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *
: AnimatedSprite(vm, 1100), _klaymen(klaymen), _ssDoorLight(ssDoorLight), _countdown(0), _isOpen(isOpen) {
_x = 408;
- _y = 290;
+ _y = 290;
createSurface(900, 63, 266);
SetUpdateHandler(&AsScene2201Door::update);
SetMessageHandler(&AsScene2201Door::handleMessage);
@@ -528,7 +528,7 @@ void AsScene2201Door::stCloseDoor() {
SsScene2201PuzzleCube::SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex)
: StaticSprite(vm, 900) {
-
+
createSurface(100, 16, 16);
loadSprite(kSsScene2201PuzzleCubeFileHashes[cubeIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 0,
kSsScene2201PuzzleCubePoints[positionIndex].x, kSsScene2201PuzzleCubePoints[positionIndex].y);
@@ -543,7 +543,7 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which)
SetMessageHandler(&Scene2201::handleMessage);
SetUpdateHandler(&Scene2201::update);
-
+
loadDataResource(0x04104242);
loadHitRectList();
setBackground(0x40008208);
@@ -551,9 +551,9 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which)
insertScreenMouse(0x0820C408);
_asTape = insertSprite<AsScene1201Tape>(this, 7, 1100, 459, 432, 0x9148A011);
- addCollisionSprite(_asTape);
+ addCollisionSprite(_asTape);
_ssDoorButton = insertSprite<SsCommonPressButton>(this, 0xE4A43E29, 0xE4A43E29, 100, 0);
-
+
for (uint32 cubeIndex = 0; cubeIndex < 9; cubeIndex++)
if ((int16)getSubVar(VA_CUBE_POSITIONS, cubeIndex) >= 0)
insertSprite<SsScene2201PuzzleCube>(cubeIndex, (int16)getSubVar(VA_CUBE_POSITIONS, cubeIndex));
@@ -562,10 +562,10 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which)
_clipRects[0].x2 = 640;
_clipRects[1].x2 = 640;
_clipRects[1].y2 = 480;
-
+
if (!getGlobalVar(V_TILE_PUZZLE_SOLVED))
insertStaticSprite(0x00026027, 900);
-
+
tempSprite = insertStaticSprite(0x030326A0, 1100);
_clipRects[0].x1 = tempSprite->getDrawRect().x;
insertStaticSprite(0x811DA061, 1100);
@@ -602,7 +602,7 @@ Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which)
setMessageList(0x004B8120);
_asDoor = insertSprite<AsScene2201Door>(_klaymen, _ssDoorLight, true);
}
-
+
insertSprite<AsScene2201CeilingFan>();
_vm->_soundMan->addSound(0x04106220, 0x81212040);
@@ -719,7 +719,7 @@ uint32 SsScene2202PuzzleCube::handleMessage(int messageNum, const MessageParam &
}
return messageResult;
}
-
+
void SsScene2202PuzzleCube::suMoveCubeX() {
bool done = false;
@@ -746,9 +746,9 @@ void SsScene2202PuzzleCube::suMoveCubeX() {
if (_x == _xFlagPos)
_counterDirection = true;
}
-
+
if (done)
- stopMoving();
+ stopMoving();
updateBounds();
@@ -780,9 +780,9 @@ void SsScene2202PuzzleCube::suMoveCubeY() {
if (_x == _xFlagPos)
_counterDirection = true;
}
-
+
if (done)
- stopMoving();
+ stopMoving();
updateBounds();
@@ -794,7 +794,7 @@ void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) {
setSubVar(VA_CUBE_POSITIONS, _cubePosition, (uint32)-1);
setSubVar(VA_CUBE_POSITIONS, newCubePosition, (uint32)_cubeSymbol);
-
+
_cubePosition = newCubePosition;
_errValue = 0;
_counterDirection = false;
@@ -837,7 +837,7 @@ void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) {
if (_newX - _x >= 180)
_xFlagPos = _newX - 90;
else
- _xFlagPos = _x + _newX / 2;
+ _xFlagPos = _x + _newX / 2;
} else {
if (_x - _newX >= 180)
_xFlagPos = _x + 90;
@@ -851,7 +851,7 @@ void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) {
if (_newY - _y >= 180)
_xFlagPos = _newY - 90;
else
- _xFlagPos = _y + _newY / 2;
+ _xFlagPos = _y + _newY / 2;
} else {
if (_y - _newY >= 180)
_xFlagPos = _y + 90;
@@ -860,7 +860,7 @@ void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) {
}
playSound(1);
}
-
+
}
void SsScene2202PuzzleCube::stopMoving() {
@@ -939,7 +939,7 @@ void Scene2202::update() {
_isSolved = true;
}
}
-
+
}
uint32 Scene2202::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -981,7 +981,7 @@ int16 Scene2202::getFreeCubePosition(int16 cubePosition) {
}
bool Scene2202::testIsSolved() {
- return
+ return
getSubVar(VA_CUBE_POSITIONS, 0) == 0 &&
getSubVar(VA_CUBE_POSITIONS, 2) == 2 &&
getSubVar(VA_CUBE_POSITIONS, 3) == 3 &&
@@ -1146,7 +1146,7 @@ Scene2203::Scene2203(NeverhoodEngine *vm, Module *parentModule, int which)
_ssSmallRightDoor->setVisible(false);
_klaymen->setClipRect(_leftDoorClipRect);
}
-
+
}
Scene2203::~Scene2203() {
@@ -1220,7 +1220,7 @@ Scene2205::Scene2205(NeverhoodEngine *vm, Module *parentModule, int which)
SetMessageHandler(&Scene2205::handleMessage);
SetUpdateHandler(&Scene2205::update);
-
+
setHitRects(0x004B0620);
if (getGlobalVar(V_LIGHTS_ON)) {
_isLightOn = true;
@@ -1263,11 +1263,11 @@ Scene2205::Scene2205(NeverhoodEngine *vm, Module *parentModule, int which)
_klaymen->setClipRect(_ssDoorFrame->getDrawRect().x, 0, 640, 480);
_klaymen->setSoundFlag(true);
-
+
loadDataResource(0x00144822);
-
+
}
-
+
void Scene2205::update() {
Scene::update();
if (!_isLightOn && getGlobalVar(V_LIGHTS_ON)) {
@@ -1343,7 +1343,7 @@ static const int16 kAsScene2206DoorSpikesXDeltasClose[] = {
AsScene2206DoorSpikes::AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash)
: StaticSprite(vm, fileHash, 200) {
-
+
if (getGlobalVar(V_SPIKES_RETRACTED))
_x -= 63;
SetUpdateHandler(&AsScene2206DoorSpikes::update);
@@ -1457,10 +1457,10 @@ Scene2206::Scene2206(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
uint32 fileHash;
-
+
SetUpdateHandler(&Scene::update);
SetMessageHandler(&Scene2206::handleMessage);
-
+
if (getGlobalVar(V_LIGHTS_ON)) {
fileHash = 0x41983216;
_sprite1 = insertStaticSprite(0x2201266A, 100);
@@ -1495,7 +1495,7 @@ Scene2206::Scene2206(NeverhoodEngine *vm, Module *parentModule, int which)
if (!getGlobalVar(V_LIGHTS_ON))
_palette->addPalette(0x0263D144, 0, 65, 0);
addCollisionSprite(_ssTestTube);
-
+
if (which < 0) {
// Restoring game
insertKlaymen<KmScene2206>(200, 430);
@@ -1644,7 +1644,7 @@ void AsScene2207Elevator::update() {
if (_destPointIndex + _destPointIndexDelta > _pointIndex) {
_pointIndex++;
startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
- _newStickFrameIndex = _pointIndex;
+ _newStickFrameIndex = _pointIndex;
if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
if (_destPointIndexDelta != 0)
_destPointIndexDelta = 0;
@@ -1660,7 +1660,7 @@ void AsScene2207Elevator::update() {
if (_pointIndex == 0)
sendMessage(_parentScene, 0x2003, 0);
startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
- _newStickFrameIndex = _pointIndex;
+ _newStickFrameIndex = _pointIndex;
if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
if (_destPointIndexDelta != 0)
_destPointIndexDelta = 0;
@@ -1675,14 +1675,14 @@ void AsScene2207Elevator::update() {
sendMessage(_parentScene, 0x2002, 900);
else if (_pointIndex < 20 && _surface->getPriority() != 1100)
sendMessage(_parentScene, 0x2002, 1100);
-
+
AnimatedSprite::update();
-
+
if (_destPointIndex + _destPointIndexDelta == _pointIndex && _isMoving) {
sendMessage(_parentScene, 0x2004, 0);
_isMoving = false;
}
-
+
}
void AsScene2207Elevator::suSetPosition() {
@@ -1706,14 +1706,14 @@ void AsScene2207Elevator::moveToY(int16 y) {
if (!_pointArray || _pointArray->size() == 0)
return;
-
+
for (uint i = 0; i < _pointArray->size(); i++) {
int16 distance = ABS(y - (*_pointArray)[i].y);
if (distance < minDistance) {
minDistance = distance;
_destPointIndex = i;
}
- }
+ }
if (_destPointIndex != _pointIndex) {
if (_destPointIndex == 0 || _destPointIndex == (int)_pointArray->size() - 1)
@@ -1732,7 +1732,7 @@ void AsScene2207Elevator::moveToY(int16 y) {
AsScene2207Lever::AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX)
: AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
+
_x = x;
_y = y;
createSurface(1010, 71, 73);
@@ -1793,7 +1793,7 @@ void AsScene2207Lever::stLeverUpEvent() {
AsScene2207WallRobotAnimation::AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene)
: AnimatedSprite(vm, 1200), _idle(true) {
-
+
_x = 309;
_y = 320;
createSurface1(0xCCFD6090, 100);
@@ -1874,7 +1874,7 @@ void AsScene2207WallRobotAnimation::cbStopAnimation() {
AsScene2207WallCannonAnimation::AsScene2207WallCannonAnimation(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1200), _idle(true) {
-
+
_x = 309;
_y = 320;
createSurface1(0x8CAA0099, 100);
@@ -1925,7 +1925,7 @@ SsScene2207Symbol::SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int i
_x = 330;
_y = 246 + index * 50;
- updatePosition();
+ updatePosition();
}
Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule)
@@ -1943,7 +1943,7 @@ Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule)
_klaymen->setRepl(64, 0);
setMessageList(0x004B38E8);
_asElevator = insertSprite<AsScene2207Elevator>(this);
-
+
if (getGlobalVar(V_LIGHTS_ON)) {
setBackground(0x88C00241);
setPalette(0x88C00241);
@@ -1952,7 +1952,7 @@ Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule)
_ssMaskPart2 = insertStaticSprite(0x688F62A5, 1100);
_ssMaskPart3 = insertStaticSprite(0x0043B038, 1100);
_asTape = insertSprite<AsScene1201Tape>(this, 4, 1100, 277, 428, 0x9148A011);
- addCollisionSprite(_asTape);
+ addCollisionSprite(_asTape);
_asLever = insertSprite<AsScene2207Lever>(this, 527, 333, 0);
addCollisionSprite(_asLever);
_asWallRobotAnimation = insertSprite<AsScene2207WallRobotAnimation>(this);
@@ -2106,7 +2106,7 @@ static const uint32 kScene2208FileHashes1[] = {
0x041023CB, 0x041020CB, 0x041026CB, 0x04102ACB,
0x041032CB, 0x041002CB
};
-
+
static const uint32 kScene2208FileHashes2[] = {
0x091206C9, 0x091406C9, 0x091806C9, 0x090006C9,
0x093006C9, 0x095006C9
@@ -2122,13 +2122,13 @@ Scene2208::Scene2208(NeverhoodEngine *vm, Module *parentModule, int which)
setGlobalVar(V_COLUMN_TEXT_NAME, calcHash("stLineagex"));
_textResource.load(getGlobalVar(V_COLUMN_TEXT_NAME));
-
+
textStart = _textResource.getString(getGlobalVar(V_CLICKED_COLUMN_INDEX), textEnd);
while (textStart < textEnd) {
_strings.push_back(textStart);
textStart += strlen(textStart) + 1;
}
-
+
_maxRowIndex = 8 + 10 * (3 - (getGlobalVar(V_COLUMN_TEXT_NAME) == calcHash("stLineagex") ? 1 : 0));
_background = new Background(_vm, 0);
@@ -2154,7 +2154,7 @@ Scene2208::Scene2208(NeverhoodEngine *vm, Module *parentModule, int which)
_bottomBackgroundSurface = new BaseSurface(_vm, 0, 640, 192, "bottom background");
spriteResource.load(kScene2208FileHashes2[getGlobalVar(V_CLICKED_COLUMN_INDEX) % 6], true);
_bottomBackgroundSurface->drawSpriteResourceEx(spriteResource, false, false, 0, 0);
-
+
SetUpdateHandler(&Scene2208::update);
SetMessageHandler(&Scene2208::handleMessage);
@@ -2165,7 +2165,7 @@ Scene2208::Scene2208(NeverhoodEngine *vm, Module *parentModule, int which)
if (_newRowIndex < 6)
_newRowIndex = 0;
_rowScrollY = 0;
- _backgroundScrollY = 48 * _newRowIndex;
+ _backgroundScrollY = 48 * _newRowIndex;
_currRowIndex = _newRowIndex;
for (int16 rowIndex = 0; rowIndex < _visibleRowsCount; rowIndex++)
@@ -2185,7 +2185,7 @@ Scene2208::~Scene2208() {
void Scene2208::update() {
int16 mouseY = _vm->getMouseY();
-
+
if (mouseY < 48) {
if (_currRowIndex > 0)
_newRowIndex = _currRowIndex - 1;
@@ -2235,7 +2235,7 @@ uint32 Scene2208::handleMessage(int messageNum, const MessageParam &param, Entit
}
void Scene2208::drawRow(int16 rowIndex) {
- NDrawRect sourceRect;
+ NDrawRect sourceRect;
int16 y = (rowIndex * 48) % 528;
if (rowIndex < 4) {
sourceRect.x = 0;
@@ -2280,7 +2280,7 @@ Scene2242::Scene2242(NeverhoodEngine *vm, Module *parentModule, int which)
SetMessageHandler(&Scene2242::handleMessage);
SetUpdateHandler(&Scene2242::update);
-
+
if (getGlobalVar(V_LIGHTS_ON)) {
setBackground(0x11840E24);
setPalette(0x11840E24);
@@ -2297,7 +2297,7 @@ Scene2242::Scene2242(NeverhoodEngine *vm, Module *parentModule, int which)
}
_asTape = insertSprite<AsScene1201Tape>(this, 10, 1100, 464, 435, 0x9148A011);
- addCollisionSprite(_asTape);
+ addCollisionSprite(_asTape);
if (which < 0) {
// Restoring game
@@ -2380,7 +2380,7 @@ void Scene2242::readClickedColumn() {
}
static const int16 kHallOfRecordsKlaymenXPos[] = {
- 68, 157, 246, 335,
+ 68, 157, 246, 335,
424, 513, 602
};
@@ -2396,7 +2396,7 @@ static const uint32 kHallOfRecordsSceneMessageListIds1[] = {
HallOfRecordsScene::HallOfRecordsScene(NeverhoodEngine *vm, Module *parentModule, int which, uint32 hallOfRecordsInfoId)
: Scene(vm, parentModule) {
-
+
_hallOfRecordsInfo = _vm->_staticData->getHallOfRecordsInfoItem(hallOfRecordsInfoId);
SetMessageHandler(&HallOfRecordsScene::handleMessage);
@@ -2487,7 +2487,7 @@ static const uint32 kScene2247MessageListIds1[] = {
Scene2247::Scene2247(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
SetMessageHandler(&Scene2247::handleMessage);
SetUpdateHandler(&Scene::update);
@@ -2524,7 +2524,7 @@ Scene2247::Scene2247(NeverhoodEngine *vm, Module *parentModule, int which)
}
_klaymen->setSoundFlag(true);
-
+
}
Scene2247::~Scene2247() {
diff --git a/engines/neverhood/modules/module2200.h b/engines/neverhood/modules/module2200.h
index af7171dd53..5c19f2a818 100644
--- a/engines/neverhood/modules/module2200.h
+++ b/engines/neverhood/modules/module2200.h
@@ -100,7 +100,7 @@ class SsScene2202PuzzleCube : public StaticSprite {
public:
SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol);
protected:
- Scene *_parentScene;
+ Scene *_parentScene;
int16 _cubeSymbol;
int16 _cubePosition;
int16 _newX, _newY;
@@ -135,7 +135,7 @@ protected:
void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
int16 getFreeCubePosition(int16 index);
- bool testIsSolved();
+ bool testIsSolved();
};
class AsCommonKey : public AnimatedSprite {
diff --git a/engines/neverhood/modules/module2300.cpp b/engines/neverhood/modules/module2300.cpp
index b434fb98c0..2a46df1ee2 100644
--- a/engines/neverhood/modules/module2300.cpp
+++ b/engines/neverhood/modules/module2300.cpp
@@ -32,12 +32,12 @@ static const uint32 kModule2300SoundList[] = {
Module2300::Module2300(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule), _soundVolume(0) {
-
+
_vm->_soundMan->addSoundList(0x1A214010, kModule2300SoundList);
_vm->_soundMan->setSoundListParams(kModule2300SoundList, true, 50, 600, 10, 150);
_isWallBroken = getGlobalVar(V_WALL_BROKEN) != 0;
-
+
if (_isWallBroken) {
_vm->_soundMan->setSoundVolume(0x90F0D1C3, 0);
_vm->_soundMan->playSoundLooping(0x90F0D1C3);
@@ -161,12 +161,12 @@ void Module2300::updateScene() {
} else {
switch (_sceneNum) {
case 1:
- if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 &&
+ if (_isWallBroken && navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 4 &&
navigationScene()->getFrameNumber() % 2) {
_soundVolume++;
_vm->_soundMan->setSoundVolume(0x90F0D1C3, _soundVolume);
}
- if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0 &&
+ if (navigationScene()->isWalkingForward() && navigationScene()->getNavigationIndex() == 0 &&
navigationScene()->getFrameNumber() == 50) {
_vm->_soundMan->playTwoSounds(0x1A214010, 0x48498E46, 0x50399F64, 0);
_vm->_soundMan->setSoundVolume(0x48498E46, 70);
@@ -182,5 +182,5 @@ void Module2300::updateScene() {
}
}
}
-
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2400.cpp b/engines/neverhood/modules/module2400.cpp
index 8d3b763f72..3a152543cf 100644
--- a/engines/neverhood/modules/module2400.cpp
+++ b/engines/neverhood/modules/module2400.cpp
@@ -26,7 +26,7 @@ namespace Neverhood {
Module2400::Module2400(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
_vm->_soundMan->addMusic(0x202D1010, 0xB110382D);
if (which < 0)
@@ -187,7 +187,7 @@ static const uint32 kAsScene2401WaterSpitFileHashes1[] = {
AsScene2401WaterSpit::AsScene2401WaterSpit(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1200) {
-
+
_x = 240;
_y = 447;
createSurface(100, 146, 74);
@@ -222,7 +222,7 @@ uint32 AsScene2401WaterSpit::handleMessage(int messageNum, const MessageParam &p
AsScene2401FlowingWater::AsScene2401FlowingWater(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1200), _isWaterFlowing(false) {
-
+
_x = 88;
_y = 421;
createSurface1(0x10203116, 100);
@@ -262,10 +262,10 @@ uint32 AsScene2401FlowingWater::handleMessage(int messageNum, const MessageParam
}
return messageResult;
}
-
+
AsScene2401WaterFlushing::AsScene2401WaterFlushing(NeverhoodEngine *vm, int16 x, int16 y)
: AnimatedSprite(vm, 1200), _countdown(0), _flushLoopCount(0) {
-
+
_x = x;
_y = y;
createSurface1(0xB8596884, 100);
@@ -308,7 +308,7 @@ uint32 AsScene2401WaterFlushing::handleMessage(int messageNum, const MessagePara
AsScene2401Door::AsScene2401Door(NeverhoodEngine *vm, bool isOpen)
: AnimatedSprite(vm, 1100), _countdown(0), _isOpen(isOpen) {
-
+
_x = 320;
_y = 240;
createSurface1(0x44687810, 100);
@@ -398,7 +398,7 @@ Scene2401::Scene2401(NeverhoodEngine *vm, Module *parentModule, int which)
_ssWaterPipes[i] = insertStaticSprite(kScene2401FileHashes1[i], 300);
_ssWaterPipes[i]->setVisible(false);
}
-
+
_asWaterSpit[0] = insertSprite<AsScene2401WaterSpit>();
_asWaterSpit[1] = insertSprite<AsScene2401WaterSpit>();
@@ -461,7 +461,7 @@ void Scene2401::update() {
if (_countdown2 != 0 && (--_countdown2) == 0)
sendMessage(_asFlowingWater, 0x2003, 0);
-
+
Scene::update();
}
@@ -559,7 +559,7 @@ AsScene2402Door::AsScene2402Door(NeverhoodEngine *vm, Scene *parentScene, bool i
} else {
stopAnimation();
setVisible(false);
- }
+ }
SetUpdateHandler(&AsScene2402Door::update);
SetMessageHandler(&AsScene2402Door::handleMessage);
}
@@ -654,7 +654,7 @@ void AsScene2402TV::upFocusKlaymen() {
_newStickFrameIndex = _currFrameIndex;
if (_countdown2 == 0) {
_vm->_soundMan->addSound(0x01520123, 0xC42D4528);
- _vm->_soundMan->playSoundLooping(0xC42D4528);
+ _vm->_soundMan->playSoundLooping(0xC42D4528);
}
_countdown2 = 5;
} else if (_countdown2 != 0 && (--_countdown2 == 0))
@@ -698,7 +698,7 @@ Scene2402::Scene2402(NeverhoodEngine *vm, Module *parentModule, int which)
_asTape = insertSprite<AsScene1201Tape>(this, 9, 1100, 286, 409, 0x9148A011);
addCollisionSprite(_asTape);
_ssButton = insertSprite<SsCommonButtonSprite>(this, 0x15288120, 100, 0);
-
+
if (which < 0) {
// Restoring game
insertKlaymen<KmScene2402>(198, 404);
@@ -779,7 +779,7 @@ uint32 Scene2402::handleMessage(int messageNum, const MessageParam &param, Entit
}
return messageResult;
}
-
+
void Scene2402::playPipeSound(uint32 fileHash) {
playSound(_soundToggle ? 0 : 1, fileHash);
_soundToggle = !_soundToggle;
@@ -787,7 +787,7 @@ void Scene2402::playPipeSound(uint32 fileHash) {
Scene2403::Scene2403(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
Sprite *tempSprite1, *tempSprite2, *tempSprite3;
SetMessageHandler(&Scene2403::handleMessage);
@@ -799,7 +799,7 @@ Scene2403::Scene2403(NeverhoodEngine *vm, Module *parentModule, int which)
addCollisionSprite(_asTape);
_asLightCord = insertSprite<AsScene2803LightCord>(this, 0xA1095A10, 0x836D3813, 368, 200);
_asLightCord->setClipRect(0, 25, 640, 480);
-
+
if (which < 0) {
// Restoring game
_isClimbingLadder = false;
@@ -828,11 +828,11 @@ Scene2403::Scene2403(NeverhoodEngine *vm, Module *parentModule, int which)
}
_ssButton = insertSprite<SsCommonButtonSprite>(this, 0x3130B0EB, 100, 0);
- tempSprite1 = insertStaticSprite(0x20C24220, 1100);
+ tempSprite1 = insertStaticSprite(0x20C24220, 1100);
tempSprite2 = insertStaticSprite(0x03080900, 1300);
tempSprite3 = insertSprite<AsScene1002KlaymenLadderHands>(_klaymen);
tempSprite3->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2());
- _klaymen->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2());
+ _klaymen->setClipRect(tempSprite1->getDrawRect().x, 0, 640, tempSprite2->getDrawRect().y2());
loadSound(1, calcHash("fxFogHornSoft"));
}
@@ -887,7 +887,7 @@ Scene2406::Scene2406(NeverhoodEngine *vm, Module *parentModule, int which)
setGlobalVar(V_KEY3_LOCATION, 2);
SetMessageHandler(&Scene2406::handleMessage);
-
+
setRectList(0x004B78C8);
insertScreenMouse(0xB03001A8);
@@ -913,7 +913,7 @@ Scene2406::Scene2406(NeverhoodEngine *vm, Module *parentModule, int which)
setPalette(0x0A038595);
tempSprite1 = insertStaticSprite(0x1712112A, 1100);
}
-
+
tempSprite2 = insertStaticSprite(0x22300924, 1300);
_clipRects[1].x1 = tempSprite1->getDrawRect().x;
_clipRects[1].y1 = tempSprite2->getDrawRect().y;
diff --git a/engines/neverhood/modules/module2500.cpp b/engines/neverhood/modules/module2500.cpp
index e3a3b74280..1b525f12af 100644
--- a/engines/neverhood/modules/module2500.cpp
+++ b/engines/neverhood/modules/module2500.cpp
@@ -51,7 +51,7 @@ static const NRect kScene2508ClipRect2 = NRect(0, 0, 594, 448);
Module2500::Module2500(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule), _soundIndex(0) {
-
+
_vm->_soundMan->addMusic(0x29220120, 0x05343184);
_vm->_soundMan->startMusic(0x05343184, 0, 0);
SetMessageHandler(&Module2500::handleMessage);
@@ -212,14 +212,14 @@ uint32 Module2500::handleMessage(int messageNum, const MessageParam &param, Enti
}
return messageResult;
}
-
+
void Module2500::createScene2704(int which, uint32 sceneInfoId, int16 value, const uint32 *staticSprites, const NRect *clipRect) {
_childObject = new Scene2704(_vm, this, which, sceneInfoId, value, staticSprites, clipRect);
}
Scene2501::Scene2501(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
_tracks.push_back(_vm->_staticData->getTrackInfo(0x004B2628));
_tracks.push_back(_vm->_staticData->getTrackInfo(0x004B264C));
_tracks.push_back(_vm->_staticData->getTrackInfo(0x004B2670));
@@ -282,7 +282,7 @@ Scene2501::Scene2501(NeverhoodEngine *vm, Module *parentModule, int which)
_asCarTrackShadow = insertSprite<AsCommonCarTrackShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4);
_asCarConnectorShadow = insertSprite<AsCommonCarConnectorShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4);
insertSprite<AsCommonCarConnector>(_asCar);
-
+
_newTrackIndex = -1;
_dataResource.load(calcHash("Ashooded"));
@@ -300,9 +300,9 @@ Scene2501::Scene2501(NeverhoodEngine *vm, Module *parentModule, int which)
if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480)
sendMessage(_asCar, 0x2008, 150);
}
-
+
_carStatus = 0;
-
+
}
Scene2501::~Scene2501() {
@@ -391,7 +391,7 @@ uint32 Scene2501::handleMessage(int messageNum, const MessageParam &param, Entit
}
return messageResult;
}
-
+
uint32 Scene2501::hmRidingCar(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = Scene::handleMessage(messageNum, param, sender);
switch (messageNum) {
@@ -434,7 +434,7 @@ uint32 Scene2501::hmCarAtHome(int messageNum, const MessageParam &param, Entity
}
return messageResult;
}
-
+
void Scene2501::moveCarToPoint(NPoint &pt) {
int minMatchTrackIndex, minMatchDistance;
_tracks.findTrackPoint(pt, minMatchTrackIndex, minMatchDistance, _dataResource);
@@ -472,7 +472,7 @@ void Scene2501::updateKlaymenClipRect() {
SsScene2504Button::SsScene2504Button(NeverhoodEngine *vm)
: StaticSprite(vm, 1400), _countdown(0), _isSoundPlaying(false) {
-
+
loadSprite(0x070220D9, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
setVisible(false);
loadSound(0, 0x4600204C);
@@ -520,9 +520,9 @@ uint32 SsScene2504Button::handleMessage(int messageNum, const MessageParam &para
Scene2504::Scene2504(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
Sprite *ssButton;
-
+
setBackground(0x90791B80);
setPalette(0x90791B80);
ssButton = insertSprite<SsScene2504Button>();
diff --git a/engines/neverhood/modules/module2600.cpp b/engines/neverhood/modules/module2600.cpp
index 56b4c65f8d..2fce82b777 100644
--- a/engines/neverhood/modules/module2600.cpp
+++ b/engines/neverhood/modules/module2600.cpp
@@ -35,7 +35,7 @@ static const uint32 kModule2600SoundList[] = {
Module2600::Module2600(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
-
+
if (which < 0)
createScene(_vm->gameState().sceneNum, -1);
else if (which == 1)
@@ -218,10 +218,10 @@ void Module2600::updateScene() {
}
}
}
-
+
SsScene2609Button::SsScene2609Button(NeverhoodEngine *vm, Scene *parentScene)
: StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) {
-
+
SetUpdateHandler(&SsScene2609Button::update);
SetMessageHandler(&SsScene2609Button::handleMessage);
@@ -273,7 +273,7 @@ uint32 SsScene2609Button::handleMessage(int messageNum, const MessageParam &para
AsScene2609Water::AsScene2609Water(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1000) {
-
+
_x = 240;
_y = 420;
setDoDeltaX(1);
@@ -309,7 +309,7 @@ uint32 AsScene2609Water::handleMessage(int messageNum, const MessageParam &param
Scene2609::Scene2609(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _isBusy(false) {
-
+
SetUpdateHandler(&Scene::update);
SetMessageHandler(&Scene2609::handleMessage);
diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp
index 19655d128b..f8f3c71042 100644
--- a/engines/neverhood/modules/module2700.cpp
+++ b/engines/neverhood/modules/module2700.cpp
@@ -83,8 +83,8 @@ static const uint32 kScene2725StaticSprites[] = {
};
Module2700::Module2700(NeverhoodEngine *vm, Module *parentModule, int which)
- : Module(vm, parentModule), _soundIndex(0), _raidoMusicInitialized(false) {
-
+ : Module(vm, parentModule), _soundIndex(0), _radioMusicInitialized(false) {
+
_vm->_soundMan->addMusic(0x42212411, 0x04020210);
_vm->_soundMan->startMusic(0x04020210, 24, 2);
SetMessageHandler(&Module2700::handleMessage);
@@ -500,7 +500,7 @@ void Module2700::updateScene() {
} else {
switch (_sceneNum) {
case 21:
- if (!_raidoMusicInitialized) {
+ if (!_radioMusicInitialized) {
_vm->_soundMan->stopMusic(0x04020210, 0, 1);
_vm->gameModule()->initRadioPuzzle();
_musicFileHash = getGlobalVar(V_GOOD_RADIO_MUSIC_NAME);
@@ -508,7 +508,7 @@ void Module2700::updateScene() {
_vm->_soundMan->startMusic(_musicFileHash, 0, 2);
_vm->_soundMan->addSound(0x42212411, 0x44014282);
_vm->_soundMan->setSoundParams(0x44014282, true, 120, 360, 72, 0);
- _raidoMusicInitialized = true;
+ _radioMusicInitialized = true;
}
break;
}
@@ -527,7 +527,7 @@ uint32 Module2700::handleMessage(int messageNum, const MessageParam &param, Enti
}
return messageResult;
}
-
+
void Module2700::createScene2703(int which, uint32 trackInfoId) {
_childObject = new Scene2703(_vm, this, which, trackInfoId);
}
@@ -545,7 +545,7 @@ static const NPoint kCarShadowOffsets[] = {
SsCommonTrackShadowBackground::SsCommonTrackShadowBackground(NeverhoodEngine *vm, uint32 fileHash)
: StaticSprite(vm, 0) {
-
+
loadSprite(fileHash, kSLFDefDrawOffset | kSLFDefPosition, 0);
}
@@ -555,7 +555,7 @@ AsCommonCarShadow::AsCommonCarShadow(NeverhoodEngine *vm, AnimatedSprite *asCar,
SetUpdateHandler(&AsCommonCarShadow::update);
createShadowSurface(shadowSurface, 211, 147, 100);
updateShadow();
-}
+}
void AsCommonCarShadow::update() {
updateShadow();
@@ -589,8 +589,8 @@ AsCommonCarConnectorShadow::AsCommonCarConnectorShadow(NeverhoodEngine *vm, Spri
SetUpdateHandler(&AsCommonCarConnectorShadow::update);
createShadowSurface1(shadowSurface, 0x60281C10, 150);
startAnimation(0x60281C10, -1, -1);
- _newStickFrameIndex = STICK_LAST_FRAME;
-}
+ _newStickFrameIndex = STICK_LAST_FRAME;
+}
void AsCommonCarConnectorShadow::update() {
_x = _asCar->getX() + kCarShadowOffsets[_index].x;
@@ -605,7 +605,7 @@ AsCommonCarTrackShadow::AsCommonCarTrackShadow(NeverhoodEngine *vm, Sprite *asCa
createShadowSurface1(shadowSurface, 0x0759129C, 100);
startAnimation(0x0759129C, frameIndex, -1);
_newStickFrameIndex = frameIndex;
-}
+}
void AsCommonCarTrackShadow::update() {
_x = _asCar->getX();
@@ -615,19 +615,19 @@ void AsCommonCarTrackShadow::update() {
Scene2701::Scene2701(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
Sprite *tempSprite;
-
+
NRect clipRect;
TrackInfo *tracks = _vm->_staticData->getTrackInfo(0x004B2240);
setGlobalVar(V_CAR_DELTA_X, 1);
-
+
setBackground(tracks->bgFilename);
setPalette(tracks->bgFilename);
_palette->addPalette(calcHash("paPodFloor"), 65, 31, 65);
_palette->addPalette(calcHash("paKlayFloor"), 0, 65, 0);
insertScreenMouse(0x08B08180);
-
+
tempSprite = insertStaticSprite(0x1E086325, 1200);
clipRect.set(0, 0, 640, tempSprite->getDrawRect().y2());
@@ -661,7 +661,7 @@ Scene2701::Scene2701(NeverhoodEngine *vm, Module *parentModule, int which)
if (testPoint.x < 0 || testPoint.x >= 640 || testPoint.y < 0 || testPoint.y >= 480)
sendMessage(_asCar, 0x2008, 150);
}
-
+
_asCar->setClipRect(clipRect);
_asCarConnector->setClipRect(clipRect);
@@ -715,10 +715,10 @@ uint32 Scene2701::hmCarAtHome(int messageNum, const MessageParam &param, Entity
Scene2702::Scene2702(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _isInLight(true), _newTrackIndex(-1) {
-
+
SetMessageHandler(&Scene2702::handleMessage);
SetUpdateHandler(&Scene2702::update);
-
+
setBackground(0x18808B00);
setPalette(0x18808B00);
_palette->addPalette(calcHash("paPodFloor"), 65, 31, 65);
@@ -734,7 +734,7 @@ Scene2702::Scene2702(NeverhoodEngine *vm, Module *parentModule, int which)
_asCarTrackShadow = insertSprite<AsCommonCarTrackShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4);
_asCarConnectorShadow = insertSprite<AsCommonCarConnectorShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4);
_dataResource.load(0x04310014);
-
+
if (which == 1) {
_isUpperTrack = false;
_currTrackIndex = 1;
@@ -765,11 +765,11 @@ Scene2702::Scene2702(NeverhoodEngine *vm, Module *parentModule, int which)
}
if (_isUpperTrack) {
- _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F68));
+ _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F68));
_tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5F8C));
_tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FB0));
} else {
- _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FD8));
+ _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FD8));
_tracks.push_back(_vm->_staticData->getTrackInfo(0x004B5FFC));
_tracks.push_back(_vm->_staticData->getTrackInfo(0x004B6020));
}
@@ -873,19 +873,19 @@ Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint3
: Scene(vm, parentModule) {
TrackInfo *tracks = _vm->_staticData->getTrackInfo(trackInfoId);
-
+
SetMessageHandler(&Scene2703::handleMessage);
SetUpdateHandler(&Scene2703::update);
-
+
setBackground(tracks->bgFilename);
setPalette(tracks->bgFilename);
_palette->addPalette(calcHash("paPodShade"), 65, 31, 65);
_palette->addPalette(calcHash("paKlayShade"), 0, 65, 0);
addEntity(_palette);
insertScreenMouse(tracks->mouseCursorFilename);
-
+
_palStatus = 2;
-
+
if (tracks->bgShadowFilename) {
_ssTrackShadowBackground = createSprite<SsCommonTrackShadowBackground>(tracks->bgShadowFilename);
addEntity(_ssTrackShadowBackground);
@@ -905,7 +905,7 @@ Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint3
_dataResource.load(tracks->dataResourceFilename);
_trackPoints = _dataResource.getPointArray(tracks->trackPointsName);
_asCar->setPathPoints(_trackPoints);
-
+
if (which == _which2) {
NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1];
sendMessage(_asCar, 0x2002, _trackPoints->size() - 1);
@@ -921,7 +921,7 @@ Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint3
else
sendMessage(_asCar, 0x2008, 150);
}
-
+
if (which == 0) {
_palette->addPalette(calcHash("paPodShade"), 65, 31, 65);
_palette->addPalette(calcHash("paKlayShade"), 0, 65, 0);
@@ -931,9 +931,9 @@ Scene2703::Scene2703(NeverhoodEngine *vm, Module *parentModule, int which, uint3
_palette->addPalette(calcHash("paKlayBlack"), 0, 65, 0);
_palStatus = 0;
}
-
+
_palette->copyBasePalette(0, 256, 0);
-
+
}
void Scene2703::update() {
@@ -981,16 +981,16 @@ uint32 Scene2703::handleMessage(int messageNum, const MessageParam &param, Entit
}
return 0;
}
-
+
Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint32 trackInfoId, int16 value,
const uint32 *staticSprites, const NRect *clipRect)
: Scene(vm, parentModule) {
TrackInfo *tracks = _vm->_staticData->getTrackInfo(trackInfoId);
-
+
SetMessageHandler(&Scene2704::handleMessage);
SetUpdateHandler(&Scene2704::update);
-
+
setBackground(tracks->bgFilename);
setPalette(tracks->bgFilename);
@@ -999,12 +999,12 @@ Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint3
if (tracks->exPaletteFilename2)
_palette->addPalette(tracks->exPaletteFilename2, 65, 31, 65);
-
+
while (staticSprites && *staticSprites)
insertStaticSprite(*staticSprites++, 1100);
insertScreenMouse(tracks->mouseCursorFilename);
-
+
if (tracks->bgShadowFilename) {
_ssTrackShadowBackground = createSprite<SsCommonTrackShadowBackground>(tracks->bgShadowFilename);
addEntity(_ssTrackShadowBackground);
@@ -1024,7 +1024,7 @@ Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint3
_dataResource.load(tracks->dataResourceFilename);
_trackPoints = _dataResource.getPointArray(tracks->trackPointsName);
_asCar->setPathPoints(_trackPoints);
-
+
if (which == _which2) {
NPoint testPoint = (*_trackPoints)[_trackPoints->size() - 1];
sendMessage(_asCar, 0x2002, _trackPoints->size() - 1);
@@ -1040,21 +1040,21 @@ Scene2704::Scene2704(NeverhoodEngine *vm, Module *parentModule, int which, uint3
else
sendMessage(_asCar, 0x2008, 0);
}
-
+
if (clipRect) {
_asCar->getClipRect() = *clipRect;
if (_asCarShadow)
- _asCarShadow->getClipRect() = *clipRect;
+ _asCarShadow->getClipRect() = *clipRect;
if (_asCarTrackShadow)
- _asCarTrackShadow->getClipRect() = *clipRect;
+ _asCarTrackShadow->getClipRect() = *clipRect;
if (_asCarConnectorShadow)
- _asCarConnectorShadow->getClipRect() = *clipRect;
+ _asCarConnectorShadow->getClipRect() = *clipRect;
if (_asCarConnector)
_asCarConnector->getClipRect() = *clipRect;
}
}
-
+
void Scene2704::update() {
Scene::update();
if (_mouseClicked) {
@@ -1083,24 +1083,24 @@ uint32 Scene2704::handleMessage(int messageNum, const MessageParam &param, Entit
Scene2706::Scene2706(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _newTrackIndex(-1) {
-
+
SetMessageHandler(&Scene2706::handleMessage);
- _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22A0));
+ _tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22A0));
_tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22C4));
_tracks.push_back(_vm->_staticData->getTrackInfo(0x004B22E8));
-
+
setBackground(0x18808B88);
setPalette(0x18808B88);
-
+
_palette->addPalette(calcHash("paPodShade"), 65, 31, 65);
_palette->addPalette(calcHash("paKlayShade"), 0, 65, 0);
-
+
insertScreenMouse(0x08B8C180);
_ssTrackShadowBackground = createSprite<SsCommonTrackShadowBackground>(0x18808B88);
addEntity(_ssTrackShadowBackground);
-
+
_asCar = insertSprite<AsCommonCar>(this, 320, 240);
_asCarShadow = insertSprite<AsCommonCarShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4);
_asCarConnector = insertSprite<AsCommonCarConnector>(_asCar);
@@ -1108,10 +1108,10 @@ Scene2706::Scene2706(NeverhoodEngine *vm, Module *parentModule, int which)
_asCarConnectorShadow = insertSprite<AsCommonCarConnectorShadow>(_asCar, _ssTrackShadowBackground->getSurface(), 4);
_dataResource.load(0x06000162);
-
+
if (which == 5)
_currTrackIndex = 2;
- else if (which == 6)
+ else if (which == 6)
_currTrackIndex = 1;
else
_currTrackIndex = 0;
@@ -1123,16 +1123,16 @@ Scene2706::Scene2706(NeverhoodEngine *vm, Module *parentModule, int which)
sendMessage(_asCar, 0x2002, _trackPoints->size() - 1);
if (which == 5)
sendMessage(_asCar, 0x2007, 50);
- else
+ else
sendMessage(_asCar, 0x2007, 150);
} else {
sendMessage(_asCar, 0x2002, 0);
if (which == 5)
sendMessage(_asCar, 0x2008, 50);
- else
+ else
sendMessage(_asCar, 0x2008, 150);
}
-
+
}
uint32 Scene2706::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -1192,7 +1192,7 @@ void Scene2706::changeTrack() {
Scene2732::Scene2732(NeverhoodEngine *vm, Module *parentModule)
: Scene(vm, parentModule) {
-
+
Sprite *tempSprite;
setBackground(0x0220C041);
diff --git a/engines/neverhood/modules/module2700.h b/engines/neverhood/modules/module2700.h
index 003666bb7f..158bb609e9 100644
--- a/engines/neverhood/modules/module2700.h
+++ b/engines/neverhood/modules/module2700.h
@@ -39,7 +39,7 @@ public:
protected:
int _sceneNum;
int _soundIndex;
- bool _raidoMusicInitialized;
+ bool _radioMusicInitialized;
uint32 _scene2711StaticSprites[6];
uint32 _musicFileHash;
void createScene(int sceneNum, int which);
diff --git a/engines/neverhood/modules/module2800.cpp b/engines/neverhood/modules/module2800.cpp
index 3d76d05762..1c0f9fc9fb 100644
--- a/engines/neverhood/modules/module2800.cpp
+++ b/engines/neverhood/modules/module2800.cpp
@@ -36,7 +36,7 @@ Module2800::Module2800(NeverhoodEngine *vm, Module *parentModule, int which)
_currentMusicFileHash = 0;
_vm->_soundMan->addMusic(0x64210814, 0xD2FA4D14);
setGlobalVar(V_RADIO_MOVE_DISH_VIDEO, 1);
-
+
if (which < 0) {
createScene(_vm->gameState().sceneNum, which);
} else if (which == 2) {
@@ -224,7 +224,7 @@ void Module2800::updateScene() {
_musicResource = NULL;
}
_currentMusicFileHash = 0;
- }
+ }
if (_moduleResult == 1) {
createScene(2, 0);
} else if (_moduleResult == 2) {
@@ -251,7 +251,7 @@ void Module2800::updateScene() {
createScene(9, 0);
else if (_moduleResult == 5)
createScene(25, 0);
- else
+ else
createScene(0, 1);
break;
case 3:
@@ -318,7 +318,7 @@ void Module2800::updateScene() {
createScene(22, 0);
else if (_moduleResult == 22)
createScene(23, 0);
- else
+ else
createScene(2, 4);
break;
case 10:
@@ -331,7 +331,7 @@ void Module2800::updateScene() {
createScene(26, 0);
else if (_moduleResult == 3)
createScene(9, 5);
- else
+ else
createScene(9, 1);
break;
case 12:
@@ -401,7 +401,7 @@ void Module2800::updateMusic(bool halfVolume) {
if (!_musicResource)
_musicResource = new MusicResource(_vm);
-
+
if (newMusicFileHash != _currentMusicFileHash) {
_currentMusicFileHash = newMusicFileHash;
if (_currentMusicFileHash != 0) {
@@ -469,7 +469,7 @@ Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which)
_klaymen->setClipRect(_sprite1->getDrawRect().x, 0, _sprite2->getDrawRect().x2(), 480);
insertScreenMouse(0x0066201C);
_asTape = insertSprite<AsScene1201Tape>(this, 8, 1100, 302, 437, 0x9148A011);
- addCollisionSprite(_asTape);
+ addCollisionSprite(_asTape);
} else if (getGlobalVar(V_RADIO_ROOM_RIGHT_DOOR)) {
setRectList(0x004B6CD0);
setBackground(0x11E00684);
@@ -480,7 +480,7 @@ Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which)
_klaymen->setClipRect(0, 0, _sprite2->getDrawRect().x2(), 480);
insertScreenMouse(0x00680116);
_asTape = insertSprite<SsScene1705Tape>(this, 8, 1100, 302, 437, 0x01142428);
- addCollisionSprite(_asTape);
+ addCollisionSprite(_asTape);
} else {
setRectList(0x004B6CF0);
setBackground(0x030006E6);
@@ -491,9 +491,9 @@ Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which)
_klaymen->setClipRect(0, 0, _sprite2->getDrawRect().x2(), 480);
insertScreenMouse(0x006E2038);
_asTape = insertSprite<AsScene1201Tape>(this, 8, 1100, 302, 437, 0x9148A011);
- addCollisionSprite(_asTape);
+ addCollisionSprite(_asTape);
}
-
+
addEntity(_palette);
if (which == 1) {
@@ -503,7 +503,7 @@ Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which)
_palette->addPalette(_paletteHash, 0, 65, 0);
_palette->addBasePalette(_paletteHash, 0, 65, 0);
}
-
+
}
Scene2801::~Scene2801() {
@@ -565,7 +565,7 @@ Scene2802::~Scene2802() {
}
setGlobalVar(V_CURR_RADIO_MUSIC_INDEX, _currRadioMusicIndex);
}
-
+
void Scene2802::update() {
int prevTuneStatus = _currTuneStatus;
uint prevRadioMusicIndex = _currRadioMusicIndex;
@@ -577,7 +577,7 @@ void Scene2802::update() {
_currTuneStatus = 3;
else if (_currTuneStatus == 4)
_currTuneStatus = 6;
-
+
switch (_currTuneStatus) {
case 2:
if (_currRadioMusicIndex < 90)
@@ -607,20 +607,20 @@ void Scene2802::update() {
} else
_currTuneStatus = 0;
break;
-
+
}
if (prevRadioMusicIndex != _currRadioMusicIndex)
_smackerPlayer->gotoFrame(_currRadioMusicIndex);
-
+
if (prevTuneStatus != _currTuneStatus)
changeTuneStatus(prevTuneStatus, _currTuneStatus);
-
+
if (getGlobalVar(V_RADIO_MOVE_DISH_VIDEO) && prevTuneStatus != _currTuneStatus && _currRadioMusicIndex != 0) {
setGlobalVar(V_RADIO_MOVE_DISH_VIDEO, 0);
leaveScene(1);
}
-
+
}
uint32 Scene2802::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -758,7 +758,7 @@ void AsScene2803LightCord::setFileHashes(uint32 fileHash1, uint32 fileHash2) {
AsScene2803TestTubeOne::AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2)
: AnimatedSprite(vm, 1200), _fileHash1(fileHash1), _fileHash2(fileHash2) {
-
+
createSurface1(fileHash1, 100);
SetUpdateHandler(&AnimatedSprite::update);
SetMessageHandler(&AsScene2803TestTubeOne::handleMessage);
@@ -781,7 +781,7 @@ uint32 AsScene2803TestTubeOne::handleMessage(int messageNum, const MessageParam
AsScene2803Rope::AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x)
: AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
+
createSurface(990, 68, 476);
SetUpdateHandler(&AnimatedSprite::update);
SetSpriteUpdate(&AnimatedSprite::updateDeltaXY);
@@ -837,7 +837,7 @@ void AsScene2803Rope::stHide() {
Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _paletteArea(0) {
-
+
static const uint32 kScene2803FileHashes1[] = {
0,
0x081000F1,
@@ -854,20 +854,20 @@ Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which)
setGlobalVar(V_BEEN_SHRINKING_ROOM, 1);
_vm->gameModule()->initTestTubes1Puzzle();
-
+
SetMessageHandler(&Scene2803::handleMessage);
-
+
loadDataResource(0x00900849);
-
+
_background = new Background(_vm, 0);
_background->createSurface(0, 640, 480);
addBackground(_background);
-
+
setPalette(0x412A423E);
addEntity(_palette);
-
+
insertScreenMouse(0xA423A41A);
-
+
if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 0) {
_asTestTubeOne = (StaticSprite*)insertStaticSprite(0x66121222, 100);
} else {
@@ -875,13 +875,13 @@ Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which)
kScene2803FileHashes1[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)],
kScene2803FileHashes2[getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0)]);
}
-
+
if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 1) == 3)
_asTestTubeTwo = (StaticSprite*)insertStaticSprite(0x64330236, 100);
if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3)
_asTestTubeThree = (StaticSprite*)insertStaticSprite(0x2E4A22A2, 100);
-
+
_asLightCord = insertSprite<AsScene2803LightCord>(this, 0x8FAD5932, 0x276E1A3D, 578, 200);
_sprite3 = (StaticSprite*)insertStaticSprite(0xA40EF2FB, 1100);
_sprite4 = (StaticSprite*)insertStaticSprite(0x0C03AA23, 1100);
@@ -896,7 +896,7 @@ Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which)
_clipRectsFloor[0].y1 = 0;
_clipRectsFloor[0].x2 = 640;
_clipRectsFloor[0].y2 = _sprite8->getDrawRect().y2();
-
+
_clipRectsFloor[1].x1 = _sprite8->getDrawRect().x2();
_clipRectsFloor[1].y1 = _sprite8->getDrawRect().y2();
_clipRectsFloor[1].x2 = 640;
@@ -906,12 +906,12 @@ Scene2803::Scene2803(NeverhoodEngine *vm, Module *parentModule, int which)
_clipRectsStairs[0].y1 = 0;
_clipRectsStairs[0].x2 = _sprite5->getDrawRect().x2();
_clipRectsStairs[0].y2 = _sprite5->getDrawRect().y2();
-
+
_clipRectsStairs[1].x1 = _sprite6->getDrawRect().x;
_clipRectsStairs[1].y1 = 0;
_clipRectsStairs[1].x2 = _sprite3->getDrawRect().x;
_clipRectsStairs[1].y2 = _sprite6->getDrawRect().y2();
-
+
_clipRectsStairs[2].x1 = _sprite3->getDrawRect().x;
_clipRectsStairs[2].y1 = 0;
_clipRectsStairs[2].x2 = _sprite4->getDrawRect().x2();
@@ -1112,7 +1112,7 @@ Scene2803Small::Scene2803Small(NeverhoodEngine *vm, Module *parentModule, int wh
static const uint32 kScene2803SmallFileHashes2[] = {
0, 0x286800D4, 0x286806D4, 0x28680AD4
};
-
+
SetMessageHandler(&Scene2803Small::handleMessage);
loadDataResource(0x81120132);
@@ -1160,7 +1160,7 @@ Scene2803Small::Scene2803Small(NeverhoodEngine *vm, Module *parentModule, int wh
if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 2) == 3)
insertStaticSprite(0x30022689, 100);
}
-
+
_sprite6->setVisible(false);
_sprite7->setVisible(false);
@@ -1352,7 +1352,7 @@ void Scene2803Small::updatePaletteArea(bool instantly) {
SsScene2804RedButton::SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene)
: StaticSprite(vm, 900), _countdown(0), _parentScene(parentScene) {
-
+
loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? 0x51A10202 : 0x11814A21, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
setVisible(false);
SetUpdateHandler(&SsScene2804RedButton::update);
@@ -1385,7 +1385,7 @@ uint32 SsScene2804RedButton::handleMessage(int messageNum, const MessageParam &p
SsScene2804LightCoil::SsScene2804LightCoil(NeverhoodEngine *vm)
: StaticSprite(vm, 900) {
-
+
loadSprite(0x8889B008, kSLFDefDrawOffset | kSLFDefPosition, 400);
setVisible(false);
SetMessageHandler(&SsScene2804LightCoil::handleMessage);
@@ -1410,7 +1410,7 @@ uint32 SsScene2804LightCoil::handleMessage(int messageNum, const MessageParam &p
SsScene2804LightTarget::SsScene2804LightTarget(NeverhoodEngine *vm)
: StaticSprite(vm, 900) {
-
+
loadSprite(0x06092132, kSLFDefDrawOffset | kSLFDefPosition, 400);
setVisible(false);
SetMessageHandler(&SsScene2804LightTarget::handleMessage);
@@ -1435,7 +1435,7 @@ uint32 SsScene2804LightTarget::handleMessage(int messageNum, const MessageParam
SsScene2804Flash::SsScene2804Flash(NeverhoodEngine *vm)
: StaticSprite(vm, 900) {
-
+
loadSprite(0x211003A0, kSLFDefDrawOffset | kSLFDefPosition, 400);
setVisible(false);
loadSound(0, 0xCB36BA54);
@@ -1449,7 +1449,7 @@ void SsScene2804Flash::show() {
SsScene2804BeamCoilBody::SsScene2804BeamCoilBody(NeverhoodEngine *vm)
: StaticSprite(vm, 900) {
-
+
loadSprite(0x9A816000, kSLFDefDrawOffset | kSLFDefPosition, 400);
setVisible(false);
}
@@ -1585,7 +1585,7 @@ SsScene2804CrystalButton::SsScene2804CrystalButton(NeverhoodEngine *vm, Scene280
0xA8042525,
0x5008292B
};
-
+
loadSprite(getGlobalVar(V_SHRINK_LIGHTS_ON) ? kSsScene2804CrystalButtonFileHashes1[crystalIndex] : kSsScene2804CrystalButtonFileHashes2[crystalIndex],
kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
setVisible(false);
@@ -1619,7 +1619,7 @@ uint32 SsScene2804CrystalButton::handleMessage(int messageNum, const MessagePara
AsScene2804BeamCoil::AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody)
: AnimatedSprite(vm, 1400), _parentScene(parentScene), _ssBeamCoilBody(ssBeamCoilBody), _countdown(0) {
-
+
createSurface1(0x00494891, 1000);
_x = 125;
_y = 184;
@@ -1659,7 +1659,7 @@ uint32 AsScene2804BeamCoil::handleMessage(int messageNum, const MessageParam &pa
}
return messageResult;
}
-
+
void AsScene2804BeamCoil::show() {
_ssBeamCoilBody->setVisible(true);
setVisible(true);
@@ -1695,7 +1695,7 @@ uint32 AsScene2804BeamCoil::hmBeaming(int messageNum, const MessageParam &param,
AsScene2804BeamTarget::AsScene2804BeamTarget(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1400) {
-
+
createSurface1(0x03842000, 1000);
_x = 475;
_y = 278;
@@ -1750,7 +1750,7 @@ Scene2804::Scene2804(NeverhoodEngine *vm, Module *parentModule, int which)
_asTarget = insertSprite<AsScene2804BeamTarget>();
_ssFlash = insertSprite<SsScene2804Flash>();
}
-
+
_ssRedButton = insertSprite<SsScene2804RedButton>(this);
addCollisionSprite(_ssRedButton);
@@ -1797,7 +1797,7 @@ uint32 Scene2804::handleMessage(int messageNum, const MessageParam &param, Entit
void Scene2804::update() {
Scene::update();
-
+
if (_countdown1 != 0 && (--_countdown1) == 0) {
leaveScene(0);
}
@@ -1836,7 +1836,7 @@ void Scene2804::update() {
Scene2805::Scene2805(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
SetMessageHandler(&Scene2805::handleMessage);
setBackground(0x08021E04);
@@ -1894,7 +1894,7 @@ uint32 Scene2805::handleMessage(int messageNum, const MessageParam &param, Entit
AsScene2806Spew::AsScene2806Spew(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1200) {
-
+
createSurface1(0x04211490, 1200);
_x = 378;
_y = 423;
@@ -1919,7 +1919,7 @@ uint32 AsScene2806Spew::handleMessage(int messageNum, const MessageParam &param,
}
return messageResult;
}
-
+
Scene2806::Scene2806(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
@@ -1927,16 +1927,16 @@ Scene2806::Scene2806(NeverhoodEngine *vm, Module *parentModule, int which)
SetMessageHandler(&Scene2806::handleMessage);
SetUpdateHandler(&Scene2806::update);
-
+
loadDataResource(0x98182003);
loadHitRectList();
-
+
_pointList = _dataResource.getPointArray(0x3606A422);
- insertScreenMouse(0x22114C13);
+ insertScreenMouse(0x22114C13);
setBackground(0xC1B22110);
setPalette(0xC1B22110);
-
+
_sprite1 = insertStaticSprite(0xA21F82CB, 1100);
_clipRects[0].x1 = _sprite1->getDrawRect().x;
_clipRects[0].y1 = _sprite1->getDrawRect().y;
@@ -1951,7 +1951,7 @@ Scene2806::Scene2806(NeverhoodEngine *vm, Module *parentModule, int which)
_sprite4 = insertStaticSprite(0x72090342, 1100);
_clipRects[1].x1 = _sprite4->getDrawRect().x;
_clipRects[1].y1 = _sprite4->getDrawRect().y;
-
+
tempSprite = insertStaticSprite(0xD2012C02, 1100);
_clipRects[2].x1 = tempSprite->getDrawRect().x;
_clipRects[2].y2 = tempSprite->getDrawRect().y2();
@@ -2027,7 +2027,7 @@ void Scene2806::findClosestPoint() {
int16 x = MIN<int16>(_klaymen->getX(), 639);
int index = 1;
-
+
while (index < (int)_pointList->size() && (*_pointList)[index].x < x)
++index;
--index;
@@ -2036,12 +2036,12 @@ void Scene2806::findClosestPoint() {
_pointIndex = index;
_palette->addPalette(kScene2806PaletteFileHashes[index], 0, 64, 0);
}
-
+
}
Scene2807::Scene2807(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
-
+
SetMessageHandler(&Scene2807::handleMessage);
if (getSubVar(VA_GOOD_TEST_TUBES_LEVEL_1, 0) == 1) {
@@ -2136,7 +2136,7 @@ static const int16 kClass490FrameIndices2[] = {
SsScene2808Dispenser::SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex)
: StaticSprite(vm, 900), _parentScene(parentScene), _countdown(0), _testTubeSetNum(testTubeSetNum),
_testTubeIndex(testTubeIndex) {
-
+
loadSprite(kClass428FileHashes[testTubeSetNum * 3 + testTubeIndex], kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1500);
setVisible(false);
SetUpdateHandler(&SsScene2808Dispenser::update);
@@ -2149,7 +2149,7 @@ void SsScene2808Dispenser::update() {
setVisible(false);
}
}
-
+
uint32 SsScene2808Dispenser::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
switch (messageNum) {
@@ -2197,16 +2197,16 @@ AsScene2808TestTube::AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum
loadSound(7, 0x70A43D2D);
loadSound(8, 0xF0601E2D);
}
-
+
startAnimation(kClass490FileHashes[testTubeIndex], 0, -1);
_newStickFrameIndex = 0;
-
+
SetUpdateHandler(&AnimatedSprite::update);
SetMessageHandler(&AsScene2808TestTube::handleMessage);
-
+
if (_fillLevel == 0)
setVisible(false);
-
+
}
uint32 AsScene2808TestTube::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -2253,7 +2253,7 @@ void AsScene2808TestTube::flush() {
AsScene2808Handle::AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum)
: AnimatedSprite(vm, 1300), _parentScene(parentScene), _testTubeSetNum(testTubeSetNum), _isActivated(false) {
-
+
loadSound(0, 0xE18D1F30);
_x = 320;
_y = 240;
@@ -2325,7 +2325,7 @@ AsScene2808Flow::AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int te
SetUpdateHandler(&AnimatedSprite::update);
AnimatedSprite::updatePosition();
}
-
+
uint32 AsScene2808Flow::hmFlowing(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
switch (messageNum) {
@@ -2351,7 +2351,7 @@ void AsScene2808Flow::stKeepFlowing() {
AsScene2808LightEffect::AsScene2808LightEffect(NeverhoodEngine *vm, int testTubeSetNum)
: AnimatedSprite(vm, 800), _countdown(1) {
-
+
_x = 320;
_y = 240;
if (testTubeSetNum == 1)
@@ -2381,7 +2381,7 @@ Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which)
_vm->gameModule()->initTestTubes1Puzzle();
else
_vm->gameModule()->initTestTubes2Puzzle();
-
+
SetMessageHandler(&Scene2808::handleMessage);
SetUpdateHandler(&Scene2808::update);
@@ -2400,7 +2400,7 @@ Scene2808::Scene2808(NeverhoodEngine *vm, Module *parentModule, int which)
_asTestTubes[testTubeIndex] = insertSprite<AsScene2808TestTube>(which, testTubeIndex, ssDispenser);
addCollisionSprite(_asTestTubes[testTubeIndex]);
}
-
+
insertScreenMouse(kScene2808FileHashes2[which]);
}
@@ -2498,13 +2498,13 @@ Scene2809::Scene2809(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule) {
Sprite *tempSprite;
-
+
SetMessageHandler(&Scene2809::handleMessage);
SetUpdateHandler(&Scene2809::update);
-
+
loadDataResource(0x1830009A);
loadHitRectList();
-
+
_pointList = _dataResource.getPointArray(0x064A310E);
setBackground(0xB22116C5);
@@ -2535,7 +2535,7 @@ Scene2809::Scene2809(NeverhoodEngine *vm, Module *parentModule, int which)
tempSprite = insertStaticSprite(0x877F6252, 1100);
_clipRects[3].x2 = tempSprite->getDrawRect().x2();
-
+
insertStaticSprite(0x01612A22, 1100);
insertStaticSprite(0x877F6252, 1100);
@@ -2610,7 +2610,7 @@ void Scene2809::findClosestPoint() {
_pointIndex = index;
_palette->addPalette(kScene2809PaletteFileHashes[index], 0, 64, 0);
}
-
+
}
AsScene2810Rope::AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x)
@@ -2647,7 +2647,7 @@ Scene2810::Scene2810(NeverhoodEngine *vm, Module *parentModule, int which)
Sprite *tempSprite;
SetMessageHandler(&Scene2810::handleMessage);
-
+
setBackground(0x26508804);
setPalette(0x26508804);
insertScreenMouse(0x0880026D);
@@ -2683,7 +2683,7 @@ Scene2810::Scene2810(NeverhoodEngine *vm, Module *parentModule, int which)
}
_sprite4->setClipRect(0, _sprite1->getDrawRect().y, 640, 480);
}
-
+
if (which < 0) {
if (getGlobalVar(V_KLAYMEN_SMALL)) {
insertKlaymen<KmScene2810Small>(240, 448);
@@ -2864,7 +2864,7 @@ uint32 Scene2810::handleMessage(int messageNum, const MessageParam &param, Entit
AsScene2812Winch::AsScene2812Winch(NeverhoodEngine *vm)
: AnimatedSprite(vm, 1100) {
-
+
createSurface1(0x20DA08A0, 1200);
SetUpdateHandler(&AnimatedSprite::update);
SetMessageHandler(&AsScene2812Winch::handleMessage);
@@ -2895,7 +2895,7 @@ uint32 AsScene2812Winch::handleMessage(int messageNum, const MessageParam &param
AsScene2812Rope::AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene)
: AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
+
createSurface(990, 68, 476);
SetUpdateHandler(&AnimatedSprite::update);
SetMessageHandler(&AsScene2812Rope::handleMessage);
@@ -2940,7 +2940,7 @@ void AsScene2812Rope::stRopingDown() {
AsScene2812TrapDoor::AsScene2812TrapDoor(NeverhoodEngine *vm)
: AnimatedSprite(vm, 0x805D0029, 100, 320, 240) {
-
+
SetMessageHandler(&AsScene2812TrapDoor::handleMessage);
_newStickFrameIndex = 0;
}
@@ -2959,15 +2959,15 @@ uint32 AsScene2812TrapDoor::handleMessage(int messageNum, const MessageParam &pa
Scene2812::Scene2812(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _paletteArea(0) {
-
+
if (getGlobalVar(V_HAS_FINAL_KEY) && getGlobalVar(V_KEY3_LOCATION) == 0)
setGlobalVar(V_KEY3_LOCATION, 3);
SetMessageHandler(&Scene2812::handleMessage);
SetUpdateHandler(&Scene2812::update);
-
+
setRectList(0x004AF700);
-
+
setBackground(0x03600606);
setPalette(0x03600606);
addEntity(_palette);
@@ -2983,7 +2983,7 @@ Scene2812::Scene2812(NeverhoodEngine *vm, Module *parentModule, int which)
_ssTape = insertSprite<SsScene1705Tape>(this, 6, 1100, 513, 437, 0xA1361863);
addCollisionSprite(_ssTape);
-
+
_asWinch = insertSprite<AsScene2812Winch>();
_asTrapDoor = insertSprite<AsScene2812TrapDoor>();
_asRope = insertSprite<AsScene2812Rope>(this);
@@ -3023,9 +3023,9 @@ Scene2812::Scene2812(NeverhoodEngine *vm, Module *parentModule, int which)
_sprite1->setVisible(false);
_klaymen->setClipRect(_sprite4->getDrawRect().x, 0, 640, _sprite3->getDrawRect().y2());
}
-
+
_asRope->setClipRect(0, _sprite2->getDrawRect().y, 640, _sprite3->getDrawRect().y2());
-
+
}
void Scene2812::update() {
@@ -3120,7 +3120,7 @@ Scene2822::Scene2822(NeverhoodEngine *vm, Module *parentModule, int which)
addBackground(_background);
_background->getSurface()->getDrawRect().y = -10;
setPalette(0xD542022E);
- insertPuzzleMouse(0x0028D089, 20, 620);
+ insertPuzzleMouse(0x2022AD5C, 20, 620);
_ssButton = insertStaticSprite(0x1A4D4120, 1100);
_ssButton->setVisible(false);
loadSound(2, 0x19044E72);
@@ -3140,7 +3140,7 @@ void Scene2822::update() {
_ssButton->setVisible(false);
_countdownStatus = 1;
_countdown = 48;
- } else if (_countdownStatus == 1) {
+ } else if (_countdownStatus == 1 && getGlobalVar(V_LADDER_DOWN_ACTION)) {
playSound(0, 0x1384CB60);
_countdownStatus = 2;
_countdown = 12;
diff --git a/engines/neverhood/modules/module2800.h b/engines/neverhood/modules/module2800.h
index fe62f11307..54a9daeb16 100644
--- a/engines/neverhood/modules/module2800.h
+++ b/engines/neverhood/modules/module2800.h
@@ -79,7 +79,7 @@ public:
protected:
Scene *_parentScene;
uint32 _fileHash1, _fileHash2;
- bool _isPulled, _isBusy;
+ bool _isPulled, _isBusy;
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
uint32 hmPulled(int messageNum, const MessageParam &param, Entity *sender);
};
@@ -323,7 +323,7 @@ protected:
Scene *_parentScene;
int _countdown;
int _testTubeSetNum, _testTubeIndex;
- void update();
+ void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
@@ -408,7 +408,7 @@ protected:
Sprite *_sprite3;
Sprite *_sprite4;
Sprite *_asSpew;
- void update();
+ void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
void findClosestPoint();
};
diff --git a/engines/neverhood/modules/module2900.cpp b/engines/neverhood/modules/module2900.cpp
index 248fb81bdc..9e51001a2e 100644
--- a/engines/neverhood/modules/module2900.cpp
+++ b/engines/neverhood/modules/module2900.cpp
@@ -36,7 +36,7 @@ Module2900::Module2900(NeverhoodEngine *vm, Module *parentModule, int which)
if (which >= 0)
setGlobalVar(V_TELEPORTER_WHICH, which);
-
+
createScene(0, 0);
}
@@ -255,7 +255,7 @@ SsScene2901LocationButton::SsScene2901LocationButton(NeverhoodEngine *vm, Scene
: StaticSprite(vm, 900), _parentScene(parentScene), _index(index), _countdown1(0) {
const NPoint &pt = kSsScene2901LocationButtonPoints[_index];
-
+
loadSprite(kSsScene2901LocationButtonFileHashes[which * 6 + index], kSLFDefDrawOffset | kSLFDefPosition, 800);
_collisionBounds.set(pt.x - 25, pt.y - 25, pt.x + 25, pt.y + 25);
setVisible(false);
@@ -263,7 +263,7 @@ SsScene2901LocationButton::SsScene2901LocationButton(NeverhoodEngine *vm, Scene
SetUpdateHandler(&SsScene2901LocationButton::update);
SetMessageHandler(&SsScene2901LocationButton::handleMessage);
}
-
+
void SsScene2901LocationButton::update() {
updatePosition();
if (_countdown1 != 0 && (--_countdown1) == 0) {
@@ -289,7 +289,7 @@ uint32 SsScene2901LocationButton::handleMessage(int messageNum, const MessagePar
SsScene2901LocationButtonLight::SsScene2901LocationButtonLight(NeverhoodEngine *vm, int which, uint index)
: StaticSprite(vm, 900), _index(index) {
-
+
loadSprite(kSsScene2901LocationButtonLightFileHashes1[which * 6 + index], kSLFDefDrawOffset | kSLFDefPosition, 900);
setVisible(false);
loadSound(0, kSsScene2901LocationButtonLightFileHashes2[_index]);
@@ -315,7 +315,7 @@ SsScene2901BrokenButton::SsScene2901BrokenButton(NeverhoodEngine *vm, int which)
SsScene2901BigButton::SsScene2901BigButton(NeverhoodEngine *vm, Scene *parentScene, int which)
: StaticSprite(vm, 900), _parentScene(parentScene), _which(which), _countdown1(0) {
- loadSprite(kSsScene2901BigButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 400);
+ loadSprite(kSsScene2901BigButtonFileHashes[which], kSLFDefDrawOffset | kSLFDefPosition, 400);
_collisionBounds.set(62, 94, 322, 350);
setVisible(false);
loadSound(0, 0xF3D420C8);
@@ -330,7 +330,7 @@ void SsScene2901BigButton::update() {
sendMessage(_parentScene, 0x2000, 0);
}
}
-
+
uint32 SsScene2901BigButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
switch (messageNum) {
@@ -361,7 +361,7 @@ Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which)
setBackground(kScene2901FileHashes1[_currLocationButtonNum]);
setPalette(kScene2901FileHashes1[_currLocationButtonNum]);
-
+
for (uint i = 0; i < 6; ++i) {
if (i != 2 || !_isButton2Broken) {
_ssLocationButtons[i] = insertSprite<SsScene2901LocationButton>(this, _currLocationButtonNum, i);
@@ -369,7 +369,7 @@ Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which)
_ssLocationButtonLights[i] = insertSprite<SsScene2901LocationButtonLight>(_currLocationButtonNum, i);
}
}
-
+
if (_isButton2Broken)
insertSprite<SsScene2901BrokenButton>(_currLocationButtonNum);
@@ -377,10 +377,10 @@ Scene2901::Scene2901(NeverhoodEngine *vm, Module *parentModule, int which)
addCollisionSprite(_ssBigButton);
insertPuzzleMouse(kScene2901FileHashes2[_currLocationButtonNum], 20, 620);
-
+
SetUpdateHandler(&Scene2901::update);
SetMessageHandler(&Scene2901::handleMessage);
-
+
}
void Scene2901::update() {
diff --git a/engines/neverhood/modules/module2900.h b/engines/neverhood/modules/module2900.h
index 75b29567f6..142f39a35c 100644
--- a/engines/neverhood/modules/module2900.h
+++ b/engines/neverhood/modules/module2900.h
@@ -49,7 +49,7 @@ protected:
Scene *_parentScene;
uint _index;
int _countdown1;
- void update();
+ void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
@@ -74,7 +74,7 @@ protected:
Scene *_parentScene;
int _which;
int _countdown1;
- void update();
+ void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
diff --git a/engines/neverhood/modules/module3000.cpp b/engines/neverhood/modules/module3000.cpp
index bc6b7790b4..ab3c18d1f4 100644
--- a/engines/neverhood/modules/module3000.cpp
+++ b/engines/neverhood/modules/module3000.cpp
@@ -39,7 +39,7 @@ static const uint32 kModule3000SoundList[] = {
Module3000::Module3000(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule), _soundVolume(0) {
-
+
_vm->_soundMan->addSoundList(0x81293110, kModule3000SoundList);
_vm->_soundMan->setSoundListParams(kModule3000SoundList, true, 50, 600, 5, 150);
_vm->_soundMan->setSoundParams(0x90F0D1C3, false, 20000, 30000, 20000, 30000);
@@ -73,7 +73,7 @@ Module3000::~Module3000() {
}
void Module3000::createScene(int sceneNum, int which) {
- static const byte kNavigationTypes05[] = {3, 0};
+ static const byte kNavigationTypes05[] = {2, 0};
static const byte kNavigationTypes06[] = {5};
debug(1, "Module3000::createScene(%d, %d)", sceneNum, which);
_vm->gameState().sceneNum = sceneNum;
@@ -440,7 +440,7 @@ static const uint32 kAsScene3009SymbolFileHashes[] = {
};
static const uint32 kSsScene3009SymbolArrowFileHashes1[] = {
- 0x24016060,
+ 0x24016060,
0x21216221,
0x486160A0,
0x42216422,
@@ -455,7 +455,7 @@ static const uint32 kSsScene3009SymbolArrowFileHashes1[] = {
};
static const uint32 kSsScene3009SymbolArrowFileHashes2[] = {
- 0x40092024,
+ 0x40092024,
0x01636002,
0x8071E028,
0x02A56064,
@@ -471,7 +471,7 @@ static const uint32 kSsScene3009SymbolArrowFileHashes2[] = {
SsScene3009FireCannonButton::SsScene3009FireCannonButton(NeverhoodEngine *vm, Scene3009 *parentScene)
: StaticSprite(vm, 1400), _parentScene(parentScene), _isClicked(false) {
-
+
loadSprite(0x120B24B0, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
setVisible(false);
SetUpdateHandler(&SsScene3009FireCannonButton::update);
@@ -637,7 +637,7 @@ uint32 AsScene3009VerticalIndicator::handleMessage(int messageNum, const Message
AsScene3009HorizontalIndicator::AsScene3009HorizontalIndicator(NeverhoodEngine *vm, Scene3009 *parentScene, uint32 cannonTargetStatus)
: AnimatedSprite(vm, 1000), _parentScene(parentScene), _enabled(false) {
-
+
_x = getGlobalVar(V_CANNON_TURNED) ? 533 : 92;
_y = 150;
createSurface1(0xC0C12954, 1200);
@@ -702,7 +702,7 @@ AsScene3009Symbol::AsScene3009Symbol(NeverhoodEngine *vm, Scene3009 *parentScene
: AnimatedSprite(vm, 1100), _parentScene(parentScene), _symbolPosition(symbolPosition) {
_symbolIndex = getSubVar(VA_CURR_CANNON_SYMBOLS, _symbolPosition);
-
+
_x = kAsScene3009SymbolPoints[_symbolPosition].x;
_y = kAsScene3009SymbolPoints[_symbolPosition].y;
createSurface1(kAsScene3009SymbolFileHashes[_symbolPosition / 3], 1200);
@@ -753,17 +753,17 @@ void AsScene3009Symbol::hide() {
}
Scene3009::Scene3009(NeverhoodEngine *vm, Module *parentModule, int which)
- : Scene(vm, parentModule), _keepVideo(false), _moveCannonLeftFirst(false),
+ : Scene(vm, parentModule), _keepVideo(false), _moveCannonLeftFirst(false),
_isTurning(false), _lockSymbolsPart1Countdown(1), _lockSymbolsPart2Countdown(1) {
_cannonTargetStatus = getGlobalVar(V_CANNON_TARGET_STATUS);
-
+
_vm->gameModule()->initCannonSymbolsPuzzle();
-
+
setGlobalVar(V_CANNON_SMACKER_NAME, 0);
-
+
_vm->_screen->clear();
-
+
setBackground(0xD000420C);
setPalette(0xD000420C);
insertPuzzleMouse(0x04208D08, 20, 620);
@@ -821,7 +821,7 @@ void Scene3009::openSmacker(uint32 fileHash, bool keepLastFrame) {
void Scene3009::update() {
Scene::update();
-
+
if (!_keepVideo && _cannonSmackerPlayer->isDone() && _cannonTargetStatus <= kCTSCount) {
switch (_cannonTargetStatus) {
case kCTSNull:
@@ -850,9 +850,9 @@ void Scene3009::update() {
if (_moveCannonLeftFirst) {
if (_cannonTargetStatus == kCTSLeftRobotNoTarget)
openSmacker(0x110A000F, false);
- else if (_cannonTargetStatus == kCTSLeftRobotIsTarget)
+ else if (_cannonTargetStatus == kCTSLeftRobotIsTarget)
openSmacker(0x500B004F, false);
- else if (_cannonTargetStatus == kCTSLeftNoRobot)
+ else if (_cannonTargetStatus == kCTSLeftNoRobot)
openSmacker(0x100B010E, false);
_moveCannonLeftFirst = false;
_asHorizontalIndicator->stMoveLeft();
@@ -1119,7 +1119,7 @@ AsScene3010DeadBolt::AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene
loadSound(0, 0x420073DC);
loadSound(1, 0x420073DC);
}
-
+
setVisible(false);
stIdle();
if (initUnlocked)
@@ -1127,7 +1127,7 @@ AsScene3010DeadBolt::AsScene3010DeadBolt(NeverhoodEngine *vm, Scene *parentScene
_needRefresh = true;
AnimatedSprite::updatePosition();
-
+
}
void AsScene3010DeadBolt::update() {
@@ -1217,7 +1217,7 @@ void AsScene3010DeadBolt::stDisabledMessage() {
Scene3010::Scene3010(NeverhoodEngine *vm, Module *parentModule, int which)
: Scene(vm, parentModule), _countdown(0), _doorUnlocked(false), _checkUnlocked(false) {
-
+
int initCountdown = 0;
setBackground(0x80802626);
@@ -1348,7 +1348,7 @@ static const uint32 kAsScene3011SymbolFileHashes[] = {
SsScene3011Button::SsScene3011Button(NeverhoodEngine *vm, Scene *parentScene, bool flag)
: StaticSprite(vm, 1400), _parentScene(parentScene), _countdown(0) {
-
+
loadSprite(flag ? 0x11282020 : 0x994D0433, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 400);
setVisible(false);
loadSound(0, 0x44061000);
@@ -1446,7 +1446,7 @@ Scene3011::Scene3011(NeverhoodEngine *vm, Module *parentModule, int which)
SetMessageHandler(&Scene3011::handleMessage);
SetUpdateHandler(&Scene3011::update);
-
+
setBackground(0x92124A04);
setPalette(0xA4070114);
addEntity(_palette);
@@ -1458,12 +1458,12 @@ Scene3011::Scene3011(NeverhoodEngine *vm, Module *parentModule, int which)
_ssButton = insertSprite<SsScene3011Button>(this, true);
addCollisionSprite(_ssButton);
-
+
}
void Scene3011::update() {
Scene::update();
-
+
if (_countdown != 0 && (--_countdown == 0)) {
switch (_updateStatus) {
case 0:
diff --git a/engines/neverhood/modules/module3000.h b/engines/neverhood/modules/module3000.h
index 797be1885f..a6cecb227e 100644
--- a/engines/neverhood/modules/module3000.h
+++ b/engines/neverhood/modules/module3000.h
@@ -244,7 +244,7 @@ protected:
bool _buttonClicked;
int _countdown;
int _noisySymbolIndex;
- int _currentSymbolIndex;
+ int _currentSymbolIndex;
int _noisyRandomSymbolIndex;
void update();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
diff --git a/engines/neverhood/mouse.cpp b/engines/neverhood/mouse.cpp
index 632f56fb74..13fba41e92 100644
--- a/engines/neverhood/mouse.cpp
+++ b/engines/neverhood/mouse.cpp
@@ -26,9 +26,9 @@
namespace Neverhood {
Mouse::Mouse(NeverhoodEngine *vm, uint32 fileHash, const NRect &mouseRect)
- : StaticSprite(vm, 2000), _mouseType(kMouseType433),
+ : StaticSprite(vm, 2000), _mouseType(kMouseType433),
_mouseCursorResource(vm), _frameNum(0) {
-
+
_mouseRect = mouseRect;
init(fileHash);
if (_x >= _mouseRect.x1 && _x <= _mouseRect.x2 &&
@@ -43,7 +43,7 @@ Mouse::Mouse(NeverhoodEngine *vm, uint32 fileHash, const NRect &mouseRect)
Mouse::Mouse(NeverhoodEngine *vm, uint32 fileHash, int16 x1, int16 x2)
: StaticSprite(vm, 2000), _mouseType(kMouseType435),
_mouseCursorResource(vm), _frameNum(0), _x1(x1), _x2(x2) {
-
+
init(fileHash);
if (_x <= _x1) {
_mouseCursorResource.setCursorNum(6);
@@ -69,8 +69,8 @@ Mouse::~Mouse() {
void Mouse::init(uint32 fileHash) {
_mouseCursorResource.load(fileHash);
- _x = _vm->getMouseX();
- _y = _vm->getMouseY();
+ _x = _vm->getMouseX();
+ _y = _vm->getMouseY();
createSurface(2000, 32, 32);
SetUpdateHandler(&Mouse::update);
SetMessageHandler(&Mouse::handleMessage);
@@ -99,7 +99,7 @@ void Mouse::update() {
_frameNum++;
if (_frameNum >= 6)
_frameNum = 0;
- _needRefresh = _frameNum % 2 == 0;
+ _needRefresh = _frameNum % 2 == 0;
}
uint32 Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -113,40 +113,40 @@ uint32 Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *s
case 1:
if (_x >= 320)
messageResult = 1;
- else
+ else
messageResult = 0;
break;
case 2:
default:
if (_x < 100)
messageResult = 0;
- else if (_x > 540)
+ else if (_x > 540)
messageResult = 1;
- else
+ else
messageResult = 2;
break;
case 3:
if (_x < 100)
messageResult = 0;
- else if (_x > 540)
+ else if (_x > 540)
messageResult = 1;
- else
+ else
messageResult = 4;
break;
case 4:
if (_x < 100)
messageResult = 0;
- else if (_x > 540)
+ else if (_x > 540)
messageResult = 1;
- else if (_y >= 150)
+ else if (_y >= 150)
messageResult = 2;
- else
+ else
messageResult = 3;
break;
case 5:
if (_y >= 240)
messageResult = 4;
- else
+ else
messageResult = 3;
break;
}
@@ -162,7 +162,7 @@ uint32 Mouse::handleMessage(int messageNum, const MessageParam &param, Entity *s
}
void Mouse::updateCursor() {
-
+
if (!_surface)
return;
@@ -213,44 +213,44 @@ void Mouse::updateCursorNum() {
case 1:
if (_x >= 320)
_mouseCursorResource.setCursorNum(5);
- else
+ else
_mouseCursorResource.setCursorNum(6);
break;
case 2:
default:
if (_x < 100)
_mouseCursorResource.setCursorNum(6);
- else if (_x > 540)
+ else if (_x > 540)
_mouseCursorResource.setCursorNum(5);
- else
+ else
_mouseCursorResource.setCursorNum(0);
break;
case 3:
if (_x < 100)
_mouseCursorResource.setCursorNum(1);
- else if (_x > 540)
+ else if (_x > 540)
_mouseCursorResource.setCursorNum(1);
break;
case 4:
if (_x < 100)
_mouseCursorResource.setCursorNum(6);
- else if (_x > 540)
+ else if (_x > 540)
_mouseCursorResource.setCursorNum(5);
- else if (_y >= 150)
+ else if (_y >= 150)
_mouseCursorResource.setCursorNum(0);
- else
+ else
_mouseCursorResource.setCursorNum(3);
break;
case 5:
if (_y >= 240)
_mouseCursorResource.setCursorNum(2);
- else
+ else
_mouseCursorResource.setCursorNum(3);
break;
}
break;
}
-
+
}
} // End of namespace Neverhood
diff --git a/engines/neverhood/mouse.h b/engines/neverhood/mouse.h
index 0b927de4df..d6f42b4071 100644
--- a/engines/neverhood/mouse.h
+++ b/engines/neverhood/mouse.h
@@ -52,7 +52,7 @@ protected:
int16 _x1;
int16 _x2;
int _type;
- void init(uint32 fileHash);
+ void init(uint32 fileHash);
void update();
void updateCursorNum();
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
diff --git a/engines/neverhood/navigationscene.cpp b/engines/neverhood/navigationscene.cpp
index 33e2a264a8..51ab96ef37 100644
--- a/engines/neverhood/navigationscene.cpp
+++ b/engines/neverhood/navigationscene.cpp
@@ -25,31 +25,35 @@
namespace Neverhood {
+enum AreaType {
+ kAreaCanMoveForward = 0,
+ kAreaCannotMoveForward = 1
+};
+
NavigationScene::NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, const byte *itemsTypes)
: Scene(vm, parentModule), _itemsTypes(itemsTypes), _navigationIndex(navigationIndex), _smackerDone(false),
_isWalkingForward(false), _isTurning(false), _smackerFileHash(0), _interactive(true), _leaveSceneAfter(false) {
_navigationList = _vm->_staticData->getNavigationList(navigationListId);
-
+
if (_navigationIndex < 0) {
_navigationIndex = (int)getGlobalVar(V_NAVIGATION_INDEX);
if (_navigationIndex >= (int)_navigationList->size())
- _navigationIndex = 0;
+ _navigationIndex = 0;
}
setGlobalVar(V_NAVIGATION_INDEX, _navigationIndex);
-
+
SetUpdateHandler(&NavigationScene::update);
SetMessageHandler(&NavigationScene::handleMessage);
-
- _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, (*_navigationList)[_navigationIndex].fileHash, true, true));
-
+
+ _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, (*_navigationList)[_navigationIndex].fileHash, true, true));
+
createMouseCursor();
_vm->_screen->clear();
_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
sendMessage(_parentModule, 0x100A, _navigationIndex);
-
}
NavigationScene::~NavigationScene() {
@@ -95,7 +99,7 @@ void NavigationScene::update() {
_vm->_screen->setSmackerDecoder(_smackerPlayer->getSmackerDecoder());
sendMessage(_parentModule, 0x100A, _navigationIndex);
}
- }
+ }
Scene::update();
}
@@ -121,39 +125,34 @@ uint32 NavigationScene::handleMessage(int messageNum, const MessageParam &param,
}
void NavigationScene::createMouseCursor() {
-
const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex];
uint32 mouseCursorFileHash;
int areaType;
- if (_mouseCursor) {
+ if (_mouseCursor)
deleteSprite((Sprite**)&_mouseCursor);
- }
mouseCursorFileHash = navigationItem.mouseCursorFileHash;
if (mouseCursorFileHash == 0)
mouseCursorFileHash = 0x63A40028;
-
- if (_itemsTypes) {
+
+ if (_itemsTypes)
areaType = _itemsTypes[_navigationIndex];
- } else if (navigationItem.middleSmackerFileHash != 0 || navigationItem.middleFlag) {
- areaType = 0;
- } else {
- areaType = 1;
- }
+ else if (navigationItem.middleSmackerFileHash != 0 || navigationItem.middleFlag)
+ areaType = kAreaCanMoveForward;
+ else
+ areaType = kAreaCannotMoveForward;
insertNavigationMouse(mouseCursorFileHash, areaType);
sendPointMessage(_mouseCursor, 0x4002, _vm->getMousePos());
-
}
void NavigationScene::handleNavigation(const NPoint &mousePos) {
-
const NavigationItem &navigationItem = (*_navigationList)[_navigationIndex];
bool oldIsWalkingForward = _isWalkingForward;
bool oldIsTurning = _isTurning;
uint32 direction = sendPointMessage(_mouseCursor, 0x2064, mousePos);
-
+
switch (direction) {
case 0:
if (navigationItem.leftSmackerFileHash != 0) {
@@ -204,13 +203,12 @@ void NavigationScene::handleNavigation(const NPoint &mousePos) {
}
break;
}
-
+
if (oldIsTurning != _isTurning)
_vm->_soundMan->setSoundThreePlayFlag(_isTurning);
if (oldIsWalkingForward != _isWalkingForward)
_vm->_soundMan->setTwoSoundsPlayFlag(_isWalkingForward);
-
}
} // End of namespace Neverhood
diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp
index e7c9f32d45..061e6d1279 100644
--- a/engines/neverhood/neverhood.cpp
+++ b/engines/neverhood/neverhood.cpp
@@ -104,9 +104,9 @@ Common::Error NeverhoodEngine::run() {
_soundMan = new SoundMan(this);
_audioResourceMan = new AudioResourceMan(this);
-
+
_gameModule = new GameModule(this);
-
+
_isSaveAllowed = true;
_updateSound = true;
@@ -122,15 +122,15 @@ Common::Error NeverhoodEngine::run() {
(*navigationList)[5].middleSmackerFileHash = 0;
(*navigationList)[5].middleFlag = 1;
}
-
+
if (ConfMan.hasKey("save_slot")) {
if (loadGameState(ConfMan.getInt("save_slot")).getCode() != Common::kNoError)
_gameModule->startup();
} else
_gameModule->startup();
-
+
mainLoop();
-
+
delete _gameModule;
delete _soundMan;
delete _audioResourceMan;
@@ -141,7 +141,7 @@ Common::Error NeverhoodEngine::run() {
delete _gameVars;
delete _staticData;
-
+
return Common::kNoError;
}
diff --git a/engines/neverhood/neverhood.h b/engines/neverhood/neverhood.h
index 773e80df7d..5643e345ad 100644
--- a/engines/neverhood/neverhood.h
+++ b/engines/neverhood/neverhood.h
@@ -93,7 +93,7 @@ public:
AudioResourceMan *_audioResourceMan;
public:
-
+
/* Save/load */
enum kReadSaveHeaderError {
@@ -118,7 +118,7 @@ public:
bool canLoadGameStateCurrently() { return _isSaveAllowed; }
bool canSaveGameStateCurrently() { return _isSaveAllowed; }
-
+
Common::Error loadGameState(int slot);
Common::Error saveGameState(int slot, const Common::String &description);
Common::Error removeGameState(int slot);
diff --git a/engines/neverhood/palette.cpp b/engines/neverhood/palette.cpp
index d4b9b67f53..c381f46671 100644
--- a/engines/neverhood/palette.cpp
+++ b/engines/neverhood/palette.cpp
@@ -81,7 +81,7 @@ void Palette::addPalette(uint32 fileHash, int toIndex, int count, int fromIndex)
if (toIndex + count > 256)
count = 256 - toIndex;
paletteResource.load(fileHash);
- memcpy(_palette + toIndex * 4, paletteResource.palette() + fromIndex * 4, count * 4);
+ memcpy(_palette + toIndex * 4, paletteResource.palette() + fromIndex * 4, count * 4);
_vm->_screen->testPalette(_palette);
}
@@ -90,20 +90,20 @@ void Palette::addBasePalette(uint32 fileHash, int toIndex, int count, int fromIn
if (toIndex + count > 256)
count = 256 - toIndex;
paletteResource.load(fileHash);
- memcpy(_basePalette + toIndex * 4, paletteResource.palette() + fromIndex * 4, count * 4);
+ memcpy(_basePalette + toIndex * 4, paletteResource.palette() + fromIndex * 4, count * 4);
}
void Palette::copyPalette(const byte *palette, int toIndex, int count, int fromIndex) {
if (toIndex + count > 256)
count = 256 - toIndex;
- memcpy(_palette + toIndex * 4, palette + fromIndex * 4, count * 4);
+ memcpy(_palette + toIndex * 4, palette + fromIndex * 4, count * 4);
_vm->_screen->testPalette(_palette);
}
void Palette::copyBasePalette(int toIndex, int count, int fromIndex) {
if (toIndex + count > 256)
count = 256 - toIndex;
- memcpy(_basePalette + toIndex * 4, _palette + fromIndex * 4, count * 4);
+ memcpy(_basePalette + toIndex * 4, _palette + fromIndex * 4, count * 4);
}
void Palette::startFadeToBlack(int counter) {
@@ -115,7 +115,7 @@ void Palette::startFadeToBlack(int counter) {
_fadeToB = 0;
_palCounter = counter;
_fadeStep = 255 / counter;
- _status = 1;
+ _status = 1;
}
void Palette::startFadeToWhite(int counter) {
@@ -127,7 +127,7 @@ void Palette::startFadeToWhite(int counter) {
_fadeToB = 255;
_palCounter = counter;
_fadeStep = 255 / counter;
- _status = 1;
+ _status = 1;
}
void Palette::startFadeToPalette(int counter) {
@@ -136,7 +136,7 @@ void Palette::startFadeToPalette(int counter) {
counter = 1;
_palCounter = counter;
_fadeStep = 255 / counter;
- _status = 2;
+ _status = 2;
}
void Palette::fillBaseWhite(int index, int count) {
diff --git a/engines/neverhood/resource.cpp b/engines/neverhood/resource.cpp
index 442713196e..5f7aea86f4 100644
--- a/engines/neverhood/resource.cpp
+++ b/engines/neverhood/resource.cpp
@@ -57,7 +57,7 @@ bool SpriteResource::load(uint32 fileHash, bool doLoadPosition) {
const byte *spriteData = _resourceHandle.data();
NPoint *position = doLoadPosition ? &_position : NULL;
parseBitmapResource(spriteData, &_rle, &_dimensions, position, NULL, &_pixels);
- }
+ }
return _pixels != NULL;
}
@@ -134,11 +134,11 @@ bool AnimResource::load(uint32 fileHash) {
return true;
unload();
-
+
_vm->_res->queryResource(fileHash, _resourceHandle);
if (!_resourceHandle.isValid() || _resourceHandle.type() != kResTypeAnimation)
return false;
-
+
const byte *resourceData, *animList, *frameList;
uint16 animInfoStartOfs, animListIndex, animListCount;
uint16 frameListStartOfs, frameCount;
@@ -146,20 +146,20 @@ bool AnimResource::load(uint32 fileHash) {
_vm->_res->loadResource(_resourceHandle);
resourceData = _resourceHandle.data();
-
+
animListCount = READ_LE_UINT16(resourceData);
animInfoStartOfs = READ_LE_UINT16(resourceData + 2);
spriteDataOfs = READ_LE_UINT32(resourceData + 4);
paletteDataOfs = READ_LE_UINT32(resourceData + 8);
-
+
animList = resourceData + 12;
for (animListIndex = 0; animListIndex < animListCount; animListIndex++) {
debug(8, "hash: %08X", READ_LE_UINT32(animList));
if (READ_LE_UINT32(animList) == fileHash)
break;
- animList += 8;
+ animList += 8;
}
-
+
if (animListIndex >= animListCount) {
_vm->_res->unloadResource(_resourceHandle);
return false;
@@ -168,12 +168,12 @@ bool AnimResource::load(uint32 fileHash) {
_spriteData = resourceData + spriteDataOfs;
if (paletteDataOfs > 0)
_paletteData = resourceData + paletteDataOfs;
-
+
frameCount = READ_LE_UINT16(animList + 4);
frameListStartOfs = READ_LE_UINT16(animList + 6);
-
+
debug(8, "frameCount = %d; frameListStartOfs = %04X; animInfoStartOfs = %04X", frameCount, frameListStartOfs, animInfoStartOfs);
-
+
frameList = resourceData + animInfoStartOfs + frameListStartOfs;
_frames.clear();
@@ -189,13 +189,13 @@ bool AnimResource::load(uint32 fileHash) {
frameInfo.drawOffset.height = READ_LE_UINT16(frameList + 12);
frameInfo.deltaX = READ_LE_UINT16(frameList + 14);
frameInfo.deltaY = READ_LE_UINT16(frameList + 16);
- frameInfo.collisionBoundsOffset.x = READ_LE_UINT16(frameList + 18);
- frameInfo.collisionBoundsOffset.y = READ_LE_UINT16(frameList + 20);
- frameInfo.collisionBoundsOffset.width = READ_LE_UINT16(frameList + 22);
+ frameInfo.collisionBoundsOffset.x = READ_LE_UINT16(frameList + 18);
+ frameInfo.collisionBoundsOffset.y = READ_LE_UINT16(frameList + 20);
+ frameInfo.collisionBoundsOffset.width = READ_LE_UINT16(frameList + 22);
frameInfo.collisionBoundsOffset.height = READ_LE_UINT16(frameList + 24);
frameInfo.spriteDataOffs = READ_LE_UINT32(frameList + 28);
- debug(8, "frameHash = %08X; counter = %d; rect = (%d,%d,%d,%d); deltaX = %d; deltaY = %d; collisionBoundsOffset = (%d,%d,%d,%d); spriteDataOffs = %08X",
- frameInfo.frameHash, frameInfo.counter,
+ debug(8, "frameHash = %08X; counter = %d; rect = (%d,%d,%d,%d); deltaX = %d; deltaY = %d; collisionBoundsOffset = (%d,%d,%d,%d); spriteDataOffs = %08X",
+ frameInfo.frameHash, frameInfo.counter,
frameInfo.drawOffset.x, frameInfo.drawOffset.y, frameInfo.drawOffset.width, frameInfo.drawOffset.height,
frameInfo.deltaX, frameInfo.deltaY,
frameInfo.collisionBoundsOffset.x, frameInfo.collisionBoundsOffset.y, frameInfo.collisionBoundsOffset.width, frameInfo.collisionBoundsOffset.height,
@@ -203,11 +203,11 @@ bool AnimResource::load(uint32 fileHash) {
frameList += 32;
_frames.push_back(frameInfo);
}
-
+
_fileHash = fileHash;
return true;
-
+
}
void AnimResource::unload() {
@@ -229,7 +229,7 @@ int16 AnimResource::getFrameIndex(uint32 frameHash) {
break;
}
debug(2, "AnimResource::getFrameIndex(%08X) -> %d", frameHash, frameIndex);
- return frameIndex;
+ return frameIndex;
}
void AnimResource::setRepl(byte oldColor, byte newColor) {
@@ -254,7 +254,7 @@ NDimensions AnimResource::loadSpriteDimensions(uint32 fileHash) {
// MouseCursorResource
-MouseCursorResource::MouseCursorResource(NeverhoodEngine *vm)
+MouseCursorResource::MouseCursorResource(NeverhoodEngine *vm)
: _cursorSprite(vm), _cursorNum(4), _currFileHash(0) {
_rect.width = 32;
@@ -265,7 +265,7 @@ void MouseCursorResource::load(uint32 fileHash) {
if (_currFileHash != fileHash) {
if (_cursorSprite.load(fileHash) && !_cursorSprite.isRle() &&
_cursorSprite.getDimensions().width == 96 && _cursorSprite.getDimensions().height == 224) {
- _currFileHash = fileHash;
+ _currFileHash = fileHash;
} else {
unload();
}
@@ -296,14 +296,14 @@ NDrawRect& MouseCursorResource::getRect() {
void MouseCursorResource::draw(int frameNum, Graphics::Surface *destSurface) {
if (_cursorSprite.getPixels()) {
const int sourcePitch = (_cursorSprite.getDimensions().width + 3) & 0xFFFC; // 4 byte alignment
- const int destPitch = destSurface->pitch;
+ const int destPitch = destSurface->pitch;
const byte *source = _cursorSprite.getPixels() + _cursorNum * (sourcePitch * 32) + frameNum * 32;
byte *dest = (byte*)destSurface->pixels;
for (int16 yc = 0; yc < 32; yc++) {
memcpy(dest, source, 32);
source += sourcePitch;
dest += destPitch;
- }
+ }
}
}
@@ -311,7 +311,7 @@ void MouseCursorResource::draw(int frameNum, Graphics::Surface *destSurface) {
TextResource::TextResource(NeverhoodEngine *vm)
: _vm(vm), _textData(NULL), _count(0) {
-
+
}
TextResource::~TextResource() {
@@ -372,7 +372,7 @@ void DataResource::load(uint32 fileHash) {
dataS.seek(2 + i * 8);
DRDirectoryItem drDirectoryItem;
drDirectoryItem.nameHash = dataS.readUint32LE();
- drDirectoryItem.offset = dataS.readUint16LE();
+ drDirectoryItem.offset = dataS.readUint16LE();
drDirectoryItem.type = dataS.readUint16LE();
debug(2, "%03d nameHash = %08X; offset = %04X; type = %d", i, drDirectoryItem.nameHash, drDirectoryItem.offset, drDirectoryItem.type);
dataS.seek(itemStartOffs + drDirectoryItem.offset);
@@ -415,7 +415,7 @@ void DataResource::load(uint32 fileHash) {
hitRect.rect.y1 = dataS.readUint16LE();
hitRect.rect.x2 = dataS.readUint16LE();
hitRect.rect.y2 = dataS.readUint16LE();
- hitRect.type = dataS.readUint16LE() + 0x5001;
+ hitRect.type = dataS.readUint16LE() + 0x5001;
debug(3, "(%d, %d, %d, %d) -> %04d", hitRect.rect.x1, hitRect.rect.y1, hitRect.rect.x2, hitRect.rect.y2, hitRect.type);
hitRectList->push_back(hitRect);
}
@@ -491,7 +491,7 @@ void DataResource::load(uint32 fileHash) {
break;
}
}
- _directory.push_back(drDirectoryItem);
+ _directory.push_back(drDirectoryItem);
}
}
}
@@ -540,12 +540,12 @@ HitRectList *DataResource::getHitRectList() {
MessageList *DataResource::getMessageListAtPos(int16 klaymenX, int16 klaymenY, int16 mouseX, int16 mouseY) {
for (uint i = 0; i < _drRects.size(); i++) {
- if (klaymenX >= _drRects[i].rect.x1 && klaymenX <= _drRects[i].rect.x2 &&
+ if (klaymenX >= _drRects[i].rect.x1 && klaymenX <= _drRects[i].rect.x2 &&
klaymenY >= _drRects[i].rect.y1 && klaymenY <= _drRects[i].rect.y2) {
- DRSubRectList *drSubRectList = _drSubRectLists[_drRects[i].subRectIndex];
+ DRSubRectList *drSubRectList = _drSubRectLists[_drRects[i].subRectIndex];
for (uint j = 0; j < drSubRectList->size(); j++) {
DRSubRect &subRect = (*drSubRectList)[j];
- if (mouseX >= subRect.rect.x1 && mouseX <= subRect.rect.x2 &&
+ if (mouseX >= subRect.rect.x1 && mouseX <= subRect.rect.x2 &&
mouseY >= subRect.rect.y1 && mouseY <= subRect.rect.y2) {
return _messageLists[subRect.messageListItemIndex];
}
diff --git a/engines/neverhood/resource.h b/engines/neverhood/resource.h
index 6a84a69ecd..40236d9d22 100644
--- a/engines/neverhood/resource.h
+++ b/engines/neverhood/resource.h
@@ -168,7 +168,7 @@ protected:
struct DRDirectoryItem {
uint32 nameHash;
- uint16 offset;
+ uint16 offset;
uint16 type;
};
@@ -195,7 +195,7 @@ protected:
Common::Array<MessageList*> _messageLists;
Common::Array<DRRect> _drRects;
Common::Array<DRSubRectList*> _drSubRectLists;
- DataResource::DRDirectoryItem *findDRDirectoryItem(uint32 nameHash, uint16 type);
+ DataResource::DRDirectoryItem *findDRDirectoryItem(uint32 nameHash, uint16 type);
};
uint32 calcHash(const char *value);
diff --git a/engines/neverhood/resourceman.cpp b/engines/neverhood/resourceman.cpp
index d5e7786c17..37089a5bd6 100644
--- a/engines/neverhood/resourceman.cpp
+++ b/engines/neverhood/resourceman.cpp
@@ -49,7 +49,7 @@ void ResourceMan::addArchive(const Common::String &filename) {
if (archiveEntry->timeStamp > entry->archiveEntry->timeStamp) {
entry->archive = archive;
entry->archiveEntry = archiveEntry;
- }
+ }
} else {
ResourceFileEntry newEntry;
newEntry.resourceHandle = -1;
diff --git a/engines/neverhood/saveload.cpp b/engines/neverhood/saveload.cpp
index ae93a0cea4..01988769e6 100644
--- a/engines/neverhood/saveload.cpp
+++ b/engines/neverhood/saveload.cpp
@@ -78,7 +78,7 @@ bool NeverhoodEngine::savegame(const char *filename, const char *description) {
byte descriptionLen = strlen(description);
out->writeByte(descriptionLen);
out->write(description, descriptionLen);
-
+
Graphics::saveThumbnail(*out);
// Not used yet, reserved for future usage
@@ -96,7 +96,7 @@ bool NeverhoodEngine::savegame(const char *filename, const char *description) {
_gameVars->setGlobalVar(V_CURRENT_SCENE_WHICH, _gameState.which);
_gameVars->saveState(out);
-
+
out->finalize();
delete out;
return true;
@@ -112,17 +112,17 @@ bool NeverhoodEngine::loadgame(const char *filename) {
SaveHeader header;
kReadSaveHeaderError errorCode = readSaveHeader(in, false, header);
-
+
if (errorCode != kRSHENoError) {
warning("Error loading savegame '%s'", filename);
delete in;
return false;
}
-
+
g_engine->setTotalPlayTime(header.playTime * 1000);
_gameVars->loadState(in);
-
+
_gameState.sceneNum = _gameVars->getGlobalVar(V_CURRENT_SCENE);
_gameState.which = _gameVars->getGlobalVar(V_CURRENT_SCENE_WHICH);
diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp
index 80a2b69169..e76a9ca521 100644
--- a/engines/neverhood/scene.cpp
+++ b/engines/neverhood/scene.cpp
@@ -28,7 +28,7 @@ namespace Neverhood {
Scene::Scene(NeverhoodEngine *vm, Module *parentModule)
: Entity(vm, 0), _parentModule(parentModule), _dataResource(vm), _hitRects(NULL),
_mouseCursorWasVisible(true) {
-
+
_isKlaymenBusy = false;
_doConvertMessages = false;
_messageList = NULL;
@@ -50,10 +50,10 @@ Scene::Scene(NeverhoodEngine *vm, Module *parentModule)
_smackerPlayer = NULL;
_isMessageListBusy = false;
_messageValue = -1;
-
+
SetUpdateHandler(&Scene::update);
SetMessageHandler(&Scene::handleMessage);
-
+
_vm->_screen->clearRenderQueue();
}
@@ -71,7 +71,7 @@ Scene::~Scene() {
delete *iter;
// Don't delete surfaces since they always belong to an entity
-
+
// Purge the resources after each scene
_vm->_res->purgeResources();
@@ -84,7 +84,7 @@ void Scene::draw() {
} else {
for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++)
(*iter)->draw();
- }
+ }
}
void Scene::addEntity(Entity *entity) {
@@ -99,7 +99,7 @@ void Scene::addEntity(Entity *entity) {
if (insertIndex >= 0)
_entities.insert_at(insertIndex, entity);
else
- _entities.push_back(entity);
+ _entities.push_back(entity);
}
bool Scene::removeEntity(Entity *entity) {
@@ -108,7 +108,7 @@ bool Scene::removeEntity(Entity *entity) {
_entities.remove_at(index);
return true;
}
- return false;
+ return false;
}
void Scene::addSurface(BaseSurface *surface) {
@@ -124,7 +124,7 @@ void Scene::addSurface(BaseSurface *surface) {
if (insertIndex >= 0)
_surfaces.insert_at(insertIndex, surface);
else
- _surfaces.push_back(surface);
+ _surfaces.push_back(surface);
}
}
@@ -135,7 +135,7 @@ bool Scene::removeSurface(BaseSurface *surface) {
return true;
}
}
- return false;
+ return false;
}
void Scene::printSurfaces(Console *con) {
@@ -246,12 +246,12 @@ void Scene::update() {
if (_mouseClicked) {
if (_klaymen) {
if (_canAcceptInput &&
- _klaymen->hasMessageHandler() &&
+ _klaymen->hasMessageHandler() &&
sendMessage(_klaymen, 0x1008, 0) != 0 &&
queryPositionSprite(_mouseClickPos.x, _mouseClickPos.y)) {
_mouseClicked = false;
} else if (_canAcceptInput &&
- _klaymen->hasMessageHandler() &&
+ _klaymen->hasMessageHandler() &&
sendMessage(_klaymen, 0x1008, 0) != 0) {
_mouseClicked = !queryPositionRectList(_mouseClickPos.x, _mouseClickPos.y);
}
@@ -262,7 +262,7 @@ void Scene::update() {
processMessageList();
- // Update all entities
+ // Update all entities
for (Common::Array<Entity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++)
(*iter)->handleUpdate();
@@ -283,7 +283,7 @@ uint32 Scene::handleMessage(int messageNum, const MessageParam &param, Entity *s
_mouseClickPos = param.asPoint();
break;
case 0x0006:
- sendMessage(_parentModule, 0x1009, param);
+ sendMessage(_parentModule, 0x1009, param);
break;
case 0x1006:
// Sent by Klaymen when its animation sequence has finished
@@ -332,7 +332,7 @@ uint32 Scene::handleMessage(int messageNum, const MessageParam &param, Entity *s
bool Scene::queryPositionSprite(int16 mouseX, int16 mouseY) {
for (uint i = 0; i < _collisionSprites.size(); i++) {
Sprite *sprite = _collisionSprites[i];
- if (sprite->hasMessageHandler() && sprite->isPointInside(mouseX, mouseY) &&
+ if (sprite->hasMessageHandler() && sprite->isPointInside(mouseX, mouseY) &&
sendPointMessage(sprite, 0x1011, _mouseClickPos) != 0) {
return true;
}
@@ -412,8 +412,8 @@ void Scene::processMessageList() {
_messageList2 = NULL;
_messageListStatus = 0;
}
-
- if (_messageList && _klaymen) {
+
+ if (_messageList && _klaymen) {
#if 0
debug("MessageList: %p, %d", (void*)_messageList, _messageList->size());
@@ -423,11 +423,11 @@ void Scene::processMessageList() {
}
debug("--------------------------------");
#endif
-
+
while (_messageList && _messageListIndex < _messageListCount && !_isKlaymenBusy) {
uint32 messageNum = (*_messageList)[_messageListIndex].messageNum;
uint32 messageParam = (*_messageList)[_messageListIndex].messageValue;
-
+
++_messageListIndex;
if (_messageListIndex == _messageListCount)
sendMessage(_klaymen, 0x1021, 0);
@@ -460,7 +460,7 @@ void Scene::processMessageList() {
if (_klaymen->hasMessageHandler() && sendMessage(_klaymen, messageNum, messageParam) != 0) {
_isKlaymenBusy = false;
}
- }
+ }
if (_messageListIndex == _messageListCount) {
_canAcceptInput = true;
_messageList = NULL;
@@ -469,7 +469,7 @@ void Scene::processMessageList() {
}
_isMessageListBusy = false;
-
+
}
void Scene::cancelMessageList() {
@@ -531,7 +531,7 @@ uint16 Scene::convertMessageNum(uint32 messageNum) {
case 0x42002200:
return 0x4004;
case 0x428D4894:
- return 0x101A;
+ return 0x101A;
}
return 0x1000;
}
@@ -546,7 +546,7 @@ HitRect *Scene::findHitRectAtPos(int16 x, int16 y) {
for (HitRectList::iterator it = _hitRects->begin(); it != _hitRects->end(); it++)
if ((*it).rect.contains(x, y))
return &(*it);
- return &kDefaultHitRect;
+ return &kDefaultHitRect;
}
void Scene::addCollisionSprite(Sprite *sprite) {
@@ -561,7 +561,7 @@ void Scene::addCollisionSprite(Sprite *sprite) {
if (insertIndex >= 0)
_collisionSprites.insert_at(insertIndex, sprite);
else
- _collisionSprites.push_back(sprite);
+ _collisionSprites.push_back(sprite);
}
void Scene::removeCollisionSprite(Sprite *sprite) {
@@ -583,7 +583,7 @@ void Scene::checkCollision(Sprite *sprite, uint16 flags, int messageNum, uint32
if ((sprite->getFlags() & flags) && collSprite->checkCollision(sprite->getCollisionBounds())) {
sprite->sendMessage(collSprite, messageNum, messageParam);
}
- }
+ }
}
void Scene::insertMouse(Mouse *mouseCursor) {
diff --git a/engines/neverhood/scene.h b/engines/neverhood/scene.h
index 813ffba0bb..5e42e34418 100644
--- a/engines/neverhood/scene.h
+++ b/engines/neverhood/scene.h
@@ -76,89 +76,89 @@ public:
void checkCollision(Sprite *sprite, uint16 flags, int messageNum, uint32 messageParam);
// Some crazy templated functions to make the logic code smaller/simpler (imo!)
// insertKlaymen
- template<class T>
+ template<class T>
void insertKlaymen() {
_klaymen = (T*)addSprite(new T(_vm, this));
}
- template<class T, class Arg1>
+ template<class T, class Arg1>
void insertKlaymen(Arg1 arg1) {
_klaymen = (T*)addSprite(new T(_vm, this, arg1));
}
- template<class T, class Arg1, class Arg2>
+ template<class T, class Arg1, class Arg2>
void insertKlaymen(Arg1 arg1, Arg2 arg2) {
_klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2));
}
- template<class T, class Arg1, class Arg2, class Arg3>
+ template<class T, class Arg1, class Arg2, class Arg3>
void insertKlaymen(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
_klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2, arg3));
}
- template<class T, class Arg1, class Arg2, class Arg3, class Arg4>
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4>
void insertKlaymen(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
_klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2, arg3, arg4));
}
- template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
void insertKlaymen(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) {
_klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2, arg3, arg4, arg5));
}
- template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>
void insertKlaymen(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6) {
_klaymen = (T*)addSprite(new T(_vm, this, arg1, arg2, arg3, arg4, arg5, arg6));
}
// insertSprite
- template<class T>
+ template<class T>
T* insertSprite() {
return (T*)addSprite(new T(_vm));
}
- template<class T, class Arg1>
+ template<class T, class Arg1>
T* insertSprite(Arg1 arg1) {
return (T*)addSprite(new T(_vm, arg1));
}
- template<class T, class Arg1, class Arg2>
+ template<class T, class Arg1, class Arg2>
T* insertSprite(Arg1 arg1, Arg2 arg2) {
return (T*)addSprite(new T(_vm, arg1, arg2));
}
- template<class T, class Arg1, class Arg2, class Arg3>
+ template<class T, class Arg1, class Arg2, class Arg3>
T* insertSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
return (T*)addSprite(new T(_vm, arg1, arg2, arg3));
}
- template<class T, class Arg1, class Arg2, class Arg3, class Arg4>
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4>
T* insertSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
return (T*)addSprite(new T(_vm, arg1, arg2, arg3, arg4));
}
- template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
T* insertSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) {
return (T*)addSprite(new T(_vm, arg1, arg2, arg3, arg4, arg5));
}
- template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>
T* insertSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6) {
return (T*)addSprite(new T(_vm, arg1, arg2, arg3, arg4, arg5, arg6));
}
// createSprite
- template<class T>
+ template<class T>
T* createSprite() {
return new T(_vm);
}
- template<class T, class Arg1>
+ template<class T, class Arg1>
T* createSprite(Arg1 arg1) {
return new T(_vm, arg1);
}
- template<class T, class Arg1, class Arg2>
+ template<class T, class Arg1, class Arg2>
T* createSprite(Arg1 arg1, Arg2 arg2) {
return new T(_vm, arg1, arg2);
}
- template<class T, class Arg1, class Arg2, class Arg3>
+ template<class T, class Arg1, class Arg2, class Arg3>
T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3) {
return new T(_vm, arg1, arg2, arg3);
}
- template<class T, class Arg1, class Arg2, class Arg3, class Arg4>
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4>
T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) {
return new T(_vm, arg1, arg2, arg3, arg4);
}
- template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>
T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) {
return new T(_vm, arg1, arg2, arg3, arg4, arg5);
}
- template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>
+ template<class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>
T* createSprite(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6) {
return new T(_vm, arg1, arg2, arg3, arg4, arg5, arg6);
}
diff --git a/engines/neverhood/screen.cpp b/engines/neverhood/screen.cpp
index 5a748cfab4..4a5bfb92ce 100644
--- a/engines/neverhood/screen.cpp
+++ b/engines/neverhood/screen.cpp
@@ -28,16 +28,16 @@ namespace Neverhood {
Screen::Screen(NeverhoodEngine *vm)
: _vm(vm), _paletteData(NULL), _paletteChanged(false), _smackerDecoder(NULL),
_yOffset(0), _fullRefresh(false) {
-
+
_ticks = _vm->_system->getMillis();
-
+
_backScreen = new Graphics::Surface();
_backScreen->create(640, 480, Graphics::PixelFormat::createFormatCLUT8());
-
+
_renderQueue = new RenderQueue();
_prevRenderQueue = new RenderQueue();
_microTiles = new MicroTileArray(640, 480);
-
+
}
Screen::~Screen() {
@@ -72,13 +72,13 @@ void Screen::update() {
}
}
}
-
+
for (RenderQueue::iterator jt = _prevRenderQueue->begin(); jt != _prevRenderQueue->end(); ++jt) {
RenderItem &prevRenderItem = (*jt);
if (prevRenderItem._refresh)
_microTiles->addRect(Common::Rect(prevRenderItem._destX, prevRenderItem._destY, prevRenderItem._destX + prevRenderItem._width, prevRenderItem._destY + prevRenderItem._height));
}
-
+
for (RenderQueue::iterator it = _renderQueue->begin(); it != _renderQueue->end(); ++it) {
RenderItem &renderItem = (*it);
if (renderItem._refresh)
@@ -93,7 +93,7 @@ void Screen::update() {
for (RectangleList::iterator ri = updateRects->begin(); ri != updateRects->end(); ++ri)
blitRenderItem(renderItem, *ri);
}
-
+
SWAP(_renderQueue, _prevRenderQueue);
_renderQueue->clear();
@@ -202,12 +202,12 @@ void Screen::drawSurface2(const Graphics::Surface *surface, NDrawRect &drawRect,
destX = drawRect.x;
ddRect.x1 = 0;
}
-
+
if (drawRect.y + drawRect.height >= clipRect.y2)
ddRect.y2 = clipRect.y2 - drawRect.y;
else
ddRect.y2 = drawRect.height;
-
+
if (drawRect.y < clipRect.y1) {
destY = clipRect.y1;
ddRect.y1 = clipRect.y1 - drawRect.y;
@@ -215,7 +215,7 @@ void Screen::drawSurface2(const Graphics::Surface *surface, NDrawRect &drawRect,
destY = drawRect.y;
ddRect.y1 = 0;
}
-
+
queueBlit(surface, destX, destY, ddRect, transparent, version, shadowSurface);
}
@@ -224,12 +224,12 @@ void Screen::drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, ND
int16 destX, destY;
NRect ddRect;
-
+
if (x + drawRect.width >= clipRect.x2)
ddRect.x2 = clipRect.x2 - drawRect.x - x;
else
ddRect.x2 = drawRect.x + drawRect.width;
-
+
if (x < clipRect.x1) {
destX = clipRect.x1;
ddRect.x1 = clipRect.x1 + drawRect.x - x;
@@ -242,7 +242,7 @@ void Screen::drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, ND
ddRect.y2 = clipRect.y2 + drawRect.y - y;
else
ddRect.y2 = drawRect.y + drawRect.height;
-
+
if (y < clipRect.y1) {
destY = clipRect.y1;
ddRect.y1 = clipRect.y1 + drawRect.y - y;
@@ -250,7 +250,7 @@ void Screen::drawSurface3(const Graphics::Surface *surface, int16 x, int16 y, ND
destY = y;
ddRect.y1 = drawRect.y;
}
-
+
queueBlit(surface, destX, destY, ddRect, transparent, version);
}
@@ -270,13 +270,13 @@ void Screen::drawDoubleSurface2(const Graphics::Surface *surface, NDrawRect &dra
dest += _backScreen->pitch;
dest += _backScreen->pitch;
}
-
+
_fullRefresh = true; // See Screen::update
}
void Screen::drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDrawRect &sysRect, NRect &clipRect, bool transparent, byte version) {
-
+
int16 x, y;
bool xflag, yflag;
NDrawRect newDrawRect;
@@ -292,26 +292,26 @@ void Screen::drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDra
y = y % sysRect.height;
if (y < 0)
y += sysRect.height;
-
+
xflag = x <= 0;
yflag = y <= 0;
-
+
newDrawRect.x = x;
newDrawRect.width = sysRect.width - x;
if (drawRect.width < newDrawRect.width) {
xflag = true;
newDrawRect.width = drawRect.width;
}
-
+
newDrawRect.y = y;
newDrawRect.height = sysRect.height - y;
if (drawRect.height < newDrawRect.height) {
yflag = true;
newDrawRect.height = drawRect.height;
}
-
+
drawSurface3(surface, drawRect.x, drawRect.y, newDrawRect, clipRect, transparent, version);
-
+
if (!xflag) {
newDrawRect.x = 0;
newDrawRect.y = y;
@@ -321,7 +321,7 @@ void Screen::drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDra
newDrawRect.height = drawRect.height;
drawSurface3(surface, sysRect.width + drawRect.x - x, drawRect.y, newDrawRect, clipRect, transparent, version);
}
-
+
if (!yflag) {
newDrawRect.x = x;
newDrawRect.y = 0;
@@ -331,7 +331,7 @@ void Screen::drawUnk(const Graphics::Surface *surface, NDrawRect &drawRect, NDra
newDrawRect.width = drawRect.width;
drawSurface3(surface, drawRect.x, sysRect.height + drawRect.y - y, newDrawRect, clipRect, transparent, version);
}
-
+
if (!xflag && !yflag) {
newDrawRect.x = 0;
newDrawRect.y = 0;
@@ -350,13 +350,13 @@ void Screen::drawSurfaceClipRects(const Graphics::Surface *surface, NDrawRect &d
void Screen::queueBlit(const Graphics::Surface *surface, int16 destX, int16 destY, NRect &ddRect, bool transparent, byte version,
const Graphics::Surface *shadowSurface) {
-
+
const int width = ddRect.x2 - ddRect.x1;
const int height = ddRect.y2 - ddRect.y1;
if (width <= 0 || height <= 0)
return;
-
+
RenderItem renderItem;
renderItem._surface = surface;
renderItem._shadowSurface = shadowSurface;
@@ -369,7 +369,7 @@ void Screen::queueBlit(const Graphics::Surface *surface, int16 destX, int16 dest
renderItem._transparent = transparent;
renderItem._version = version;
_renderQueue->push_back(renderItem);
-
+
}
void Screen::blitRenderItem(const RenderItem &renderItem, const Common::Rect &clipRect) {
diff --git a/engines/neverhood/smackerplayer.cpp b/engines/neverhood/smackerplayer.cpp
index 21d8851f48..187939faee 100644
--- a/engines/neverhood/smackerplayer.cpp
+++ b/engines/neverhood/smackerplayer.cpp
@@ -79,22 +79,22 @@ void SmackerDoubleSurface::draw() {
void NeverhoodSmackerDecoder::forceSeekToFrame(uint frame) {
if (!isVideoLoaded())
return;
-
+
if (frame >= getFrameCount())
error("Can't force Smacker seek to invalid frame %d", frame);
-
+
if (_header.audioInfo[0].hasAudio)
error("Can't force Smacker frame seek with audio");
if (!rewind())
error("Failed to rewind");
-
+
SmackerVideoTrack *videoTrack = (SmackerVideoTrack *)getTrack(0);
uint32 offset = 0;
for (uint32 i = 0; i < frame; i++) {
videoTrack->increaseCurFrame();
offset += _frameSizes[i] & ~3;
}
-
+
_fileStream->seek(offset, SEEK_CUR);
}
@@ -124,7 +124,7 @@ SmackerPlayer::~SmackerPlayer() {
void SmackerPlayer::open(uint32 fileHash, bool keepLastFrame) {
debug(0, "SmackerPlayer::open(%08X)", fileHash);
-
+
_fileHash = fileHash;
_keepLastFrame = keepLastFrame;
@@ -136,13 +136,13 @@ void SmackerPlayer::open(uint32 fileHash, bool keepLastFrame) {
_smackerDecoder = new NeverhoodSmackerDecoder();
_smackerDecoder->loadStream(_stream);
-
+
_palette = new Palette(_vm);
_palette->usePalette();
if (!_paused)
_smackerDecoder->start();
-
+
}
void SmackerPlayer::close() {
@@ -212,7 +212,7 @@ void SmackerPlayer::update() {
_videoDone = false;
}
}
-
+
}
void SmackerPlayer::updateFrame() {
@@ -240,7 +240,7 @@ void SmackerPlayer::updateFrame() {
if (_smackerDecoder->hasDirtyPalette())
updatePalette();
-
+
}
void SmackerPlayer::updatePalette() {
diff --git a/engines/neverhood/smackerplayer.h b/engines/neverhood/smackerplayer.h
index f13b653757..dd7199dd6d 100644
--- a/engines/neverhood/smackerplayer.h
+++ b/engines/neverhood/smackerplayer.h
@@ -62,7 +62,7 @@ public:
void close();
void gotoFrame(int frameNumber);
uint32 getFrameCount();
- uint32 getFrameNumber();
+ uint32 getFrameNumber();
uint getStatus();
void setDrawPos(int16 x, int16 y);
void rewind();
diff --git a/engines/neverhood/smackerscene.cpp b/engines/neverhood/smackerscene.cpp
index 115aafe5be..d9d032a3b5 100644
--- a/engines/neverhood/smackerscene.cpp
+++ b/engines/neverhood/smackerscene.cpp
@@ -31,16 +31,16 @@ SmackerScene::SmackerScene(NeverhoodEngine *vm, Module *parentModule, bool doubl
debug(0, "SmackerScene::SmackerScene(%d, %d, %d)", doubleSurface, canSkip, canAbort);
// NOTE: Merged from SmackerScene::init, maybe split again if needed (incl. parameter flags)
-
+
if (getGlobalVar(V_SMACKER_CAN_ABORT)) {
_canSkip = true;
_canAbort = true;
}
-
+
if (!_doubleSurface)
_vm->_screen->clear();
- _fileHash[0] = 0;
+ _fileHash[0] = 0;
_fileHash[1] = 0;
SetUpdateHandler(&SmackerScene::update);
@@ -67,7 +67,7 @@ void SmackerScene::nextVideo() {
debug(0, "SmackerScene::nextVideo()");
_fileHashListIndex++;
-
+
if (_fileHashList && _fileHashList[_fileHashListIndex] != 0) {
uint32 smackerFileHash = _fileHashList[_fileHashListIndex];
ResourceHandle resourceHandle;
diff --git a/engines/neverhood/sound.cpp b/engines/neverhood/sound.cpp
index 46ec8007b0..c3bc3501b5 100644
--- a/engines/neverhood/sound.cpp
+++ b/engines/neverhood/sound.cpp
@@ -35,7 +35,7 @@ SoundResource::~SoundResource() {
unload();
}
-bool SoundResource::isPlaying() {
+bool SoundResource::isPlaying() {
AudioResourceManSoundItem *soundItem = getSoundItem();
return soundItem ? soundItem->isPlaying() : false;
}
@@ -94,7 +94,7 @@ MusicResource::MusicResource(NeverhoodEngine *vm)
bool MusicResource::isPlaying() {
AudioResourceManMusicItem *musicItem = getMusicItem();
- return musicItem && musicItem->isPlaying();
+ return musicItem && musicItem->isPlaying();
}
void MusicResource::load(uint32 fileHash) {
@@ -134,7 +134,7 @@ AudioResourceManMusicItem *MusicResource::getMusicItem() {
MusicItem::MusicItem(NeverhoodEngine *vm, uint32 groupNameHash, uint32 musicFileHash)
: _vm(vm), _musicResource(NULL) {
-
+
_groupNameHash = groupNameHash;
_fileHash = musicFileHash;
_play = false;
@@ -187,7 +187,7 @@ SoundItem::SoundItem(NeverhoodEngine *vm, uint32 groupNameHash, uint32 soundFile
_playOnceAfterRandomCountdown(false), _minCountdown(0), _maxCountdown(0),
_playOnceAfterCountdown(playOnceAfterCountdown), _initialCountdown(initialCountdown),
_playLooping(false), _currCountdown(currCountdown) {
-
+
_soundResource = new SoundResource(vm);
_soundResource->load(soundFileHash);
}
@@ -200,7 +200,7 @@ SoundItem::~SoundItem() {
void SoundItem::setSoundParams(bool playOnceAfterRandomCountdown, int16 minCountdown, int16 maxCountdown,
int16 firstMinCountdown, int16 firstMaxCountdown) {
-
+
_playOnceAfterCountdown = false;
_playLooping = false;
_playOnceAfterRandomCountdown = playOnceAfterRandomCountdown;
@@ -361,7 +361,7 @@ void SoundMan::setSoundVolume(uint32 soundFileHash, int volume) {
}
void SoundMan::update() {
-
+
for (uint i = 0; i < _soundItems.size(); ++i) {
SoundItem *soundItem = _soundItems[i];
if (soundItem)
@@ -456,7 +456,7 @@ void SoundMan::playSoundThree(uint32 groupNameHash, uint32 soundFileHash) {
SoundItem *soundItem = new SoundItem(_vm, groupNameHash, soundFileHash, false, 0, 0, false, _initialCountdown3, false, 0);
_soundIndex3 = addSoundItem(soundItem);
}
-
+
}
void SoundMan::setTwoSoundsPlayFlag(bool playOnceAfterCountdown) {
@@ -530,16 +530,16 @@ NeverhoodAudioStream::~NeverhoodAudioStream() {
int NeverhoodAudioStream::readBuffer(int16 *buffer, const int numSamples) {
int samplesLeft = numSamples;
-
+
while (samplesLeft > 0 && !_endOfData) {
const int maxSamples = MIN<int>(kSampleBufferLength, samplesLeft);
const int bytesToRead = maxSamples * (_isCompressed ? 1 : 2);
int bytesRead = _stream->read(_buffer, bytesToRead);
int samplesRead = bytesRead / (_isCompressed ? 1 : 2);
-
+
samplesLeft -= samplesRead;
-
+
const byte *src = _buffer;
if (_isCompressed) {
while (samplesRead--) {
@@ -694,7 +694,7 @@ void AudioResourceManMusicItem::update() {
_start = false;
_isPlaying = true;
}
-
+
if (_vm->_mixer->isSoundHandleActive(_soundHandle)) {
if (_isFadingIn) {
_fadeVolume += _fadeVolumeStep;
@@ -787,11 +787,11 @@ int16 AudioResourceMan::loadMusic(uint32 fileHash) {
return i;
}
}
-
+
int16 musicIndex = _musicItems.size();
_musicItems.push_back(musicItem);
return musicIndex;
-
+
}
void AudioResourceMan::updateMusic() {
diff --git a/engines/neverhood/sound.h b/engines/neverhood/sound.h
index aa5da284ea..0733346daa 100644
--- a/engines/neverhood/sound.h
+++ b/engines/neverhood/sound.h
@@ -70,7 +70,7 @@ public:
void setVolume(int16 volume);
protected:
NeverhoodEngine *_vm;
- int16 _musicIndex;
+ int16 _musicIndex;
AudioResourceManMusicItem *getMusicItem();
};
@@ -83,7 +83,7 @@ public:
void update();
uint32 getGroupNameHash() const { return _groupNameHash; }
uint32 getFileHash() const { return _fileHash; }
-protected:
+protected:
NeverhoodEngine *_vm;
uint32 _groupNameHash;
uint32 _fileHash;
@@ -110,7 +110,7 @@ public:
uint32 getGroupNameHash() const { return _groupNameHash; }
uint32 getFileHash() const { return _fileHash; }
int16 getCurrCountdown() const { return _currCountdown; }
-protected:
+protected:
NeverhoodEngine *_vm;
uint32 _groupNameHash;
uint32 _fileHash;
@@ -136,7 +136,7 @@ public:
void deleteMusic(uint32 musicFileHash);
void startMusic(uint32 musicFileHash, int16 countdown, int16 fadeVolumeStep);
void stopMusic(uint32 musicFileHash, int16 countdown, int16 fadeVolumeStep);
-
+
// Sound
void addSound(uint32 groupNameHash, uint32 soundFileHash);
void addSoundList(uint32 groupNameHash, const uint32 *soundFileHashList);
@@ -148,7 +148,7 @@ public:
void playSoundLooping(uint32 soundFileHash);
void stopSound(uint32 soundFileHash);
void setSoundVolume(uint32 soundFileHash, int volume);
-
+
// Misc
void update();
void deleteGroup(uint32 groupNameHash);
@@ -161,25 +161,25 @@ public:
protected:
NeverhoodEngine *_vm;
-
+
// TODO Find out what these special sounds are used for (door sounds?)
int _soundIndex1, _soundIndex2;
int16 _initialCountdown;
bool _playOnceAfterCountdown;
-
+
int _soundIndex3;
int16 _initialCountdown3;
bool _playOnceAfterCountdown3;
Common::Array<MusicItem*> _musicItems;
Common::Array<SoundItem*> _soundItems;
-
+
MusicItem *getMusicItemByHash(uint32 musicFileHash);
SoundItem *getSoundItemByHash(uint32 soundFileHash);
int16 addMusicItem(MusicItem *musicItem);
int16 addSoundItem(SoundItem *soundItem);
void deleteSoundByIndex(int index);
-
+
};
class NeverhoodAudioStream : public Audio::AudioStream {
@@ -209,7 +209,7 @@ private:
// TODO Rename these
class AudioResourceManSoundItem {
-public:
+public:
AudioResourceManSoundItem(NeverhoodEngine *vm, uint32 fileHash);
void loadSound();
void unloadSound();
@@ -218,7 +218,7 @@ public:
void playSound(bool looping);
void stopSound();
bool isPlaying();
-protected:
+protected:
NeverhoodEngine *_vm;
uint32 _fileHash;
ResourceHandle _resourceHandle;
@@ -243,7 +243,7 @@ public:
bool canRestart() const { return _canRestart; }
bool isTerminated() const { return _terminate; }
uint32 getFileHash() const { return _fileHash; }
-protected:
+protected:
NeverhoodEngine *_vm;
uint32 _fileHash;
bool _isPlaying;
@@ -263,7 +263,7 @@ class AudioResourceMan {
public:
AudioResourceMan(NeverhoodEngine *vm);
~AudioResourceMan();
-
+
void stopAllSounds();
int16 addSound(uint32 fileHash);
@@ -271,10 +271,10 @@ public:
int16 loadMusic(uint32 fileHash);
void updateMusic();
-
+
AudioResourceManSoundItem *getSoundItem(int16 index);
AudioResourceManMusicItem *getMusicItem(int16 index);
-
+
protected:
NeverhoodEngine *_vm;
diff --git a/engines/neverhood/sprite.cpp b/engines/neverhood/sprite.cpp
index 50880089f9..3c158ff7e3 100644
--- a/engines/neverhood/sprite.cpp
+++ b/engines/neverhood/sprite.cpp
@@ -28,11 +28,11 @@ namespace Neverhood {
// Sprite
Sprite::Sprite(NeverhoodEngine *vm, int objectPriority)
- : Entity(vm, objectPriority), _x(0), _y(0), _spriteUpdateCb(NULL), _filterXCb(NULL), _filterYCb(NULL),
+ : Entity(vm, objectPriority), _x(0), _y(0), _spriteUpdateCb(NULL), _filterXCb(NULL), _filterYCb(NULL),
_dataResource(vm), _doDeltaX(false), _doDeltaY(false), _needRefresh(false), _flags(0), _surface(NULL) {
SetMessageHandler(&Sprite::handleMessage);
-
+
}
Sprite::~Sprite() {
@@ -71,7 +71,7 @@ bool Sprite::isPointInside(int16 x, int16 y) {
}
bool Sprite::checkCollision(NRect &rect) {
- return (_collisionBounds.x1 < rect.x2) && (rect.x1 < _collisionBounds.x2) && (_collisionBounds.y1 < rect.y2) && (rect.y1 < _collisionBounds.y2);
+ return (_collisionBounds.x1 < rect.x2) && (rect.x1 < _collisionBounds.x2) && (_collisionBounds.y1 < rect.y2) && (rect.y1 < _collisionBounds.y2);
}
uint32 Sprite::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -153,13 +153,13 @@ void StaticSprite::updatePosition() {
if (!_surface)
return;
-
+
if (_doDeltaX) {
_surface->getDrawRect().x = filterX(_x - _drawOffset.x - _drawOffset.width + 1);
} else {
_surface->getDrawRect().x = filterX(_x + _drawOffset.x);
}
-
+
if (_doDeltaY) {
_surface->getDrawRect().y = filterY(_y - _drawOffset.y - _drawOffset.height + 1);
} else {
@@ -261,7 +261,7 @@ void AnimatedSprite::updateAnim() {
}
if (_newAnimFileHash == 0 && _currFrameIndex != _currStickFrameIndex) {
if (_currFrameTicks != 0 && (--_currFrameTicks == 0) && _animResource.getFrameCount() != 0) {
-
+
if (_nextAnimFileHash != 0) {
if (_animResource.load(_nextAnimFileHash)) {
_currAnimFileHash = _nextAnimFileHash;
@@ -270,7 +270,7 @@ void AnimatedSprite::updateAnim() {
_currAnimFileHash = 0;
}
if (_replOldColor != _replNewColor) {
- _animResource.setRepl(_replOldColor, _replNewColor);
+ _animResource.setRepl(_replOldColor, _replNewColor);
}
_nextAnimFileHash = 0;
if (_animStatus != 0) {
@@ -278,17 +278,17 @@ void AnimatedSprite::updateAnim() {
_lastFrameIndex = _plLastFrameHash != 0 ? MAX<int16>(0, _animResource.getFrameIndex(_plLastFrameHash)) : _animResource.getFrameCount() - 1;
} else {
_currFrameIndex = _plFirstFrameIndex != -1 ? _plFirstFrameIndex : _animResource.getFrameCount() - 1;
- _lastFrameIndex = _plLastFrameIndex != -1 ? _plLastFrameIndex : _animResource.getFrameCount() - 1;
+ _lastFrameIndex = _plLastFrameIndex != -1 ? _plLastFrameIndex : _animResource.getFrameCount() - 1;
}
} else {
updateFrameIndex();
}
if (_newAnimFileHash == 0)
updateFrameInfo();
- }
+ }
}
}
-
+
if (_newAnimFileHash != 0) {
if (_animStatus == 2) {
_currStickFrameIndex = _currFrameIndex;
@@ -301,7 +301,7 @@ void AnimatedSprite::updateAnim() {
_currAnimFileHash = 0;
}
if (_replOldColor != _replNewColor) {
- _animResource.setRepl(_replOldColor, _replNewColor);
+ _animResource.setRepl(_replOldColor, _replNewColor);
}
_newAnimFileHash = 0;
_currFrameIndex = _plFirstFrameHash != 0 ? MAX<int16>(0, _animResource.getFrameIndex(_plFirstFrameHash)) : 0;
@@ -314,7 +314,7 @@ void AnimatedSprite::updateAnim() {
_currAnimFileHash = 0;
}
if (_replOldColor != _replNewColor) {
- _animResource.setRepl(_replOldColor, _replNewColor);
+ _animResource.setRepl(_replOldColor, _replNewColor);
}
_newAnimFileHash = 0;
_currFrameIndex = _plFirstFrameIndex != -1 ? _plFirstFrameIndex : _animResource.getFrameCount() - 1;
diff --git a/engines/neverhood/staticdata.cpp b/engines/neverhood/staticdata.cpp
index 3f89c2236f..006992641a 100644
--- a/engines/neverhood/staticdata.cpp
+++ b/engines/neverhood/staticdata.cpp
@@ -33,13 +33,13 @@ StaticData::~StaticData() {
void StaticData::load(const char *filename) {
Common::File fd;
-
+
if (!fd.open(filename))
error("StaticData::load() Could not open %s", filename);
-
- fd.readUint32LE(); // magic
+
+ fd.readUint32LE(); // magic
fd.readUint32LE(); // version
-
+
// Load message lists
uint32 messageListsCount = fd.readUint32LE();
debug(3, "messageListsCount: %d", messageListsCount);
@@ -84,7 +84,7 @@ void StaticData::load(const char *filename) {
}
_rectLists[id] = rectList;
}
-
+
// Load hit rects
uint32 hitRectListsCount = fd.readUint32LE();
debug(3, "hitRectListsCount: %d", hitRectListsCount);
diff --git a/engines/neverhood/todo.txt b/engines/neverhood/todo.txt
deleted file mode 100644
index 9d781e06ec..0000000000
--- a/engines/neverhood/todo.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-NOTE:
--------
-Some of the TODOs should be done AFTER the whole game logic is implemented
-else the game disasm and reimplemtation code become even more different
-(unless I decide it's ok to do it :)
-
-TODOs which can be done any time:
------------------------------------
-- Cleanup
-- Clean up staticdata structs to look more like the ones in create_neverhood
- (e.g. by using template classes etc.)
- - Or use a common base class and manage all stuff in one single table and cast stuff accordingly
-
-TODOs which should be done only after the game logic is finished:
--------------------------------------------------------------------
-- Maybe rework organization of files (e.g. put ALL Sprites into one separate file, same with Modules and Scenes)
- - This would solve the problem of how to organize stuff which is used several times, and less headers would have to be included
- - The move special scenes (SmackerScene) into the scenes file
-
-DONE:
--------
-- Implement game menus
-- Rework sound system (I don't like that SoundResources need to be explicitly initialized in Scene constructors)
- - Should be just a handle object which initializes itself
- - Play routine should fill the handle so it can be stopped/queried later
- - Basically like ScummVM own sound handles
-- RE and implement yet unknown music/sound stuff
-- Implement clever sprite redrawing code (dirty rectangles, microtiles etc.), only redraw what's neccessary
-- Rework the resource system
- - The current system can be simplified a lot
- - Also resource purging needs to be implemented
-- Maybe merge CollisionMan with Scene (since it's so far never used independently)
-- Give placeholder stuff (e.g. sub?????, _flag??? etc.) better fitting names
-- Use CursorMan for the mouse cursor (instead of using it like a normal sprite)
- - This whould make it neccessary to call _system->updateScreen more often else
- the mouse movement would be choppy
-
-TODOs which are experimental:
--------------------------------
-NOTE: Since they affect the whole game, they really should be only implemented once the full game logic is implemented.
-These are nothing more than wild ideas for now, any might never be implemented.
-- Use states instead of separate callback methods
-- Try to move more stuff to neverhood.dat
-- Try to use more template functions instead of manually creating functions
- (Can be coupled with the above to move parameters to the dat and only use IDs)
diff --git a/engines/pegasus/neighborhood/neighborhood.cpp b/engines/pegasus/neighborhood/neighborhood.cpp
index 38366c4ba2..3116bd7978 100644
--- a/engines/pegasus/neighborhood/neighborhood.cpp
+++ b/engines/pegasus/neighborhood/neighborhood.cpp
@@ -1364,7 +1364,7 @@ void Neighborhood::setUpAIRules() {
if (g_AIArea) {
g_AIArea->forceAIUnlocked();
- if (!_vm->isDemo() && (getObjectID() == kPrehistoricID || getObjectID() == kNoradAlphaID ||
+ if (!_vm->isOldDemo() && (getObjectID() == kPrehistoricID || getObjectID() == kNoradAlphaID ||
getObjectID() == kNoradDeltaID || getObjectID() == kMarsID || getObjectID() == kWSCID)) {
AIEnergyMonitorCondition *condition50 = new AIEnergyMonitorCondition(kWorriedEnergy);
diff --git a/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp b/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
index 169f75f7d2..3491f161c7 100644
--- a/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
+++ b/engines/pegasus/neighborhood/norad/alpha/fillingstation.cpp
@@ -201,7 +201,7 @@ void NoradAlphaFillingStation::showIntakeInProgress(uint16 numSeconds) {
if (item->getObjectID() == kGasCanister) {
GameState.setNoradGassed(true);
- ((NoradAlpha *)getOwner())->loadAmbientLoops();
+ ((NoradAlpha *)getOwner())->checkAirMask();
getOwner()->restoreStriding(kNorad03, kEast, kAltNoradAlphaNormal);
}
} else {
diff --git a/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp b/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
index e4a5e26473..6a24113465 100644
--- a/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
+++ b/engines/pegasus/neighborhood/norad/alpha/noradalpha.cpp
@@ -576,7 +576,7 @@ void NoradAlpha::takeItemFromRoom(Item *item) {
if (_fillingStationItem == item) {
_fillingStationItem = 0;
GameState.setNoradGassed(false);
- loadAmbientLoops();
+ checkAirMask();
((NoradAlphaFillingStation *)_currentInteraction)->newFillingItem(0);
forceStridingStop(kNorad03, kEast, kAltNoradAlphaNormal);
}
diff --git a/engines/pegasus/neighborhood/norad/norad.cpp b/engines/pegasus/neighborhood/norad/norad.cpp
index 578f062dea..53b3ff9add 100644
--- a/engines/pegasus/neighborhood/norad/norad.cpp
+++ b/engines/pegasus/neighborhood/norad/norad.cpp
@@ -241,7 +241,9 @@ void Norad::setUpAirMask() {
}
void Norad::checkAirMask() {
- if (g_airMask && g_airMask->isAirFilterOn()) {
+ // WORKAROUND: The original game forgot to handle the case where the canister would
+ // be removed, leading to the timer remaining active.
+ if (!GameState.getNoradGassed() || (g_airMask && g_airMask->isAirFilterOn())) {
_airMaskTimer.stop();
} else if (GameState.getNoradGassed() && !_airMaskTimer.isRunning()) {
_airMaskTimer.setTime(0);
diff --git a/engines/pegasus/timers.cpp b/engines/pegasus/timers.cpp
index 50cc9bc6d8..8463d866e8 100644
--- a/engines/pegasus/timers.cpp
+++ b/engines/pegasus/timers.cpp
@@ -115,7 +115,7 @@ void TimeBase::stop() {
void TimeBase::pause() {
if (isRunning() && !_paused) {
_pausedRate = getRate();
- stop();
+ _rate = 0;
_paused = true;
_pauseStart = g_system->getMillis();
}
@@ -123,7 +123,7 @@ void TimeBase::pause() {
void TimeBase::resume() {
if (_paused) {
- setRate(_pausedRate);
+ _rate = _pausedRate;
_paused = false;
if (isRunning())
diff --git a/engines/plugins_table.h b/engines/plugins_table.h
index 44979458ca..edc94eb0d3 100644
--- a/engines/plugins_table.h
+++ b/engines/plugins_table.h
@@ -44,6 +44,9 @@ LINK_PLUGIN(HUGO)
#if PLUGIN_ENABLED_STATIC(KYRA)
LINK_PLUGIN(KYRA)
#endif
+#if PLUGIN_ENABLED_STATIC(MORTEVIELLE)
+LINK_PLUGIN(MORTEVIELLE)
+#endif
#if PLUGIN_ENABLED_STATIC(LASTEXPRESS)
LINK_PLUGIN(LASTEXPRESS)
#endif
diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp
index fd602ff4fb..a99bd66e5e 100644
--- a/engines/saga/animation.cpp
+++ b/engines/saga/animation.cpp
@@ -185,7 +185,7 @@ int Anim::playCutaway(int cut, bool fade) {
event.time = (40 / 3) * 1000 / _cutawayList[cut].frameRate;
if (fade)
- eventColumns = _vm->_events->chain(eventColumns, event);
+ _vm->_events->chain(eventColumns, event);
else
_vm->_events->queue(event);
}
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 812d967b9f..3ac89bc2c2 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -364,7 +364,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
// Load MIDI/XMI resource data
if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {
- // Load the external music file for Mac IHNM
+ // Load the external music file for Mac IHNM
_player->playQuickTime(Common::String::format("Music/Music%02x", resourceId), flags & MUSIC_LOOP);
} else {
if (_currentMusicBuffer == &_musicBuffer[1]) {
diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index 49d24753a1..ca843af465 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -249,11 +249,11 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
if (!memcmp(header, "Creative", 8)) {
resourceType = kSoundVOC;
- } else if (!memcmp(header, "RIFF", 4) != 0) {
+ } else if (!memcmp(header, "RIFF", 4)) {
resourceType = kSoundWAV;
- } else if (!memcmp(header, "FORM", 4) != 0) {
+ } else if (!memcmp(header, "FORM", 4)) {
resourceType = kSoundAIFF;
- } else if (!memcmp(header, "ajkg", 4) != 0) {
+ } else if (!memcmp(header, "ajkg", 4)) {
resourceType = kSoundShorten;
}
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index 64793efa6c..3c223bebbe 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -1966,7 +1966,7 @@ static bool isVertexCovered(const Patch &p, unsigned int wi) {
// ---w1--1----p----w2--2----
// ^ \ (inside)
if (wi > p.indexw1 && wi <= p.indexw2)
- return true;
+ return true;
// v / (outside)
// ---w2--2----p----w1--1----
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 15a9f54996..d72b1d1772 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -551,7 +551,7 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) {
// NOTE: To fix a corrupted jar object, type "send Glass_Jar message 52"
// in the debugger.
if (g_sci->getGameId() == GID_PEPPER && func == 0 && argc >= 6 && module == 894 &&
- tuple.noun == 26 && tuple.cond == 0 && tuple.seq == 1 &&
+ tuple.noun == 26 && tuple.cond == 0 && tuple.seq == 1 &&
!s->_msgState->getMessage(module, tuple, NULL_REG))
tuple.verb = 0;
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index bf1ce6da64..ca1ef357ae 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -745,7 +745,7 @@ void GfxFrameout::kernelFrameout() {
// Process global scaling, if needed.
// TODO: Seems like SCI32 always processes global scaling for scaled objects
// TODO: We can only process symmetrical scaling for now (i.e. same value for scaleX/scaleY)
- if ((itemEntry->scaleSignal & kScaleSignalDoScaling32) &&
+ if ((itemEntry->scaleSignal & kScaleSignalDoScaling32) &&
!(itemEntry->scaleSignal & kScaleSignalDisableGlobalScaling32) &&
(itemEntry->scaleX == itemEntry->scaleY) &&
itemEntry->scaleX != 128)
@@ -779,6 +779,14 @@ void GfxFrameout::kernelFrameout() {
_coordAdjuster->fromDisplayToScript(nsRect.bottom, nsRect.right);
g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
}
+
+ // TODO: For some reason, the top left nsRect coordinates get
+ // swapped in the GK1 inventory screen, investigate why.
+ // HACK: Fix the coordinates by explicitly setting them here.
+ Common::Rect objNSRect = g_sci->_gfxCompare->getNSRect(itemEntry->object);
+ if (objNSRect.top == nsRect.left && objNSRect.left == nsRect.top && nsRect.top != 0 && nsRect.left != 0) {
+ g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
+ }
}
// Don't attempt to draw sprites that are outside the visible
diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp
index 9546b1503f..9653d9ccff 100644
--- a/engines/sci/sound/midiparser_sci.cpp
+++ b/engines/sci/sound/midiparser_sci.cpp
@@ -57,6 +57,7 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) :
_signalToSet = 0;
_dataincAdd = false;
_dataincToAdd = 0;
+ _jumpToHoldTick = false;
_resetOnPause = false;
_pSnd = 0;
}
@@ -452,6 +453,10 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
debugC(4, kDebugLevelSound, "signal %04x", _signalToSet);
}
+ if (_jumpToHoldTick) {
+ _jumpToHoldTick = false;
+ jumpToTick(_loopTick, false, false);
+ }
info.start = _position._playPos;
info.delta = 0;
@@ -486,6 +491,10 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
// though, so ignoring these signals in SCI0 games will result
// in glitches (e.g. the intro of LB1 Amiga gets stuck - bug
// #3297883). Refer to MusicEntry::setSignal() in sound/music.cpp.
+ // FIXME: SSCI doesn't start playing at the very beginning
+ // of the stream, but at a fixed location a few commands later.
+ // That is probably why this signal isn't triggered
+ // immediately there.
if (_soundVersion <= SCI_VERSION_0_LATE ||
_position._playTick || info.delta) {
_signalSet = true;
@@ -531,10 +540,15 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
// Check if the hold ID marker is the same as the hold ID
// marker set for that song by cmdSetSoundHold.
// If it is, loop back, but don't stop notes when jumping.
+ // We need to wait for the delta of the current event before
+ // jumping, thus the jump will be performed on the next
+ // parseNextEvent() call, like with the signal set events.
+ // In LSL6, room 360, song 381, this ends up jumping forward
+ // one tick (the hold marker occurs at playtick 27, with
+ // _loopTick being 15 and the event itself having a delta of
+ // 13, total = 28) - bug #3614566.
if (info.basic.param2 == _pSnd->hold) {
- uint32 extraDelta = info.delta;
- jumpToTick(_loopTick, false, false);
- _nextEvent.delta += extraDelta;
+ _jumpToHoldTick = true;
}
break;
case kUpdateCue:
@@ -637,7 +651,14 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
// (e.g. song 110, during the intro). The original interpreter
// treats this case as an infinite loop (bug #3311911).
if (_pSnd->loop || _pSnd->hold > 0) {
- // We need to play it again...
+ // TODO: this jump is also vulnerable to the same lockup as
+ // the MIDI hold one above. However, we can't perform the
+ // jump on the next tick like with the MIDI hold jump above,
+ // as there aren't any subsequent MIDI events after this one.
+ // This assert is here to detect cases where the song ends
+ // up jumping forward, like with bug #3614566 (see above).
+ assert(_loopTick + info.delta < _position._playTick);
+
uint32 extraDelta = info.delta;
jumpToTick(_loopTick);
_nextEvent.delta += extraDelta;
diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h
index d3fd337644..7bd68994c8 100644
--- a/engines/sci/sound/midiparser_sci.h
+++ b/engines/sci/sound/midiparser_sci.h
@@ -110,6 +110,7 @@ protected:
int16 _signalToSet;
bool _dataincAdd;
int16 _dataincToAdd;
+ bool _jumpToHoldTick;
bool _resetOnPause;
bool _channelUsed[16];
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index cb807997e9..395051d2a5 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -758,6 +758,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "pajama2", "PYJAMADB", kGenHEPC, Common::DE_DEU, UNK, 0 },
{ "pajama2", "PyjamaDBMN", kGenHEPC, Common::DE_DEU, UNK, 0 },
{ "pajama2", "PyjamaDBMN", kGenHEMac, Common::DE_DEU, Common::kPlatformMacintosh, 0 },
+ { "pajama2", "PyjamaHM", kGenHEPC, Common::FR_FRA, UNK, 0 },
{ "pajama2", "PyjamaHM", kGenHEMac, Common::FR_FRA, Common::kPlatformMacintosh, 0 },
{ "pajama2", "PYJAMA2", kGenHEPC, Common::DE_DEU, UNK, 0 },
{ "pajama2", "Pyjama Pit 2", kGenHEMac, Common::DE_DEU, Common::kPlatformMacintosh, 0 },
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp
index 12ebfef9b7..0e96952a48 100644
--- a/engines/scumm/imuse/imuse.cpp
+++ b/engines/scumm/imuse/imuse.cpp
@@ -1483,7 +1483,7 @@ void IMuseInternal::initMT32(MidiDriver *midi) {
}
void IMuseInternal::initGM(MidiDriver *midi) {
- byte buffer[11];
+ byte buffer[12];
int i;
// General MIDI System On message
@@ -1509,7 +1509,7 @@ void IMuseInternal::initGM(MidiDriver *midi) {
midi->sysEx(buffer, 9);
debug(2, "GS SysEx: GS Reset");
_system->delayMillis(200);
-
+
// Set global Master Tune to 442.0kHz, as on the MT-32
memcpy(&buffer[4], "\x40\x00\x00\x00\x04\x04\x0F\x29", 8);
midi->sysEx(buffer, 12);
@@ -1540,7 +1540,7 @@ void IMuseInternal::initGM(MidiDriver *midi) {
// Set Channels 1-16 Reverb to 64, which is the
// equivalent of MT-32 default Reverb Level 5
for (i = 0; i < 16; ++i)
- midi->send((64 << 16) | (91 << 8) | (0xB0 | i));
+ midi->send((64 << 16) | (91 << 8) | (0xB0 | i));
debug(2, "GM Controller 91 Change: Channels 1-16 Reverb Level is 64");
// Set Channels 1-16 Pitch Bend Sensitivity to
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index ee2de49475..d1786dfb60 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -535,7 +535,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
openMainMenuDialog(); // Display global main menu
- if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0)
+ if (VAR_SAVELOAD_SCRIPT2 != 0xFF && _currentRoom != 0)
runScript(VAR(VAR_SAVELOAD_SCRIPT2), 0, 0, 0);
} else if (restartKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_F8 && lastKeyHit.hasFlags(0))) {
diff --git a/engines/scumm/insane/insane_enemy.cpp b/engines/scumm/insane/insane_enemy.cpp
index fa6d4264ec..3876966fd1 100644
--- a/engines/scumm/insane/insane_enemy.cpp
+++ b/engines/scumm/insane/insane_enemy.cpp
@@ -1519,8 +1519,6 @@ void Insane::chooseEnemyWeaponAnim(int32 buttons) {
case INV_BOOT:
case INV_HAND:
case INV_DUST:
- _actor[1].act[2].state = 0;
- switchEnemyWeapon();
default:
switchEnemyWeapon();
}
@@ -2437,6 +2435,7 @@ void Insane::actor12Reaction(int32 buttons) {
smlayer_setActorFacing(1, 2, 6, 180);
smlayer_setActorLayer(1, 2, 25);
_actor[1].act[2].state = 103;
+ break;
case 103:
_actor[1].kicking = false;
diff --git a/engines/scumm/player_mac.cpp b/engines/scumm/player_mac.cpp
index c16c85bff3..a60736df5e 100644
--- a/engines/scumm/player_mac.cpp
+++ b/engines/scumm/player_mac.cpp
@@ -289,12 +289,16 @@ uint32 Player_Mac::durationToSamples(uint16 duration) {
// (duration * 473 * _sampleRate) / (4 * 480 * 480)
//
// But that's likely to cause integer overflow, so we do it in two
- // steps and hope that the rounding error won't be noticeable.
+ // steps using bitwise operations to perform
+ // ((duration * 473 * _sampleRate) / 4096) without overflowing,
+ // then divide this by 225
+ // (note that 4 * 480 * 480 == 225 * 4096 == 225 << 12)
//
// The original code is a bit unclear on if it should be 473 or 437,
// but since the comments indicated 473 I'm assuming 437 was a typo.
- uint32 samples = (duration * _sampleRate) / (4 * 480);
- samples = (samples * 473) / 480;
+ uint32 samples = (duration * _sampleRate);
+ samples = (samples >> 12) * 473 + (((samples & 4095) * 473) >> 12);
+ samples = samples / 225;
return samples;
}
diff --git a/engines/scumm/player_v3m.cpp b/engines/scumm/player_v3m.cpp
index 0f222d84fe..bf65ec797f 100644
--- a/engines/scumm/player_v3m.cpp
+++ b/engines/scumm/player_v3m.cpp
@@ -124,7 +124,7 @@ bool Player_V3M::checkMusicAvailable() {
return true;
}
}
-
+
GUI::MessageDialog dialog(_(
"Could not find the 'Loom' Macintosh executable to read the\n"
"instruments from. Music will be disabled."), _("OK"));
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index db8da21bbc..7f0eb41a1e 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Sun Jun 23 22:18:47 2013
+ This file was generated by the md5table tool on Tue Jul 09 01:43:38 2013
DO NOT EDIT MANUALLY!
*/
@@ -328,6 +328,7 @@ static const MD5Table md5table[] = {
{ "73e5ab7dbb9a8061cc6d25df02dbd1e7", "loom", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformDOS },
{ "7410a8ba9795020cd42f171c4320659e", "pajama3", "", "", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "746e88c172a5b7a1ae89ac0ee3ee681a", "freddi", "HE 90", "Updated", -1, Common::RU_RUS, Common::kPlatformWindows },
+ { "7477bc23d0383516c5e310cd8771dcc9", "pajama2", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "74da3494fbe1a7d20213b0afe0954755", "catalog", "HE CUP", "Preview", 10841544, Common::FR_FRA, Common::kPlatformUnknown },
{ "754feb59d3bf86b8a00840df74fd7b26", "freddi3", "", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "75ba23fff4fd63fa446c02864f2a5a4b", "zak", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformDOS },
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index 206bd68b07..79ec060bc1 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -37,7 +37,14 @@
#include "gui/message.h"
+#ifdef USE_MPEG2
+#include "video/avi_decoder.h"
+#endif
+
+#ifdef USE_ZLIB
#include "video/dxa_decoder.h"
+#endif
+
#include "video/psx_decoder.h"
#include "video/smk_decoder.h"
@@ -176,27 +183,26 @@ bool MoviePlayer::load(uint32 id) {
break;
case kVideoDecoderPSX:
filename = Common::String::format("%s.str", (_vm->_systemVars.isDemo) ? sequenceList[id] : sequenceListPSX[id]);
+ break;
+ case kVideoDecoderMP2:
+ filename = Common::String::format("%s.mp2", sequenceList[id]);
+ break;
+ }
- // Need to switch to true color
+ // Need to switch to true color for PSX/MP2 videos
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
initGraphics(g_system->getWidth(), g_system->getHeight(), true, 0);
- // Need to load here in case it fails in which case we'd need
- // to go back to paletted mode
- if (_decoder->loadFile(filename)) {
- _decoder->start();
- return true;
- } else {
+ if (!_decoder->loadFile(filename)) {
+ // Go back to 8bpp color
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
initGraphics(g_system->getWidth(), g_system->getHeight(), true);
- return false;
- }
- break;
- }
- if (!_decoder->loadFile(filename))
return false;
+ }
- // For DXA, also add the external sound file
- if (_decoderType == kVideoDecoderDXA)
+ // For DXA/MP2, also add the external sound file
+ if (_decoderType == kVideoDecoderDXA || _decoderType == kVideoDecoderMP2)
_decoder->addStreamFileTrack(sequenceList[id]);
_decoder->start();
@@ -224,9 +230,9 @@ void MoviePlayer::play() {
}
void MoviePlayer::performPostProcessing(byte *screen) {
- // TODO: We don't support the PSX stream videos yet
+ // TODO: We don't support displaying these in true color yet,
// nor using the PSX fonts to display subtitles.
- if (_vm->isPsx())
+ if (_vm->isPsx() || _decoderType == kVideoDecoderMP2)
return;
if (!_movieTexts.empty()) {
@@ -414,20 +420,19 @@ bool MoviePlayer::playVideo() {
_vm->_system->delayMillis(10);
}
- if (_decoderType == kVideoDecoderPSX) {
- // Need to jump back to paletted color
+ // Need to jump back to paletted color
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
initGraphics(g_system->getWidth(), g_system->getHeight(), true);
- }
return !_vm->shouldQuit() && !skipped;
}
uint32 MoviePlayer::getBlackColor() {
- return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black;
+ return (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black;
}
uint32 MoviePlayer::findTextColor() {
- if (_decoderType == kVideoDecoderPSX) {
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) {
// We're in true color mode, so return the actual colors
switch (_textColor) {
case 1:
@@ -547,9 +552,16 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
filename = Common::String::format("%s.mp2", sequenceList[id]);
if (Common::File::exists(filename)) {
- GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK"));
+#ifdef USE_MPEG2
+ // HACK: Old ScummVM builds ignored the AVI frame rate field and forced the video
+ // to be played back at 12fps.
+ Video::VideoDecoder *aviDecoder = new Video::AVIDecoder(12);
+ return new MoviePlayer(vm, textMan, resMan, system, aviDecoder, kVideoDecoderMP2);
+#else
+ GUI::MessageDialog dialog(_("MPEG-2 cutscenes found but ScummVM has been built without MPEG-2"), _("OK"));
dialog.runModal();
return 0;
+#endif
}
if (!vm->isPsx() || scumm_stricmp(sequenceList[id], "enddemo") != 0) {
diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h
index d0c61f5eb3..2c51a74f71 100644
--- a/engines/sword1/animation.h
+++ b/engines/sword1/animation.h
@@ -41,7 +41,8 @@ namespace Sword1 {
enum DecoderType {
kVideoDecoderDXA = 0,
kVideoDecoderSMK = 1,
- kVideoDecoderPSX = 2
+ kVideoDecoderPSX = 2,
+ kVideoDecoderMP2 = 3
};
class MovieText {
diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 00260f789a..713120ad43 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -42,7 +42,14 @@
#include "gui/message.h"
+#ifdef USE_MPEG2
+#include "video/avi_decoder.h"
+#endif
+
+#ifdef USE_ZLIB
#include "video/dxa_decoder.h"
+#endif
+
#include "video/smk_decoder.h"
#include "video/psx_decoder.h"
@@ -88,26 +95,26 @@ bool MoviePlayer::load(const char *name) {
break;
case kVideoDecoderPSX:
filename = Common::String::format("%s.str", name);
+ break;
+ case kVideoDecoderMP2:
+ filename = Common::String::format("%s.mp2", name);
+ break;
+ }
- // Need to switch to true color
- initGraphics(640, 480, true, 0);
+ // Need to switch to true color for PSX/MP2 videos
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
+ initGraphics(g_system->getWidth(), g_system->getHeight(), true, 0);
- // Need to load here in case it fails in which case we'd need
- // to go back to paletted mode
- if (_decoder->loadFile(filename)) {
- _decoder->start();
- return true;
- } else {
- initGraphics(640, 480, true);
- return false;
- }
- }
+ if (!_decoder->loadFile(filename)) {
+ // Go back to 8bpp color
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
+ initGraphics(g_system->getWidth(), g_system->getHeight(), true);
- if (!_decoder->loadFile(filename))
return false;
+ }
- // For DXA, also add the external sound file
- if (_decoderType == kVideoDecoderDXA)
+ // For DXA/MP2, also add the external sound file
+ if (_decoderType == kVideoDecoderDXA || _decoderType == kVideoDecoderMP2)
_decoder->addStreamFileTrack(name);
_decoder->start();
@@ -136,10 +143,9 @@ void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadI
_vm->_sound->stopSpeech();
}
- if (_decoderType == kVideoDecoderPSX) {
- // Need to jump back to paletted color
+ // Need to jump back to paletted color
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
initGraphics(640, 480, true);
- }
}
void MoviePlayer::openTextObject(uint32 index) {
@@ -378,11 +384,11 @@ bool MoviePlayer::playVideo() {
}
uint32 MoviePlayer::getBlackColor() {
- return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black;
+ return (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black;
}
uint32 MoviePlayer::getWhiteColor() {
- return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0xFF, 0xFF, 0xFF) : _white;
+ return (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) ? g_system->getScreenFormat().RGBToColor(0xFF, 0xFF, 0xFF) : _white;
}
void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
@@ -446,9 +452,16 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system
filename = Common::String::format("%s.mp2", name);
if (Common::File::exists(filename)) {
- GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK"));
+#ifdef USE_MPEG2
+ // HACK: Old ScummVM builds ignored the AVI frame rate field and forced the video
+ // to be played back at 12fps.
+ Video::AVIDecoder *aviDecoder = new Video::AVIDecoder(12);
+ return new MoviePlayer(vm, system, aviDecoder, kVideoDecoderMP2);
+#else
+ GUI::MessageDialog dialog(_("MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"), _("OK"));
dialog.runModal();
return NULL;
+#endif
}
// The demo tries to play some cutscenes that aren't there, so make those warnings more discreet.
diff --git a/engines/sword2/animation.h b/engines/sword2/animation.h
index b2a243b2ca..8669bdc8d8 100644
--- a/engines/sword2/animation.h
+++ b/engines/sword2/animation.h
@@ -40,7 +40,8 @@ namespace Sword2 {
enum DecoderType {
kVideoDecoderDXA = 0,
kVideoDecoderSMK = 1,
- kVideoDecoderPSX = 2
+ kVideoDecoderPSX = 2,
+ kVideoDecoderMP2 = 3
};
struct MovieText {
diff --git a/engines/sword25/gfx/dynamicbitmap.cpp b/engines/sword25/gfx/dynamicbitmap.cpp
index 242508bf85..1f3d2d063d 100644
--- a/engines/sword25/gfx/dynamicbitmap.cpp
+++ b/engines/sword25/gfx/dynamicbitmap.cpp
@@ -53,7 +53,7 @@ DynamicBitmap::DynamicBitmap(InputPersistenceBlock &reader, RenderObjectPtr<Rend
bool DynamicBitmap::createRenderedImage(uint width, uint height) {
bool result = false;
_image.reset(new RenderedImage(width, height, result));
-
+
_originalWidth = _width = width;
_originalHeight = _height = height;
@@ -77,7 +77,7 @@ bool DynamicBitmap::doRender(RectangleList *updateRects) {
// Get the frame buffer object
GraphicEngine *pGfx = Kernel::getInstance()->getGfx();
assert(pGfx);
-
+
// Draw the bitmap
bool result;
if (_scaleFactorX == 1.0f && _scaleFactorY == 1.0f) {
diff --git a/engines/sword25/gfx/image/image.h b/engines/sword25/gfx/image/image.h
index 9d7fc43251..8db54e7c54 100644
--- a/engines/sword25/gfx/image/image.h
+++ b/engines/sword25/gfx/image/image.h
@@ -205,7 +205,7 @@ public:
@brief Returns true, if the content of the BS_Image is allowed to be replaced by call of SetContent().
*/
virtual bool isSetContentAllowed() const = 0;
-
+
virtual bool isSolid() const { return false; }
//@}
diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index c8a6666046..9b8cf2266d 100644
--- a/engines/sword25/gfx/image/renderedimage.cpp
+++ b/engines/sword25/gfx/image/renderedimage.cpp
@@ -41,6 +41,7 @@
#include "sword25/gfx/renderobjectmanager.h"
#include "common/system.h"
+#include "graphics/thumbnail.h"
namespace Sword25 {
@@ -293,7 +294,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
for (RectangleList::iterator it = updateRects->begin(); it != updateRects->end(); ++it) {
const Common::Rect &clipRect = *it;
-
+
int skipLeft = 0, skipTop = 0;
int drawX = posX, drawY = posY;
int drawWidth = img->w;
@@ -305,7 +306,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
drawWidth -= skipLeft;
drawX = clipRect.left;
}
-
+
if (drawY < clipRect.top) {
skipTop = clipRect.top - drawY;
drawHeight -= skipTop;
@@ -314,13 +315,13 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
if (drawX + drawWidth >= clipRect.right)
drawWidth = clipRect.right - drawX;
-
+
if (drawY + drawHeight >= clipRect.bottom)
drawHeight = clipRect.bottom - drawY;
-
+
if ((drawWidth > 0) && (drawHeight > 0)) {
int xp = 0, yp = 0;
-
+
int inStep = 4;
int inoStep = img->pitch;
if (flipping & Image::FLIP_V) {
@@ -329,14 +330,14 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
} else {
xp = skipLeft;
}
-
+
if (flipping & Image::FLIP_H) {
inoStep = -inoStep;
yp = img->h - 1 - skipTop;
} else {
yp = skipTop;
}
-
+
byte *ino = (byte *)img->getBasePtr(xp, yp);
byte *outo = (byte *)_backSurface->getBasePtr(drawX, drawY);
@@ -350,7 +351,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
ino += inoStep;
}
} else
-#endif
+#endif
{
byte *in, *out;
for (int i = 0; i < drawHeight; i++) {
@@ -360,7 +361,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
uint32 pix = *(uint32 *)in;
int a = (pix >> 24) & 0xff;
in += inStep;
-
+
if (ca != 255) {
a = a * ca >> 8;
}
@@ -370,11 +371,11 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
out += 4;
continue;
}
-
+
int b = (pix >> 0) & 0xff;
int g = (pix >> 8) & 0xff;
int r = (pix >> 16) & 0xff;
-
+
if (a == 255) {
#if defined(SCUMM_LITTLE_ENDIAN)
if (cb != 255)
@@ -459,7 +460,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
}
}
-
+
}
if (imgScaled) {
@@ -509,60 +510,4 @@ void RenderedImage::checkForTransparency() {
}
}
-/**
- * Scales a passed surface, creating a new surface with the result
- * @param srcImage Source image to scale
- * @param scaleFactor Scale amount. Must be between 0 and 1.0 (but not zero)
- * @remarks Caller is responsible for freeing the returned surface
- */
-Graphics::Surface *RenderedImage::scale(const Graphics::Surface &srcImage, int xSize, int ySize) {
- Graphics::Surface *s = new Graphics::Surface();
- s->create(xSize, ySize, srcImage.format);
-
- int *horizUsage = scaleLine(xSize, srcImage.w);
- int *vertUsage = scaleLine(ySize, srcImage.h);
-
- // Loop to create scaled version
- for (int yp = 0; yp < ySize; ++yp) {
- const byte *srcP = (const byte *)srcImage.getBasePtr(0, vertUsage[yp]);
- byte *destP = (byte *)s->getBasePtr(0, yp);
-
- for (int xp = 0; xp < xSize; ++xp) {
- const byte *tempSrcP = srcP + (horizUsage[xp] * srcImage.format.bytesPerPixel);
- for (int byteCtr = 0; byteCtr < srcImage.format.bytesPerPixel; ++byteCtr) {
- *destP++ = *tempSrcP++;
- }
- }
- }
-
- // Delete arrays and return surface
- delete[] horizUsage;
- delete[] vertUsage;
- return s;
-}
-
-/**
- * Returns an array indicating which pixels of a source image horizontally or vertically get
- * included in a scaled image
- */
-int *RenderedImage::scaleLine(int size, int srcSize) {
- int scale = 100 * size / srcSize;
- assert(scale > 0);
- int *v = new int[size];
- Common::fill(v, &v[size], 0);
-
- int distCtr = 0;
- int *destP = v;
- for (int distIndex = 0; distIndex < srcSize; ++distIndex) {
- distCtr += scale;
- while (distCtr >= 100) {
- assert(destP < &v[size]);
- *destP++ = distIndex;
- distCtr -= 100;
- }
- }
-
- return v;
-}
-
} // End of namespace Sword25
diff --git a/engines/sword25/gfx/image/renderedimage.h b/engines/sword25/gfx/image/renderedimage.h
index a25b258592..116f97de26 100644
--- a/engines/sword25/gfx/image/renderedimage.h
+++ b/engines/sword25/gfx/image/renderedimage.h
@@ -104,8 +104,6 @@ public:
return true;
}
- static Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize);
-
void setIsTransparent(bool isTransparent) { _isTransparent = isTransparent; }
virtual bool isSolid() const { return !_isTransparent; }
@@ -119,7 +117,6 @@ private:
Graphics::Surface *_backSurface;
void checkForTransparency();
- static int *scaleLine(int size, int srcSize);
};
} // End of namespace Sword25
diff --git a/engines/sword25/gfx/panel.cpp b/engines/sword25/gfx/panel.cpp
index 931b9cdbe7..b9bb8b087d 100644
--- a/engines/sword25/gfx/panel.cpp
+++ b/engines/sword25/gfx/panel.cpp
@@ -84,7 +84,7 @@ bool Panel::doRender(RectangleList *updateRects) {
gfxPtr->fill(&intersectionRect, _color);
}
}
-
+
return true;
}
diff --git a/engines/sword25/gfx/renderobject.cpp b/engines/sword25/gfx/renderobject.cpp
index 807c1eb64b..1dd6f4590f 100644
--- a/engines/sword25/gfx/renderobject.cpp
+++ b/engines/sword25/gfx/renderobject.cpp
@@ -183,7 +183,7 @@ bool RenderObject::updateObjectState() {
// Die Bounding-Box neu berechnen und Update-Regions registrieren.
updateBoxes();
-
+
++_version;
// Änderungen Validieren
diff --git a/engines/sword25/gfx/renderobject.h b/engines/sword25/gfx/renderobject.h
index 7e0334ee88..1116c3284c 100644
--- a/engines/sword25/gfx/renderobject.h
+++ b/engines/sword25/gfx/renderobject.h
@@ -236,7 +236,7 @@ public:
@brief Löscht alle Kinderobjekte.
*/
void deleteAllChildren();
-
+
// Accessor-Methoden
// -----------------
/**
@@ -305,11 +305,11 @@ public:
int getZ() const {
return _z;
}
-
+
int getAbsoluteZ() const {
return _absoluteZ;
}
-
+
/**
@brief Gibt die Breite des Objektes zurück.
*/
@@ -363,11 +363,11 @@ public:
return _handle;
}
- // Get the RenderObjects current version
+ // Get the RenderObjects current version
int getVersion() const {
return _version;
}
-
+
bool isSolid() const {
return _isSolid;
}
@@ -410,7 +410,7 @@ protected:
bool _oldVisible;
static int _nextGlobalVersion;
-
+
int _version;
// This should be set to true if the RenderObject is NOT alpha-blended to optimize drawing
@@ -509,9 +509,9 @@ private:
@brief Berechnet die absolute Position des Objektes.
*/
int calcAbsoluteY() const;
-
+
int calcAbsoluteZ() const;
-
+
/**
@brief Sortiert alle Kinderobjekte nach ihrem Renderang.
*/
diff --git a/engines/sword25/gfx/renderobjectmanager.cpp b/engines/sword25/gfx/renderobjectmanager.cpp
index 994d9367ab..77f944c9e0 100644
--- a/engines/sword25/gfx/renderobjectmanager.cpp
+++ b/engines/sword25/gfx/renderobjectmanager.cpp
@@ -113,7 +113,7 @@ bool RenderObjectManager::render() {
RectangleList *updateRects = _uta->getRectangles();
Common::Array<int> updateRectsMinZ;
-
+
updateRectsMinZ.reserve(updateRects->size());
// Calculate the minimum drawing Z value of each update rectangle
@@ -144,9 +144,9 @@ bool RenderObjectManager::render() {
}
delete updateRects;
-
+
SWAP(_currQueue, _prevQueue);
-
+
return true;
}
diff --git a/engines/sword25/gfx/staticbitmap.cpp b/engines/sword25/gfx/staticbitmap.cpp
index 91b93e8910..bb57fa3a03 100644
--- a/engines/sword25/gfx/staticbitmap.cpp
+++ b/engines/sword25/gfx/staticbitmap.cpp
@@ -71,7 +71,7 @@ bool StaticBitmap::initBitmapResource(const Common::String &filename) {
// RenderObject Eigenschaften aktualisieren
_originalWidth = _width = bitmapPtr->getWidth();
_originalHeight = _height = bitmapPtr->getHeight();
-
+
_isSolid = bitmapPtr->isSolid();
// Bild-Resource freigeben
diff --git a/engines/sword25/util/pluto/pluto.cpp b/engines/sword25/util/pluto/pluto.cpp
index b7f5e30340..b7a8fd3c8b 100644
--- a/engines/sword25/util/pluto/pluto.cpp
+++ b/engines/sword25/util/pluto/pluto.cpp
@@ -1,6 +1,6 @@
/* $Id$ */
-/* Pluto - Heavy-duty persistence for Lua
+/* Tamed Pluto - Heavy-duty persistence for Lua
* Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public
* domain. People making use of this software as part of an application
* are politely requested to email the author at sneftel@gmail.com
@@ -14,11 +14,17 @@
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Instrumented by Stefan Reich (info@luaos.net)
+ * for Mobile Lua (http://luaos.net/pages/mobile-lua.php)
*/
+#include "config.h"
#include "sword25/util/lua/lua.h"
#include "pluto.h"
+#undef TOTEXT
+
#define USE_PDEP
#ifdef USE_PDEP
@@ -42,10 +48,20 @@
#include <string.h>
+/* Define this if you want size_t values to be written in 64-bit
+ (even on 32-bit systems). Should eliminate at least one source of
+ 32/64 bit incompatibility. */
+#define SIZES64
+
/* #define PLUTO_DEBUG */
+#ifdef SIZES64
+#define VERSION "Tamed Pluto 1.0 with SIZES64 flag"
+#else
+#define VERSION "Tamed Pluto 1.0"
+#endif
#ifdef PLUTO_DEBUG
@@ -56,6 +72,23 @@
#define verify(x) { int v = (int)((x)); v=v; lua_assert(v); }
+#define NUMTYPES 9
+static const char* typenames[] = {
+ "nil",
+ "boolean",
+ "lightuserdata",
+ "number",
+ "string",
+ "table",
+ "function",
+ "userdata",
+ "thread"
+};
+
+static int humanReadable = 0;
+#define hrBufSize 200
+static char hrBuf[hrBufSize];
+
typedef struct PersistInfo_t {
lua_State *L;
int counter;
@@ -76,6 +109,77 @@ void printindent(int indent)
}
#endif
+/* lua_Chunkwriter signature: (lua_State *L, const void *p, size_t sz, void *ud).
+ ud is a pointer to the WriterInfo struct (holds the buffer pointer)
+*/
+
+static void pi_write(PersistInfo *pi, const void *p, size_t size, void *ud) {
+ if (humanReadable) {
+ uint i;
+ snprintf(hrBuf, hrBufSize, " pi_write %d ", (int) size);
+ pi->writer(pi->L, hrBuf, strlen(hrBuf), ud);
+ for (i = 0; i < size; i++) {
+ char b = ((char *)p)[i];
+ snprintf(hrBuf, hrBufSize, "%X%X", (b >> 4) & 0xF, b & 0xF);
+ pi->writer(pi->L, hrBuf, strlen(hrBuf), ud);
+ }
+ snprintf(hrBuf, hrBufSize, "\n");
+ pi->writer(pi->L, hrBuf, strlen(hrBuf), ud);
+ } else {
+ pi->writer(pi->L, p, size, ud);
+ }
+#ifdef TOTEXT
+ int i;
+ printf(" pi_write %d ", (int) size);
+ for (i = 0; i < size; i++) {
+ char b = ((char *)p)[i];
+ printf("%X%X", (b >> 4) & 0xF, b & 0xF);
+ }
+ printf("\n");
+#endif
+}
+
+static void hrOut(PersistInfo *pi) {
+ pi->writer(pi->L, hrBuf, strlen(hrBuf), pi->ud);
+}
+
+static void write_size(PersistInfo *pi, size_t *val)
+{
+#ifdef SIZES64
+ int64 longval; /* yeah, you really need long long to get 8 bytes on win32... duh. */
+ longval = *val;
+ pi_write(pi, &longval, 8, pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "write_size64 %ld\n", longval);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("write_size64 %ld\n", longval);
+#endif
+#else
+ pi_write(pi, val, sizeof(size_t), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "write_size %ld\n", *((size_t *)val));
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("write_size %ld\n", *val);
+#endif
+#endif
+}
+
+static void read_size(ZIO *zio, size_t *val)
+{
+#ifdef SIZES64
+ int64 longval;
+ verify(LIF(Z,read)(zio, &longval, 8) == 0);
+ *val = longval;
+#else
+ verify(LIF(Z,read)(zio, val, sizeof(size_t)) == 0);
+#endif
+}
+
+
/* Mutual recursion requires prototype */
static void persist(PersistInfo *pi);
@@ -107,7 +211,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction)
if(defaction) {
{
int zero = 0;
- pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+ pi_write(pi, &zero, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistspecialobject_write_zero\n");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistspecialobject_write_zero\n");
+#endif
}
return 0;
} else {
@@ -127,7 +238,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction)
if(defaction) {
{
int zero = 0;
- pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+ pi_write(pi, &zero, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistspecialobject_write_zero2\n");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistspecialobject_write_zero2\n");
+#endif
}
return 0;
} else {
@@ -143,7 +261,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction)
/* perms reftbl sptbl ... obj */
{
int zero = 0;
- pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+ pi_write(pi, &zero, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistspecialobject_write_zero3\n");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistspecialobject_write_zero3\n");
+#endif
}
return 0;
} else {
@@ -176,7 +301,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction)
/* perms reftbl ... obj mt func */
{
int one = 1;
- pi->writer(pi->L, &one, sizeof(int), pi->ud);
+ pi_write(pi, &one, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistspecialobject_write_one\n");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistspecialobject_write_one\n");
+#endif
}
persist(pi);
/* perms reftbl ... obj mt func */
@@ -187,6 +319,14 @@ static int persistspecialobject(PersistInfo *pi, int defaction)
static void persisttable(PersistInfo *pi)
{
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persisttable\n");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persisttable\n");
+#endif
+
/* perms reftbl ... tbl */
lua_checkstack(pi->L, 3);
if(persistspecialobject(pi, 1)) {
@@ -235,8 +375,15 @@ static void persistuserdata(PersistInfo *pi) {
} else {
/* Use literal persistence */
size_t length = uvalue(getobject(pi->L, -1))->len;
- pi->writer(pi->L, &length, sizeof(size_t), pi->ud);
- pi->writer(pi->L, lua_touserdata(pi->L, -1), length, pi->ud);
+ write_size(pi, &length);
+ pi_write(pi, lua_touserdata(pi->L, -1), length, pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistuserdata %ld\n", (long) length);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistuserdata %ld\n", (long) length);
+#endif
if(!lua_getmetatable(pi->L, -1)) {
/* perms reftbl ... udata */
lua_pushnil(pi->L);
@@ -269,8 +416,8 @@ static void pushproto(lua_State *L, Proto *proto)
#define setuvvalue(L,obj,x) \
{ TValue *i_o=(obj); \
- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUPVAL; \
- checkliveness(G(L),i_o); }
+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUPVAL; \
+ checkliveness(G(L),i_o); }
static void pushupval(lua_State *L, UpVal *upval)
{
@@ -309,7 +456,14 @@ static void persistfunction(PersistInfo *pi)
{
/* We don't really _NEED_ the number of upvals,
* but it'll simplify things a bit */
- pi->writer(pi->L, &cl->l.p->nups, sizeof(lu_byte), pi->ud);
+ pi_write(pi, &cl->l.p->nups, sizeof(lu_byte), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistfunction_number_upvalues %d\n", (int) cl->l.p->nups);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistfunction_number_upvalues %d\n", (int) cl->l.p->nups);
+#endif
}
/* Persist prototype */
{
@@ -401,7 +555,14 @@ static void persistproto(PersistInfo *pi)
/* Persist constant refs */
{
int i;
- pi->writer(pi->L, &p->sizek, sizeof(int), pi->ud);
+ pi_write(pi, &p->sizek, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_sizek %d\n", p->sizek);
+ hrOut(pi);
+ }
+ #ifdef TOTEXT
+ printf("persistproto_sizek %d\n", p->sizek);
+ #endif
for(i=0; i<p->sizek; i++) {
LIF(A,pushobject)(pi->L, &p->k[i]);
/* perms reftbl ... proto const */
@@ -415,7 +576,14 @@ static void persistproto(PersistInfo *pi)
/* serialize inner Proto refs */
{
int i;
- pi->writer(pi->L, &p->sizep, sizeof(int), pi->ud);
+ pi_write(pi, &p->sizep, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_sizep %d\n", p->sizep);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_sizep %d\n", p->sizep);
+#endif
for(i=0; i<p->sizep; i++)
{
pushproto(pi->L, p->p[i]);
@@ -429,14 +597,37 @@ static void persistproto(PersistInfo *pi)
/* Serialize code */
{
- pi->writer(pi->L, &p->sizecode, sizeof(int), pi->ud);
- pi->writer(pi->L, p->code, sizeof(Instruction) * p->sizecode, pi->ud);
+ int len;
+ pi_write(pi, &p->sizecode, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_sizecode %d\n", p->sizecode);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_sizecode %d\n", p->sizecode);
+#endif
+ len = sizeof(Instruction) * p->sizecode;
+ pi_write(pi, p->code, len, pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_code %d\n", len);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_code %d\n", len);
+#endif
}
/* Serialize upvalue names */
{
int i;
- pi->writer(pi->L, &p->sizeupvalues, sizeof(int), pi->ud);
+ pi_write(pi, &p->sizeupvalues, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_upvalues %d\n", p->sizeupvalues);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_upvalues %d\n", p->sizeupvalues);
+#endif
for(i=0; i<p->sizeupvalues; i++)
{
pushstring(pi->L, p->upvalues[i]);
@@ -447,15 +638,36 @@ static void persistproto(PersistInfo *pi)
/* Serialize local variable infos */
{
int i;
- pi->writer(pi->L, &p->sizelocvars, sizeof(int), pi->ud);
+ pi_write(pi, &p->sizelocvars, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_sizelocvars %d\n", p->sizelocvars);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_sizelocvars %d\n", p->sizelocvars);
+#endif
for(i=0; i<p->sizelocvars; i++)
{
pushstring(pi->L, p->locvars[i].varname);
persist(pi);
lua_pop(pi->L, 1);
- pi->writer(pi->L, &p->locvars[i].startpc, sizeof(int), pi->ud);
- pi->writer(pi->L, &p->locvars[i].endpc, sizeof(int), pi->ud);
+ pi_write(pi, &p->locvars[i].startpc, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_startpc %d\n", p->locvars[i].startpc);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_startpc %d\n", p->locvars[i].startpc);
+#endif
+ pi_write(pi, &p->locvars[i].endpc, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_endpc %d\n", p->locvars[i].endpc);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_endpc %d\n", p->locvars[i].endpc);
+#endif
}
}
@@ -466,23 +678,81 @@ static void persistproto(PersistInfo *pi)
/* Serialize line numbers */
{
- pi->writer(pi->L, &p->sizelineinfo, sizeof(int), pi->ud);
+ pi_write(pi, &p->sizelineinfo, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_sizelineinfo %d\n", p->sizelineinfo);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_sizelineinfo %d\n", p->sizelineinfo);
+#endif
if (p->sizelineinfo)
{
- pi->writer(pi->L, p->lineinfo, sizeof(int) * p->sizelineinfo, pi->ud);
+ int len;
+ len = sizeof(int) * p->sizelineinfo;
+ pi_write(pi, p->lineinfo, len, pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_lineinfo %d\n", len);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_lineinfo %d\n", len);
+#endif
}
}
/* Serialize linedefined and lastlinedefined */
- pi->writer(pi->L, &p->linedefined, sizeof(int), pi->ud);
- pi->writer(pi->L, &p->lastlinedefined, sizeof(int), pi->ud);
+ pi_write(pi, &p->linedefined, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_linedefined %d\n", p->linedefined);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_linedefined %d\n", p->linedefined);
+#endif
+ pi_write(pi, &p->lastlinedefined, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_lastlinedefined %d\n", p->lastlinedefined);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_lastlinedefined %d\n", p->lastlinedefined);
+#endif
/* Serialize misc values */
{
- pi->writer(pi->L, &p->nups, sizeof(lu_byte), pi->ud);
- pi->writer(pi->L, &p->numparams, sizeof(lu_byte), pi->ud);
- pi->writer(pi->L, &p->is_vararg, sizeof(lu_byte), pi->ud);
- pi->writer(pi->L, &p->maxstacksize, sizeof(lu_byte), pi->ud);
+ pi_write(pi, &p->nups, sizeof(lu_byte), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_nups %d\n", (int) p->nups);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_nups %d\n", (int) p->nups);
+#endif
+ pi_write(pi, &p->numparams, sizeof(lu_byte), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_numparams %d\n", (int) p->numparams);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_numparams %d\n", (int) p->numparams);
+#endif
+ pi_write(pi, &p->is_vararg, sizeof(lu_byte), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_is_vararg %d\n", (int) p->is_vararg);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_is_vararg %d\n", (int) p->is_vararg);
+#endif
+ pi_write(pi, &p->maxstacksize, sizeof(lu_byte), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistproto_maxstacksize %d\n", (int) p->maxstacksize);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistproto_maxstacksize %d\n", (int) p->maxstacksize);
+#endif
}
/* We do not currently persist upvalue names, local variable names,
* variable lifetimes, line info, or source code. */
@@ -518,7 +788,7 @@ static void persistthread(PersistInfo *pi)
/* Persist the stack */
posremaining = revappendstack(L2, pi->L);
/* perms reftbl ... thr (rev'ed contents of L2) */
- pi->writer(pi->L, &posremaining, sizeof(size_t), pi->ud);
+ write_size(pi, &posremaining);
for(; posremaining > 0; posremaining--) {
persist(pi);
lua_pop(pi->L, 1);
@@ -527,7 +797,7 @@ static void persistthread(PersistInfo *pi)
/* Now, persist the CallInfo stack. */
{
size_t i, numframes = (L2->ci - L2->base_ci) + 1;
- pi->writer(pi->L, &numframes, sizeof(size_t), pi->ud);
+ write_size(pi, &numframes);
for(i=0; i<numframes; i++) {
CallInfo *ci = L2->base_ci + i;
size_t stackbase = ci->base - L2->stack;
@@ -536,11 +806,18 @@ static void persistthread(PersistInfo *pi)
size_t savedpc = (ci != L2->base_ci) ?
ci->savedpc - ci_func(ci)->l.p->code :
0;
- pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud);
- pi->writer(pi->L, &stackfunc, sizeof(size_t), pi->ud);
- pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud);
- pi->writer(pi->L, &ci->nresults, sizeof(int), pi->ud);
- pi->writer(pi->L, &savedpc, sizeof(size_t), pi->ud);
+ write_size(pi, &stackbase);
+ write_size(pi, &stackfunc);
+ write_size(pi, &stacktop);
+ pi_write(pi, &ci->nresults, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistthread %d\n", ci->nresults);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistthread %d\n", ci->nresults);
+#endif
+ write_size(pi, &savedpc);
}
}
@@ -549,10 +826,18 @@ static void persistthread(PersistInfo *pi)
size_t stackbase = L2->base - L2->stack;
size_t stacktop = L2->top - L2->stack;
lua_assert(L2->nCcalls <= 1);
- pi->writer(pi->L, &L2->status, sizeof(lu_byte), pi->ud);
- pi->writer(pi->L, &stackbase, sizeof(size_t), pi->ud);
- pi->writer(pi->L, &stacktop, sizeof(size_t), pi->ud);
- pi->writer(pi->L, &L2->errfunc, sizeof(ptrdiff_t), pi->ud);
+ pi_write(pi, &L2->status, sizeof(lu_byte), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistthread_status %d\n", (int) L2->status);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistthread_status %d\n", (int) L2->status);
+#endif
+ write_size(pi, &stackbase);
+ write_size(pi, &stacktop);
+ pi_write(pi, &L2->errfunc, sizeof(ptrdiff_t), pi->ud);
+ //write_size(pi, (size_t *)&L2->errfunc);
}
/* Finally, record upvalues which need to be reopened */
@@ -573,7 +858,7 @@ static void persistthread(PersistInfo *pi)
lua_pop(pi->L, 1);
/* perms reftbl ... thr */
stackpos = uv->v - L2->stack;
- pi->writer(pi->L, &stackpos, sizeof(size_t), pi->ud);
+ write_size(pi, &stackpos);
}
/* perms reftbl ... thr */
lua_pushnil(pi->L);
@@ -588,26 +873,62 @@ static void persistthread(PersistInfo *pi)
static void persistboolean(PersistInfo *pi)
{
int b = lua_toboolean(pi->L, -1);
- pi->writer(pi->L, &b, sizeof(int), pi->ud);
+ pi_write(pi, &b, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistboolean %d\n", b);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistboolean %d\n", b);
+#endif
}
static void persistlightuserdata(PersistInfo *pi)
{
void *p = lua_touserdata(pi->L, -1);
- pi->writer(pi->L, &p, sizeof(void *), pi->ud);
+ pi_write(pi, &p, sizeof(void *), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistlightuserdata %p\n", p);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistlightuserdata %d\n", (int) p);
+#endif
}
static void persistnumber(PersistInfo *pi)
{
lua_Number n = lua_tonumber(pi->L, -1);
- pi->writer(pi->L, &n, sizeof(lua_Number), pi->ud);
+ pi_write(pi, &n, sizeof(lua_Number), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persistnumber %d (%d)\n", (int) n, (int) sizeof(lua_Number));
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persistnumber %d (%d)\n", (int) n, (int) sizeof(lua_Number));
+#endif
}
static void persiststring(PersistInfo *pi)
{
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persiststring\n");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persiststring\n");
+#endif
size_t length = lua_strlen(pi->L, -1);
- pi->writer(pi->L, &length, sizeof(size_t), pi->ud);
- pi->writer(pi->L, lua_tostring(pi->L, -1), length, pi->ud);
+ write_size(pi, &length);
+ const char* s = lua_tostring(pi->L, -1);
+ pi_write(pi, s, length, pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persiststring %d \"%s\"\n", (int)length, s);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persiststring %d \"%s\"\n", length, s);
+#endif
}
/* Top-level delegating persist function
@@ -630,8 +951,22 @@ static void persist(PersistInfo *pi)
// since size_t is supposedly the same size as a pointer on most
// (modern) architectures.
int ref = (int)(size_t)lua_touserdata(pi->L, -1);
- pi->writer(pi->L, &zero, sizeof(int), pi->ud);
- pi->writer(pi->L, &ref, sizeof(int), pi->ud);
+ pi_write(pi, &zero, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persist_seenobject\n");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persist_seenobject\n");
+#endif
+ pi_write(pi, &ref, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persist_touserdata_ref %d\n", ref);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persist_touserdata_ref %d\n", ref);
+#endif
lua_pop(pi->L, 1);
/* perms reftbl ... obj ref */
#ifdef PLUTO_DEBUG
@@ -647,9 +982,16 @@ static void persist(PersistInfo *pi)
if(lua_isnil(pi->L, -1)) {
int zero = 0;
/* firsttime */
- pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+ pi_write(pi, &zero, sizeof(int), pi->ud);
/* ref */
- pi->writer(pi->L, &zero, sizeof(int), pi->ud);
+ pi_write(pi, &zero, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persist_nil (last 2 lines)\n");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persist_nil (last 2 lines)\n");
+#endif
#ifdef PLUTO_DEBUG
printindent(pi->level);
printf("0 0\n");
@@ -659,7 +1001,14 @@ static void persist(PersistInfo *pi)
{
/* indicate that it's the first time */
int one = 1;
- pi->writer(pi->L, &one, sizeof(int), pi->ud);
+ pi_write(pi, &one, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persist_newobject\n");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persist_newobject\n");
+#endif
}
lua_pushvalue(pi->L, -1);
/* perms reftbl ... obj obj */
@@ -668,7 +1017,14 @@ static void persist(PersistInfo *pi)
lua_rawset(pi->L, 2);
/* perms reftbl ... obj */
- pi->writer(pi->L, &pi->counter, sizeof(int), pi->ud);
+ pi_write(pi, &pi->counter, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persist_counter %d\n", pi->counter);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persist_counter %d\n", pi->counter);
+#endif
/* At this point, we'll give the permanents table a chance to play. */
@@ -685,7 +1041,14 @@ static void persist(PersistInfo *pi)
printf("1 %d PERM\n", pi->counter);
pi->level++;
#endif
- pi->writer(pi->L, &type, sizeof(int), pi->ud);
+ pi_write(pi, &type, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persist_permtype %d\n", type);
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persist_permtype %d\n", type);
+#endif
persist(pi);
lua_pop(pi->L, 1);
/* perms reftbl ... obj */
@@ -702,7 +1065,14 @@ static void persist(PersistInfo *pi)
}
{
int type = lua_type(pi->L, -1);
- pi->writer(pi->L, &type, sizeof(int), pi->ud);
+ pi_write(pi, &type, sizeof(int), pi->ud);
+ if (humanReadable) {
+ snprintf(hrBuf, hrBufSize, "persist %s\n", type >= 0 && type < NUMTYPES ? typenames[type] : "?");
+ hrOut(pi);
+ }
+#ifdef TOTEXT
+ printf("persist %s\n", type >= 0 && type < NUMTYPES ? typenames[type] : "?");
+#endif
#ifdef PLUTO_DEBUG
printindent(pi->level);
@@ -798,8 +1168,8 @@ typedef struct WriterInfo_t {
size_t buflen;
} WriterInfo;
-static int bufwriter (lua_State *L, const void* p, size_t sz, void* ud) {
- const char* cp = (const char*)p;
+static int bufwriter (lua_State *L, const void *p, size_t sz, void *ud) {
+ const char *cp = (const char *)p;
WriterInfo *wi = (WriterInfo *)ud;
LIF(M,reallocvector)(L, wi->buf, wi->buflen, wi->buflen+sz, char);
@@ -819,7 +1189,7 @@ int persist_l(lua_State *L)
wi.buf = NULL;
wi.buflen = 0;
-
+
lua_settop(L, 2);
/* perms? rootobj? */
luaL_checktype(L, 1, LUA_TTABLE);
@@ -895,10 +1265,13 @@ static void unpersistnumber(UnpersistInfo *upi)
static void unpersiststring(UnpersistInfo *upi)
{
/* perms reftbl sptbl ref */
+ /*int length;*/
size_t length;
char* string;
lua_checkstack(upi->L, 1);
- verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0);
+ /*verify(LIF(Z,read)(&upi->zio, &length, sizeof(int)) == 0);*/
+ /*verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0);*/
+ read_size(&upi->zio, &length);
string = pdep_newvector(upi->L, length, char);
verify(LIF(Z,read)(&upi->zio, string, length) == 0);
lua_pushlstring(upi->L, string, length);
@@ -1312,7 +1685,7 @@ static void unpersistthread(int ref, UnpersistInfo *upi)
/* First, deserialize the object stack. */
{
size_t i, stacksize;
- verify(LIF(Z,read)(&upi->zio, &stacksize, sizeof(size_t)) == 0);
+ read_size(&upi->zio, &stacksize);
LIF(D,growstack)(L2, (int)stacksize);
/* Make sure that the first stack element (a nil, representing
* the imaginary top-level C function) is written to the very,
@@ -1331,16 +1704,16 @@ static void unpersistthread(int ref, UnpersistInfo *upi)
/* Now, deserialize the CallInfo stack. */
{
size_t i, numframes;
- verify(LIF(Z,read)(&upi->zio, &numframes, sizeof(size_t)) == 0);
+ read_size(&upi->zio, &numframes);
LIF(D,reallocCI)(L2,numframes*2);
for(i=0; i<numframes; i++) {
CallInfo *ci = L2->base_ci + i;
size_t stackbase, stackfunc, stacktop, savedpc;
- verify(LIF(Z,read)(&upi->zio, &stackbase, sizeof(size_t)) == 0);
- verify(LIF(Z,read)(&upi->zio, &stackfunc, sizeof(size_t)) == 0);
- verify(LIF(Z,read)(&upi->zio, &stacktop, sizeof(size_t)) == 0);
+ read_size(&upi->zio, &stackbase);
+ read_size(&upi->zio, &stackfunc);
+ read_size(&upi->zio, &stacktop);
verify(LIF(Z,read)(&upi->zio, &ci->nresults, sizeof(int)) == 0);
- verify(LIF(Z,read)(&upi->zio, &savedpc, sizeof(size_t)) == 0);
+ read_size(&upi->zio, &savedpc);
if(stacklimit < stacktop)
stacklimit = stacktop;
@@ -1363,9 +1736,10 @@ static void unpersistthread(int ref, UnpersistInfo *upi)
size_t stackbase, stacktop;
L2->savedpc = L2->ci->savedpc;
verify(LIF(Z,read)(&upi->zio, &L2->status, sizeof(lu_byte)) == 0);
- verify(LIF(Z,read)(&upi->zio, &stackbase, sizeof(size_t)) == 0);
- verify(LIF(Z,read)(&upi->zio, &stacktop, sizeof(size_t)) == 0);
+ read_size(&upi->zio, &stackbase);
+ read_size(&upi->zio, &stacktop);
verify(LIF(Z,read)(&upi->zio, &L2->errfunc, sizeof(ptrdiff_t)) == 0);
+ //read_size(&upi->zio, (size_t *)&L2->errfunc);
L2->base = L2->stack + stackbase;
L2->top = L2->stack + stacktop;
}
@@ -1391,7 +1765,7 @@ static void unpersistthread(int ref, UnpersistInfo *upi)
lua_pop(upi->L, 1);
/* perms reftbl ... thr */
- verify(LIF(Z,read)(&upi->zio, &stackpos, sizeof(size_t)) == 0);
+ read_size(&upi->zio, &stackpos);
uv->v = L2->stack + stackpos;
gcunlink(upi->L, (GCObject *)uv);
uv->marked = luaC_white(g);
@@ -1443,7 +1817,7 @@ static void unpersistuserdata(int ref, UnpersistInfo *upi)
/* perms reftbl ... udata */
} else {
size_t length;
- verify(LIF(Z,read)(&upi->zio, &length, sizeof(size_t)) == 0);
+ read_size(&upi->zio, &length);
lua_newuserdata(upi->L, length);
/* perms reftbl ... udata */
@@ -1611,8 +1985,8 @@ void pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
}
typedef struct LoadInfo_t {
- char *buf;
- size_t size;
+ char *buf;
+ size_t size;
} LoadInfo;
@@ -1653,9 +2027,41 @@ int unpersist_l(lua_State *L)
return 1;
}
+/* Stefan's first C function for Lua! :)
+ Returns a string describing the Pluto version you're using. */
+
+int version_l(lua_State *L)
+{
+ const char *version = VERSION;
+
+ lua_settop(L, 0);
+ /* (empty) */
+ lua_pushlstring(L, version, strlen(version));
+ /* str */
+ return 1;
+}
+
+/* Set human-readable output on or off. */
+int human_l(lua_State *L)
+{
+ /* flag? ...? */
+ lua_settop(L, 1);
+ /* flag? */
+ /*luaL_checktype(L, 1, LUA_TBOOLEAN);*/
+ /* flag */
+
+ humanReadable = lua_toboolean(L, 1);
+
+ lua_settop(L, 0);
+ /* (empty) */
+ return 0;
+}
+
static luaL_reg pluto_reg[] = {
{ "persist", persist_l },
{ "unpersist", unpersist_l },
+ { "version", version_l },
+ { "human", human_l },
{ NULL, NULL }
};
diff --git a/engines/teenagent/callbacks.cpp b/engines/teenagent/callbacks.cpp
index 2de81abb37..3e6e40a8fa 100644
--- a/engines/teenagent/callbacks.cpp
+++ b/engines/teenagent/callbacks.cpp
@@ -294,7 +294,7 @@ bool TeenAgentEngine::fnRobotSafeAlreadyUnlockedCheck() {
}
void TeenAgentEngine::fnRobotSafeUnlockCheck() {
- if (CHECK_FLAG(dsAddr_MansionRobotSafeVoiceTestPassedFlag, 1) &&
+ if (CHECK_FLAG(dsAddr_MansionRobotSafeVoiceTestPassedFlag, 1) &&
CHECK_FLAG(dsAddr_MansionRobotSafeScentTestPassedFlag, 1) &&
CHECK_FLAG(dsAddr_MansionRobotSafeViewTestPassedFlag, 1)) {
waitLanAnimationFrame(1, 1);
@@ -546,7 +546,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
break;
case 0x4056:
- // FIXME - This is the bird use callback in the first act at
+ // FIXME - This is the bird use callback in the first act at
// the mudpool. Current Code based on behaviour. Need to analyse cseg data.
dialog->popMark(scene, dsAddr_dialogStackMudpoolBird);
break;
@@ -1603,7 +1603,7 @@ bool TeenAgentEngine::processCallback(uint16 addr) {
break;
case 0x5b44:
- // FIXME - This is the doorbell use callback on House #2
+ // FIXME - This is the doorbell use callback on House #2
// i.e. Granny and Anne's House. Need to analyse cseg data properly.
// Current code inferred from behaviour.
// FIXME - Add animation call for Ego pushing doorbell.
diff --git a/engines/teenagent/dialog.cpp b/engines/teenagent/dialog.cpp
index 870aca6400..312757a462 100644
--- a/engines/teenagent/dialog.cpp
+++ b/engines/teenagent/dialog.cpp
@@ -28,7 +28,7 @@ namespace TeenAgent {
void Dialog::show(uint16 dialogNum, Scene *scene, uint16 animation1, uint16 animation2, byte color1, byte color2, byte slot1, byte slot2) {
uint16 addr = _vm->res->getDialogAddr(dialogNum);
- // WORKAROUND: For Dialog 163, The usage of this in the engine overlaps the previous dialog i.e. the
+ // WORKAROUND: For Dialog 163, The usage of this in the engine overlaps the previous dialog i.e. the
// starting offset used is two bytes early, thus implicitly changing the first command of this dialog
// from NEW_LINE to CHANGE_CHARACTER.
// FIXME: Unsure if this is correct behaviour or if this is a regression from the original. Check this.
diff --git a/engines/teenagent/resources.cpp b/engines/teenagent/resources.cpp
index 442d0abf16..399baf469f 100644
--- a/engines/teenagent/resources.cpp
+++ b/engines/teenagent/resources.cpp
@@ -206,16 +206,19 @@ Common::SeekableReadStream *Resources::loadLan000(uint32 id) const {
if (dseg.get_byte(dsAddr_birdOnBarRadioAntennaFlag) == 1) {
return lan500.getStream(380);
}
+ break;
case 30:
if (dseg.get_byte(dsAddr_birdOnBarRadioAntennaFlag) == 1) {
return lan500.getStream(381);
}
+ break;
case 42:
if (dseg.get_byte(dsAddr_johnNotyOutsideMansionDoorFlag) == 1) {
return lan500.getStream(400);
}
+ break;
}
return lan000.getStream(id);
}
diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp
index 3921414b01..104adf72a2 100644
--- a/engines/tinsel/handle.cpp
+++ b/engines/tinsel/handle.cpp
@@ -300,7 +300,7 @@ void LoadFile(MEMHANDLE *pH) {
// discardable - unlock the memory
MemoryUnlock(pH->_node);
-
+
// set the loaded flag
pH->filesize |= fLoaded;
diff --git a/engines/tinsel/rince.cpp b/engines/tinsel/rince.cpp
index 3e6334f583..49666c13ca 100644
--- a/engines/tinsel/rince.cpp
+++ b/engines/tinsel/rince.cpp
@@ -808,7 +808,8 @@ void T2MoverProcess(CORO_PARAM, const void *param) {
PokeInPalette(pmi);
pMover->actorObj = MultiInitObject(pmi);
- pMover->actorID = pMover->actorID;
+ // FIXME: This is what the original did. A bug, perhaps?
+ // pMover->actorID = pMover->actorID;
pMover->bActive = true;
// add it to display list
diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp
index 17cb23b98f..43654fc3af 100644
--- a/engines/tinsel/scene.cpp
+++ b/engines/tinsel/scene.cpp
@@ -138,7 +138,7 @@ const SCENE_STRUC *GetSceneStruc(const byte *pStruc) {
g_tempStruc.hEntrance = READ_32(p); p += sizeof(uint32);
g_tempStruc.hPoly = READ_32(p); p += sizeof(uint32);
g_tempStruc.hTaggedActor = READ_32(p); p += sizeof(uint32);
-
+
return &g_tempStruc;
}
diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp
index dc82c78ee5..410f9b8971 100644
--- a/engines/tony/gfxcore.cpp
+++ b/engines/tony/gfxcore.cpp
@@ -1865,7 +1865,7 @@ void RMGfxSourceBuffer8RLEWordAA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RM
CORO_END_CODE;
}
-int RMGfxSourceBuffer8RLEWordAA::init(byte *buf, int dimx, int dimy, bool bLoadPalette) {
+int RMGfxSourceBuffer8RLEWordAA::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
return RMGfxSourceBuffer8RLE::init(buf, dimx, dimy, bLoadPalette);
}
diff --git a/engines/tony/gfxcore.h b/engines/tony/gfxcore.h
index 1bacf7e5a9..2548968e81 100644
--- a/engines/tony/gfxcore.h
+++ b/engines/tony/gfxcore.h
@@ -408,7 +408,7 @@ public:
// Overloaded initialization methods
virtual void init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette = false);
- virtual int init(byte *buf, int dimx, int dimy, bool bLoadPalette = false);
+ virtual int init(const byte *buf, int dimx, int dimy, bool bLoadPalette = false);
virtual ~RMGfxSourceBuffer8RLEWordAA();
};
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index 479f4965f3..83c9e3ec70 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -58,6 +58,7 @@ Character::Character(ToonEngine *vm) : _vm(vm) {
_animSpecialDefaultId = 0;
_currentPathNode = 0;
_currentWalkStamp = 0;
+ _currentFacingStamp = 0;
_visible = true;
_speed = 150; // 150 = nominal drew speed
_lastWalkTime = 0;
@@ -99,6 +100,9 @@ void Character::setFacing(int32 facing) {
if (_blockingWalk) {
_flags |= 2;
+ _currentFacingStamp++;
+ int32 localFacingStamp = _currentFacingStamp;
+
int32 dir = 0;
_lastWalkTime = _vm->_system->getMillis();
@@ -127,6 +131,11 @@ void Character::setFacing(int32 facing) {
else
playWalkAnim(0, 0);
_vm->doFrame();
+
+ if (_currentFacingStamp != localFacingStamp) {
+ // another setFacing was started in doFrame, we need to cancel this one.
+ return;
+ }
};
_flags &= ~2;
diff --git a/engines/toon/character.h b/engines/toon/character.h
index d33c314bf7..b248e7ccf2 100644
--- a/engines/toon/character.h
+++ b/engines/toon/character.h
@@ -143,6 +143,7 @@ protected:
Common::Array<Common::Point> _currentPath;
uint32 _currentPathNode;
int32 _currentWalkStamp;
+ int32 _currentFacingStamp;
};
} // End of namespace Toon
diff --git a/engines/tsage/converse.cpp b/engines/tsage/converse.cpp
index de5ac62425..753a835389 100644
--- a/engines/tsage/converse.cpp
+++ b/engines/tsage/converse.cpp
@@ -416,7 +416,7 @@ SequenceManager *SequenceManager::globalManager() {
ConversationChoiceDialog::ConversationChoiceDialog() {
_stdColor = 23;
_highlightColor = g_globals->_scenePalette._colors.background;
- _fontNumber = 1;
+ _fontNumber = (g_vm->getGameID() == GType_Ringworld2) ? 3 : 1;
_savedFgColor = _savedFontNumber = 0;
_selectedIndex = 0;
}
@@ -424,15 +424,15 @@ ConversationChoiceDialog::ConversationChoiceDialog() {
int ConversationChoiceDialog::execute(const Common::StringArray &choiceList) {
_gfxManager._font.setFontNumber(_fontNumber);
- _bounds = Rect(20, 0, 20, 0);
+ _bounds = Rect(40, 0, 40, 0);
_choiceList.clear();
// Set up the list of choices
int yp = 0;
for (uint idx = 0; idx < choiceList.size(); ++idx) {
Rect tempRect;
- _gfxManager._font.getStringBounds(choiceList[idx].c_str(), tempRect, 265);
- tempRect.moveTo(25, yp + 10);
+ _gfxManager._font.getStringBounds(choiceList[idx].c_str(), tempRect, textMaxWidth());
+ tempRect.moveTo(textLeft(), yp + 10);
_choiceList.push_back(ChoiceEntry(choiceList[idx], tempRect));
yp += tempRect.height() + 5;
@@ -444,7 +444,8 @@ int ConversationChoiceDialog::execute(const Common::StringArray &choiceList) {
_bounds.bottom -= 10;
yp = 180 - _bounds.height();
_bounds.translate(0, yp);
- _bounds.right = _bounds.left + 280;
+ _bounds.setWidth(textMaxWidth() + 15);
+ _bounds.moveTo(160 - (_bounds.width() / 2), _bounds.top);
// Draw the dialog
draw();
@@ -513,6 +514,7 @@ void ConversationChoiceDialog::draw() {
// Fill in the contents of the entire dialog
_gfxManager._bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+
drawFrame();
_gfxManager._bounds = tempRect;
@@ -524,7 +526,7 @@ void ConversationChoiceDialog::draw() {
Common::String strNum = Common::String::format("%d", idx + 1);
// Write the choice number
- _gfxManager._font.setPosition(13, _choiceList[idx]._bounds.top);
+ _gfxManager._font.setPosition(numberLeft(), _choiceList[idx]._bounds.top);
_gfxManager._font.writeString(strNum.c_str());
_gfxManager._font.writeLines(_choiceList[idx]._msg.c_str(), _choiceList[idx]._bounds, ALIGN_LEFT);
@@ -533,6 +535,18 @@ void ConversationChoiceDialog::draw() {
_gfxManager.deactivate();
}
+int ConversationChoiceDialog::textLeft() const {
+ return (g_vm->getGameID() == GType_Ringworld2) ? 20 : 25;
+}
+
+int ConversationChoiceDialog::textMaxWidth() const {
+ return (g_vm->getGameID() == GType_Ringworld2) ? 250 : 265;
+}
+
+int ConversationChoiceDialog::numberLeft() const {
+ return (g_vm->getGameID() == GType_Ringworld2) ? 8 : 13;
+}
+
/*--------------------------------------------------------------------------*/
void Obj44::load(const byte *dataP) {
@@ -542,8 +556,8 @@ void Obj44::load(const byte *dataP) {
_mode = s.readSint16LE();
_lookupValue = s.readSint16LE();
_lookupIndex = s.readSint16LE();
- _field6 = s.readSint16LE();
- _field8 = s.readSint16LE();
+ _exitMode = s.readSint16LE();
+ _speakerMode = s.readSint16LE();
}
_id = s.readSint16LE();
@@ -551,8 +565,8 @@ void Obj44::load(const byte *dataP) {
_callbackId[idx] = s.readSint16LE();
if (g_vm->getGameID() == GType_Ringworld2) {
- _field16 = s.readSint16LE();
- s.skip(20);
+ for (int i = 0; i < 11; ++i)
+ _field16[i] = s.readSint16LE();
} else {
s.skip(4);
}
@@ -578,9 +592,11 @@ void Obj44::synchronize(Serializer &s) {
s.syncAsSint16LE(_mode);
s.syncAsSint16LE(_lookupValue);
s.syncAsSint16LE(_lookupIndex);
- s.syncAsSint16LE(_field6);
- s.syncAsSint16LE(_field8);
- s.syncAsSint16LE(_field16);
+ s.syncAsSint16LE(_exitMode);
+ s.syncAsSint16LE(_speakerMode);
+
+ for (int i = 0; i < 11; ++i)
+ s.syncAsSint16LE(_field16[i]);
}
}
@@ -632,6 +648,7 @@ void StripManager::reset() {
_activeSpeaker = NULL;
_textShown = false;
_callbackObject = NULL;
+ _exitMode = 0;
_obj44List.clear();
if (!_script.empty()) {
@@ -679,6 +696,8 @@ void StripManager::synchronize(Serializer &s) {
s.syncAsByte(_textShown);
s.syncAsByte(_field2E6);
s.syncAsSint32LE(_field2E8);
+ if (g_vm->getGameID() == GType_Ringworld2)
+ s.syncAsSint16LE(_exitMode);
// Synchronize the item list
int arrSize = _obj44List.size();
@@ -708,14 +727,24 @@ void StripManager::synchronize(Serializer &s) {
}
void StripManager::remove() {
+ if (g_vm->getGameID() == GType_Ringworld2) {
+ for (uint i = 0; i < _speakerList.size(); ++i) {
+ if (_activeSpeaker != _speakerList[i])
+ _speakerList[i]->proc16();
+ }
+ }
+
if (_textShown) {
if (_activeSpeaker)
_activeSpeaker->removeText();
_textShown = false;
}
- if (_activeSpeaker)
+ if (_activeSpeaker) {
+ if (g_vm->getGameID() == GType_Ringworld2)
+ static_cast<Ringworld2::VisualSpeaker *>(_activeSpeaker)->_speakerMode = 0xff;
_activeSpeaker->remove();
+ }
if (_sceneNumber != g_globals->_sceneManager._scene->_screenNumber) {
g_globals->_sceneManager._scene->_sceneBounds = _sceneBounds;
@@ -729,6 +758,8 @@ void StripManager::remove() {
}
void StripManager::signal() {
+ int strIndex = 0;
+
if (_textShown) {
_activeSpeaker->removeText();
_textShown = false;
@@ -760,12 +791,10 @@ void StripManager::signal() {
Obj44 &obj44 = _obj44List[_obj44Index];
- if (g_vm->getGameID() != GType_Ringworld2) {
- _field2E8 = obj44._id;
- } else {
+ if (g_vm->getGameID() == GType_Ringworld2) {
// Return to Ringworld specific handling
- if (obj44._field6)
- _field2E8 = obj44._field6;
+ if (obj44._exitMode)
+ _exitMode = obj44._exitMode;
switch (obj44._mode) {
case 1:
@@ -781,40 +810,83 @@ void StripManager::signal() {
break;
}
}
-
+
+ _field2E8 = obj44._id;
Common::StringArray choiceList;
// Build up a list of script entries
int idx;
+ bool delayFlag = false;
- if (g_vm->getGameID() == GType_Ringworld2 && obj44._field16) {
+ if ((g_vm->getGameID() == GType_Ringworld2) && obj44._field16[0]) {
// Special loading mode used in Return to Ringworld
for (idx = 0; idx < OBJ44_LIST_SIZE; ++idx) {
- int objIndex = _lookupList[obj44._field16 - 1];
-
- if (!obj44._list[objIndex]._id)
+ int f16Index = _lookupList[obj44._field16[0] - 1];
+ int entryId = obj44._field16[f16Index];
+
+ Obj0A &entry = obj44._list[idx];
+ if (entry._id == entryId) {
+ // Get the next one
+ choiceList.push_back((const char *)&_script[0] + entry._scriptOffset);
+ strIndex = idx;
+ delayFlag = true;
break;
-
- // Get the next one
- choiceList.push_back((const char *)&_script[0] + obj44._list[objIndex]._scriptOffset);
+ }
}
} else {
// Standard choices loading
- for (idx = 0; idx < OBJ44_LIST_SIZE; ++idx) {
+ for (idx = 0; idx < OBJ0A_LIST_SIZE; ++idx) {
if (!obj44._list[idx]._id)
break;
// Get the next one
- choiceList.push_back((const char *)&_script[0] + obj44._list[idx]._scriptOffset);
+ const char *choiceStr = (const char *)&_script[0] + obj44._list[idx]._scriptOffset;
+
+ if (!*choiceStr) {
+ // Choice is empty
+ assert(g_vm->getGameID() == GType_Ringworld2);
+
+ if (obj44._list[1]._id) {
+ // it's a reference to another list slot
+ int listId = obj44._list[idx]._id;
+
+ int obj44Idx = 0;
+ while (_obj44List[obj44Idx]._id != listId)
+ ++obj44Idx;
+
+ if (_obj44List[obj44Idx]._field16[0]) {
+ int f16Index = _lookupList[_obj44List[obj44Idx]._field16[0] - 1];
+ listId = _obj44List[obj44Idx]._field16[f16Index];
+
+ if (_lookupList[_obj44List[obj44Idx]._field16[0] - 1]) {
+ int listIdx = 0;
+ while (_obj44List[obj44Idx]._list[listIdx]._id != listId)
+ ++listIdx;
+
+ choiceStr = (const char *)&_script[0] + _obj44List[obj44Idx]._list[listIdx]._scriptOffset;
+ } else {
+ for (int listIdx = 0; listIdx < OBJ0A_LIST_SIZE; ++listIdx) {
+ obj44._list[listIdx]._id = obj44._list[listIdx + 1]._id;
+ obj44._list[listIdx]._scriptOffset = obj44._list[listIdx + 1]._scriptOffset;
+
+ if (!obj44._list[listIdx + 1]._id)
+ obj44._list[listIdx]._id = 0;
+ }
+ }
+ }
+ }
+ }
+
+ // Add entry to the list
+ choiceList.push_back(choiceStr);
}
}
- int strIndex = 0;
if (choiceList.size() > 1)
// Get the user to select a conversation option
strIndex = _choiceDialog.execute(choiceList);
- if ((choiceList.size() != 1) && !_field2E6)
+ if ((delayFlag || choiceList.size() != 1) && !_field2E6)
_delayFrames = 1;
else {
Speaker *speakerP = getSpeaker((const char *)&_script[0] + obj44._speakerOffset);
@@ -843,11 +915,28 @@ void StripManager::signal() {
}
}
- if ((g_vm->getGameID() == GType_Ringworld2) && (_obj44List.size() > 0))
- static_cast<Ringworld2::VisualSpeaker *>(_activeSpeaker)->proc15();
+ if (g_vm->getGameID() == GType_Ringworld2) {
+ Ringworld2::VisualSpeaker *speaker = static_cast<Ringworld2::VisualSpeaker *>(_activeSpeaker);
+
+ if (speaker) {
+ speaker->_speakerMode = obj44._speakerMode;
+ if (!choiceList[strIndex].empty())
+ speaker->proc15();
+ }
- _textShown = true;
- _activeSpeaker->setText(choiceList[strIndex]);
+ if (!choiceList[strIndex].empty()) {
+ _textShown = true;
+ _activeSpeaker->setText(choiceList[strIndex]);
+ } else if (!obj44._speakerMode) {
+ _delayFrames = 1;
+ } else {
+ _delayFrames = 0;
+ speaker->proc15();
+ }
+ } else {
+ _textShown = true;
+ _activeSpeaker->setText(choiceList[strIndex]);
+ }
}
_obj44Index = getNewIndex(obj44._list[strIndex]._id);
@@ -915,6 +1004,8 @@ Speaker *StripManager::getSpeaker(const char *speakerName) {
int StripManager::getNewIndex(int id) {
if (id == 10000)
return id;
+ if ((g_vm->getGameID() == GType_Ringworld2) && (id < 0))
+ return id;
for (uint idx = 0; idx < _obj44List.size(); ++idx) {
if (_obj44List[idx]._id == id) {
diff --git a/engines/tsage/converse.h b/engines/tsage/converse.h
index 0c4eb9539d..5aef0d8a7f 100644
--- a/engines/tsage/converse.h
+++ b/engines/tsage/converse.h
@@ -94,6 +94,7 @@ public:
virtual void proc12(Action *action);
virtual void setText(const Common::String &msg);
virtual void removeText();
+ virtual void proc16() {}
void setTextPos(const Common::Point &pt) { _textPos = pt; }
};
@@ -145,6 +146,10 @@ public:
};
class ConversationChoiceDialog : public ModalDialog {
+private:
+ int textLeft() const;
+ int textMaxWidth() const;
+ int numberLeft() const;
public:
int _stdColor;
int _highlightColor;
@@ -189,8 +194,9 @@ public:
// Return to Ringworld specific field
int _mode;
- int _lookupValue, _lookupIndex, _field6;
- int _field8, _field16;
+ int _lookupValue, _lookupIndex, _exitMode;
+ int _speakerMode;
+ int _field16[11];
public:
void load(const byte *dataP);
virtual void synchronize(Serializer &s);
@@ -217,6 +223,7 @@ public:
bool _textShown;
bool _field2E6;
int _field2E8;
+ int _exitMode;
Common::Array<Obj44> _obj44List;
Common::Array<byte> _script;
StripProc _onBegin;
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
index 4a90e23a33..7ca529f2ed 100644
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -2468,10 +2468,10 @@ void SceneObject::postInit(SceneObjectList *OwnerList) {
if (!OwnerList)
OwnerList = g_globals->_sceneObjects;
- if (!OwnerList->contains(this)) {
+ if (!OwnerList->contains(this) || ((_flags & OBJFLAG_REMOVE) != 0)) {
_percent = 100;
_priority = 255;
- _flags = 4;
+ _flags = OBJFLAG_ZOOMED;
_visage = 0;
_strip = 1;
_frame = 1;
@@ -2724,7 +2724,9 @@ void SceneObject::setup(int visage, int stripFrameNum, int frameNum, int posX, i
}
void SceneObject::setup(int visage, int stripFrameNum, int frameNum) {
- postInit();
+ if (g_vm->getGameID() != GType_Ringworld2)
+ postInit();
+
setVisage(visage);
setStrip(stripFrameNum);
setFrame(frameNum);
@@ -3103,6 +3105,7 @@ Visage::Visage() {
_rlbNum = -1;
_data = NULL;
_flipHoriz = false;
+ _flipVert = false;
}
Visage::Visage(const Visage &v) {
@@ -3112,6 +3115,7 @@ Visage::Visage(const Visage &v) {
if (_data)
g_vm->_memoryManager.incLocks(_data);
_flipHoriz = false;
+ _flipVert = false;
}
Visage &Visage::operator=(const Visage &s) {
@@ -3155,8 +3159,11 @@ void Visage::setVisage(int resNum, int rlbNum) {
rlbNum = (int)(v & 0xff);
}
_flipHoriz = flags & 1;
+ _flipVert = flags & 2;
_data = g_resourceManager->getResource(RES_VISAGE, resNum, rlbNum);
+
+ DEALLOCATE(indexData);
}
}
@@ -3179,7 +3186,9 @@ GfxSurface Visage::getFrame(int frameNum) {
byte *frameData = _data + offset;
GfxSurface result = surfaceFromRes(frameData);
- if (_flipHoriz) flip(result);
+ if (_flipHoriz) flipHorizontal(result);
+ if (_flipVert) flipVertical(result);
+
return result;
}
@@ -3187,7 +3196,7 @@ int Visage::getFrameCount() const {
return READ_LE_UINT16(_data);
}
-void Visage::flip(GfxSurface &gfxSurface) {
+void Visage::flipHorizontal(GfxSurface &gfxSurface) {
Graphics::Surface s = gfxSurface.lockSurface();
for (int y = 0; y < s.h; ++y) {
@@ -3200,6 +3209,21 @@ void Visage::flip(GfxSurface &gfxSurface) {
gfxSurface.unlockSurface();
}
+void Visage::flipVertical(GfxSurface &gfxSurface) {
+ Graphics::Surface s = gfxSurface.lockSurface();
+
+ for (int y = 0; y < s.h / 2; ++y) {
+ // Flip the lines1
+ byte *line1P = (byte *)s.getBasePtr(0, y);
+ byte *line2P = (byte *)s.getBasePtr(0, s.h - y - 1);
+
+ for (int x = 0; x < s.w; ++x)
+ SWAP(line1P[x], line2P[x]);
+ }
+
+ gfxSurface.unlockSurface();
+}
+
/*--------------------------------------------------------------------------*/
Player::Player(): SceneObject() {
@@ -4267,10 +4291,15 @@ void SceneHandler::dispatch() {
GUIErrorMessage(SAVE_ERROR_MSG);
}
if (_loadGameSlot != -1) {
+ int priorSceneBeforeLoad = GLOBALS._sceneManager._previousScene;
+ int currentSceneBeforeLoad = GLOBALS._sceneManager._sceneNumber;
+
int loadSlot = _loadGameSlot;
_loadGameSlot = -1;
g_saver->restore(loadSlot);
g_globals->_events.setCursorFromFlag();
+
+ postLoad(priorSceneBeforeLoad, currentSceneBeforeLoad);
}
g_globals->_soundManager.dispatch();
diff --git a/engines/tsage/core.h b/engines/tsage/core.h
index 296754011e..1f9d7cd3a5 100644
--- a/engines/tsage/core.h
+++ b/engines/tsage/core.h
@@ -472,11 +472,13 @@ class Visage {
private:
byte *_data;
- void flip(GfxSurface &s);
+ void flipHorizontal(GfxSurface &s);
+ void flipVertical(GfxSurface &s);
public:
int _resNum;
int _rlbNum;
bool _flipHoriz;
+ bool _flipVert;
public:
Visage();
Visage(const Visage &v);
@@ -898,6 +900,7 @@ public:
protected:
virtual void playerAction(Event &event) {}
virtual void processEnd(Event &event) {}
+ virtual void postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad) {}
public:
SceneHandler();
void registerHandler();
diff --git a/engines/tsage/dialogs.cpp b/engines/tsage/dialogs.cpp
index 77ac0a25d7..43833f53b9 100644
--- a/engines/tsage/dialogs.cpp
+++ b/engines/tsage/dialogs.cpp
@@ -137,43 +137,47 @@ void ModalDialog::drawFrame() {
Rect origRect = _bounds;
_bounds.collapse(-10, -10);
- // Fill the dialog area
- g_globals->gfxManager().fillRect(origRect, 54);
-
- // Draw top line
- GfxSurface surface = surfaceFromRes(8, 1, 7);
- for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10)
- surface.draw(Common::Point(xp, _bounds.top));
- surface.draw(Common::Point(_bounds.right - 20, _bounds.top));
-
- surface = surfaceFromRes(8, 1, 1);
- surface.draw(Common::Point(_bounds.left, _bounds.top));
-
- surface = surfaceFromRes(8, 1, 4);
- surface.draw(Common::Point(_bounds.right - 10, _bounds.top));
-
- // Draw vertical edges
- surface = surfaceFromRes(8, 1, 2);
- for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10)
- surface.draw(Common::Point(_bounds.left, yp));
- surface.draw(Common::Point(_bounds.left, _bounds.bottom - 20));
-
- surface = surfaceFromRes(8, 1, 5);
- for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10)
- surface.draw(Common::Point(_bounds.right - 10, yp));
- surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 20));
-
- // Draw bottom line
- surface = surfaceFromRes(8, 1, 8);
- for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10)
- surface.draw(Common::Point(xp, _bounds.bottom - 10));
- surface.draw(Common::Point(_bounds.right - 20, _bounds.bottom - 10));
-
- surface = surfaceFromRes(8, 1, 3);
- surface.draw(Common::Point(_bounds.left, _bounds.bottom - 10));
-
- surface = surfaceFromRes(8, 1, 6);
- surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 10));
+ if (g_vm->getGameID() == GType_Ringworld2) {
+ GfxElement::drawFrame();
+ } else {
+ // Fill the dialog area
+ g_globals->gfxManager().fillRect(origRect, 54);
+
+ // Draw top line
+ GfxSurface surface = surfaceFromRes(8, 1, 7);
+ for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10)
+ surface.draw(Common::Point(xp, _bounds.top));
+ surface.draw(Common::Point(_bounds.right - 20, _bounds.top));
+
+ surface = surfaceFromRes(8, 1, 1);
+ surface.draw(Common::Point(_bounds.left, _bounds.top));
+
+ surface = surfaceFromRes(8, 1, 4);
+ surface.draw(Common::Point(_bounds.right - 10, _bounds.top));
+
+ // Draw vertical edges
+ surface = surfaceFromRes(8, 1, 2);
+ for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10)
+ surface.draw(Common::Point(_bounds.left, yp));
+ surface.draw(Common::Point(_bounds.left, _bounds.bottom - 20));
+
+ surface = surfaceFromRes(8, 1, 5);
+ for (int yp = _bounds.top + 10; yp < (_bounds.bottom - 20); yp += 10)
+ surface.draw(Common::Point(_bounds.right - 10, yp));
+ surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 20));
+
+ // Draw bottom line
+ surface = surfaceFromRes(8, 1, 8);
+ for (int xp = _bounds.left + 10; xp < (_bounds.right - 20); xp += 10)
+ surface.draw(Common::Point(xp, _bounds.bottom - 10));
+ surface.draw(Common::Point(_bounds.right - 20, _bounds.bottom - 10));
+
+ surface = surfaceFromRes(8, 1, 3);
+ surface.draw(Common::Point(_bounds.left, _bounds.bottom - 10));
+
+ surface = surfaceFromRes(8, 1, 6);
+ surface.draw(Common::Point(_bounds.right - 10, _bounds.bottom - 10));
+ }
// Set the dialog's manager bounds
_gfxManager._bounds = origRect;
diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp
index 4589a926c9..5c4fa967e5 100644
--- a/engines/tsage/globals.cpp
+++ b/engines/tsage/globals.cpp
@@ -3,7 +3,7 @@
* 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
@@ -366,30 +366,47 @@ bool BlueForceGlobals::removeFlag(int flagNum) {
namespace Ringworld2 {
+Ringworld2Globals::Ringworld2Globals() {
+ _scannerDialog = new ScannerDialog();
+}
+
+Ringworld2Globals::~Ringworld2Globals() {
+ delete _scannerDialog;
+}
+
void Ringworld2Globals::reset() {
Globals::reset();
+ if (!_scannerDialog)
+ _scannerDialog = new ScannerDialog();
+
// Reset the inventory
R2_INVENTORY.reset();
T2_GLOBALS._uiElements.updateInventory();
T2_GLOBALS._uiElements._active = false;
+ // Set the screen to track the player
+ _scrollFollower = &_player;
+
// Reset fields
- Common::fill(&_v1000[0], &_v1000[0x1000], 0);
- _v1000Flag = false;
+ Common::fill(&_fadePaletteMap[0][0], &_fadePaletteMap[10][256], 0);
+ Common::fill(&_paletteMap[0], &_paletteMap[4096], 0);
+
+ _fadePaletteFlag = false;
_v5589E.set(0, 0, 0, 0);
_v558B6.set(0, 0, 0, 0);
_v558C2 = 0;
_animationCtr = 0;
_v5657C = 0;
- _v565E1 = 0;
- _v565E3 = 0;
+ _electromagnetChangeAmount = 0;
+ _electromagnetZoom = 0;
_v565E5 = 0;
_v565E7 = 0;
_v565E9 = -5;
_v565EB = 26;
_v565F5 = 0;
_v565F6 = 0;
+ _v565F8 = 0;
_v565FA = 0;
_v565AE = 0;
_v56605[0] = 0;
@@ -463,7 +480,7 @@ void Ringworld2Globals::reset() {
_v565EC[2] = 27;
_v565EC[3] = 4;
_v565EC[4] = 4;
- Common::fill(&_v565F1[0], &_v565F1[MAX_CHARACTERS], 1);
+ Common::fill(&_scannerFrequencies[0], &_scannerFrequencies[MAX_CHARACTERS], 1);
_speechSubtitles = SPEECH_VOICE | SPEECH_TEXT;
_insetUp = 0;
_frameEdgeColour = 2;
@@ -496,14 +513,15 @@ void Ringworld2Globals::synchronize(Serializer &s) {
s.syncAsSint16LE(_v558C2);
s.syncAsSint16LE(_animationCtr);
s.syncAsSint16LE(_v5657C);
- s.syncAsSint16LE(_v565E1);
- s.syncAsSint16LE(_v565E3);
+ s.syncAsSint16LE(_electromagnetChangeAmount);
+ s.syncAsSint16LE(_electromagnetZoom);
s.syncAsSint16LE(_v565E5);
s.syncAsSint16LE(_v565E7);
s.syncAsSint16LE(_v565E9);
s.syncAsSint16LE(_v565EB);
s.syncAsSint16LE(_v565F5);
s.syncAsSint16LE(_v565F6);
+ s.syncAsSint16LE(_v565F8);
s.syncAsSint16LE(_v565FA);
s.syncAsSint16LE(_v566A3);
s.syncAsSint16LE(_v566A6);
@@ -525,7 +543,7 @@ void Ringworld2Globals::synchronize(Serializer &s) {
s.syncAsByte(_v565EC[i]);
for (i = 0; i < MAX_CHARACTERS; ++i)
- s.syncAsByte(_v565F1[i]);
+ s.syncAsByte(_scannerFrequencies[i]);
s.syncAsByte(_v565AE);
s.syncAsByte(_v566A4);
diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h
index d190b6a2a4..ed27ff0556 100644
--- a/engines/tsage/globals.h
+++ b/engines/tsage/globals.h
@@ -247,28 +247,31 @@ namespace Ringworld2 {
#define k5A790 18
#define k5A791 17
+class ScannerDialog;
+
class Ringworld2Globals: public TsAGE2Globals {
public:
ASoundExt _sound1, _sound2, _sound3, _sound4;
PlayStream _playStream;
StripProxy _stripProxy;
- bool _v1000Flag;
- byte _v1000[0x1000];
- byte _palIndexList[10][256];
+ bool _fadePaletteFlag;
+ byte _fadePaletteMap[10][256];
+ byte _paletteMap[4096];
int _insetUp;
int _frameEdgeColour; // _v421e
Rect _v5589E;
Rect _v558B6;
int _v558C2;
int _animationCtr;
- int _v565E1;
- int _v565E3;
+ int _electromagnetChangeAmount;
+ int _electromagnetZoom;
int _v565E5;
int _v565E7;
int _v565E9;
int _v565EB;
int _v565F5;
int _v565F6;
+ int _v565F8;
int _v565FA;
int _v5657C;
byte _v565AE;
@@ -302,9 +305,12 @@ public:
int _v57C2C;
int _speechSubtitles;
byte _v565EC[5];
- byte _v565F1[4];
+ byte _scannerFrequencies[4];
byte _stripManager_lookupList[12];
+ ScannerDialog *_scannerDialog;
+ Ringworld2Globals();
+ virtual ~Ringworld2Globals();
virtual void reset();
virtual void synchronize(Serializer &s);
};
diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
index fb0b0b0cbb..ce19502524 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -234,9 +234,14 @@ GfxSurface::GfxSurface(const GfxSurface &s) {
}
GfxSurface::~GfxSurface() {
+ clear();
+}
+
+void GfxSurface::clear() {
if (_customSurface) {
_customSurface->free();
delete _customSurface;
+ _customSurface = NULL;
}
}
@@ -289,8 +294,11 @@ void GfxSurface::addDirtyRect(const Rect &r) {
r2.translate(_bounds.left, _bounds.top);
// Add to the dirty rect list
- _dirtyRects.push_back(Rect(r2.left, r2.top,
- MIN(r2.right + 1, SCREEN_WIDTH), MIN(r2.bottom + 1, SCREEN_HEIGHT)));
+ r2.right = MIN(r2.right + 1, SCREEN_WIDTH);
+ r2.bottom = MIN(r2.bottom + 1, SCREEN_HEIGHT);
+
+ if (r2.isValidRect())
+ _dirtyRects.push_back(r2);
}
}
@@ -790,35 +798,58 @@ void GfxElement::drawFrame() {
lineP++;
}
}
+
+ // Draw the edge frame
+ // Outer frame border
+ surface.hLine(tempRect.left + 2, tempRect.top, tempRect.right - 2, 0);
+ surface.hLine(tempRect.left + 2, tempRect.bottom, tempRect.right - 2, 0);
+ surface.vLine(tempRect.left, tempRect.top + 2, tempRect.bottom - 2, 0);
+ surface.vLine(tempRect.right, tempRect.top + 2, tempRect.bottom - 2, 0);
+ *((byte *)surface.getBasePtr(tempRect.left + 1, tempRect.top + 1)) = 0;
+ *((byte *)surface.getBasePtr(tempRect.right - 1, tempRect.top + 1)) = 0;
+ *((byte *)surface.getBasePtr(tempRect.left + 1, tempRect.bottom - 1)) = 0;
+ *((byte *)surface.getBasePtr(tempRect.right - 1, tempRect.bottom - 1)) = 0;
+
+ // Inner frame border
+ surface.hLine(tempRect.left + 2, tempRect.top + 1, tempRect.right - 2, R2_GLOBALS._frameEdgeColour);
+ surface.hLine(tempRect.left + 2, tempRect.bottom - 1, tempRect.right - 2, R2_GLOBALS._frameEdgeColour);
+ surface.vLine(tempRect.left + 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColour);
+ surface.vLine(tempRect.right - 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColour);
+ *((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColour;
+ *((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColour;
+ *((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColour;
+ *((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColour;
+
gfxManager.unlockSurface();
+ gfxManager.getSurface().addDirtyRect(tempRect);
} else {
// Fill dialog content with specified background colour
gfxManager.fillRect(tempRect, _colors.background);
- }
-
- --tempRect.bottom; --tempRect.right;
- gfxManager.fillArea(tempRect.left, tempRect.top, bgColor);
- gfxManager.fillArea(tempRect.left, tempRect.bottom, fgColor);
- gfxManager.fillArea(tempRect.right, tempRect.top, fgColor);
- gfxManager.fillArea(tempRect.right, tempRect.bottom, fgColor);
-
- tempRect.collapse(-1, -1);
- gfxManager.fillRect2(tempRect.left + 1, tempRect.top, tempRect.width() - 1, 1, bgColor);
- gfxManager.fillRect2(tempRect.left, tempRect.top + 1, 1, tempRect.height() - 1, bgColor);
- gfxManager.fillRect2(tempRect.left + 1, tempRect.bottom, tempRect.width() - 1, 1, fgColor);
- gfxManager.fillRect2(tempRect.right, tempRect.top + 1, 1, tempRect.height() - 1, fgColor);
-
- gfxManager.fillArea(tempRect.left, tempRect.top, 0);
- gfxManager.fillArea(tempRect.left, tempRect.bottom, 0);
- gfxManager.fillArea(tempRect.right, tempRect.top, 0);
- gfxManager.fillArea(tempRect.right, tempRect.bottom, 0);
- tempRect.collapse(-1, -1);
- gfxManager.fillRect2(tempRect.left + 2, tempRect.top, tempRect.width() - 3, 1, 0);
- gfxManager.fillRect2(tempRect.left, tempRect.top + 2, 1, tempRect.height() - 3, 0);
- gfxManager.fillRect2(tempRect.left + 2, tempRect.bottom, tempRect.width() - 3, 1, 0);
- gfxManager.fillRect2(tempRect.right, tempRect.top + 2, 1, tempRect.height() - 3, 0);
+ --tempRect.bottom; --tempRect.right;
+ gfxManager.fillArea(tempRect.left, tempRect.top, bgColor);
+ gfxManager.fillArea(tempRect.left, tempRect.bottom, fgColor);
+ gfxManager.fillArea(tempRect.right, tempRect.top, fgColor);
+ gfxManager.fillArea(tempRect.right, tempRect.bottom, fgColor);
+
+ tempRect.collapse(-1, -1);
+ gfxManager.fillRect2(tempRect.left + 1, tempRect.top, tempRect.width() - 1, 1, bgColor);
+ gfxManager.fillRect2(tempRect.left, tempRect.top + 1, 1, tempRect.height() - 1, bgColor);
+ gfxManager.fillRect2(tempRect.left + 1, tempRect.bottom, tempRect.width() - 1, 1, fgColor);
+ gfxManager.fillRect2(tempRect.right, tempRect.top + 1, 1, tempRect.height() - 1, fgColor);
+
+ gfxManager.fillArea(tempRect.left, tempRect.top, 0);
+ gfxManager.fillArea(tempRect.left, tempRect.bottom, 0);
+ gfxManager.fillArea(tempRect.right, tempRect.top, 0);
+ gfxManager.fillArea(tempRect.right, tempRect.bottom, 0);
+
+ tempRect.collapse(-1, -1);
+ gfxManager.fillRect2(tempRect.left + 2, tempRect.top, tempRect.width() - 3, 1, 0);
+ gfxManager.fillRect2(tempRect.left, tempRect.top + 2, 1, tempRect.height() - 3, 0);
+ gfxManager.fillRect2(tempRect.left + 2, tempRect.bottom, tempRect.width() - 3, 1, 0);
+ gfxManager.fillRect2(tempRect.right, tempRect.top + 2, 1, tempRect.height() - 3, 0);
+ }
gfxManager.unlockSurface();
}
@@ -1322,6 +1353,12 @@ void GfxManager::copyFrom(GfxSurface &src, int destX, int destY) {
_surface.copyFrom(src, destX, destY);
}
+void GfxManager::copyFrom(GfxSurface &src, const Rect &srcBounds, const Rect &destBounds) {
+ _surface.setBounds(_bounds);
+
+ _surface.copyFrom(src, srcBounds, destBounds);
+}
+
/*--------------------------------------------------------------------------*/
diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h
index 826f2fef6f..7239a99a68 100644
--- a/engines/tsage/graphics.h
+++ b/engines/tsage/graphics.h
@@ -100,6 +100,7 @@ public:
void unlockSurface();
void synchronize(Serializer &s);
void create(int width, int height);
+ void clear();
void setBounds(const Rect &bounds) { _bounds = bounds; }
const Rect &getBounds() const { return _bounds; }
@@ -302,6 +303,7 @@ public:
}
void copyFrom(GfxSurface &src, Rect destBounds, Region *priorityRegion = NULL);
void copyFrom(GfxSurface &src, int destX, int destY);
+ void copyFrom(GfxSurface &src, const Rect &srcBounds, const Rect &destBounds);
GfxSurface &getSurface() {
_surface.setBounds(_bounds);
diff --git a/engines/tsage/ringworld/ringworld_scenes1.cpp b/engines/tsage/ringworld/ringworld_scenes1.cpp
index 4d9d565705..89c07273fc 100644
--- a/engines/tsage/ringworld/ringworld_scenes1.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes1.cpp
@@ -2273,6 +2273,7 @@ void Scene60::Item1::doAction(int action) {
} else {
scene->setAction(&scene->_action2);
}
+ break;
default:
SceneHotspot::doAction(action);
break;
diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.cpp b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
index 478fdcf5a5..57fdef6405 100644
--- a/engines/tsage/ringworld2/ringworld2_dialogs.cpp
+++ b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
@@ -236,7 +236,7 @@ void CharacterDialog::show() {
// Play a transition sound as the character is changed
if (R2_GLOBALS._player._characterScene[0] != 300) {
- switch (R2_GLOBALS._v565F1[R2_GLOBALS._player._characterIndex]) {
+ switch (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex]) {
case 0:
R2_GLOBALS._sound4.stop();
break;
@@ -255,8 +255,8 @@ void CharacterDialog::show() {
default:
break;
}
- } else if (R2_GLOBALS._v565F1[R2_GLOBALS._player._characterIndex] > 1) {
- switch (R2_GLOBALS._v565F1[R2_GLOBALS._player._characterIndex]) {
+ } else if (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex] > 1) {
+ switch (R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex]) {
case 2:
R2_GLOBALS._sound4.play(45);
break;
@@ -272,8 +272,8 @@ void CharacterDialog::show() {
default:
break;
}
- } else if ((R2_GLOBALS._player._characterScene[1] == 300) && (R2_GLOBALS._v565F1[1] != 1)) {
- switch (R2_GLOBALS._v565F1[1]) {
+ } else if ((R2_GLOBALS._player._characterScene[1] == 300) && (R2_GLOBALS._scannerFrequencies[1] != 1)) {
+ switch (R2_GLOBALS._scannerFrequencies[1]) {
case 2:
R2_GLOBALS._sound4.play(45);
break;
@@ -291,10 +291,10 @@ void CharacterDialog::show() {
}
} else if (R2_GLOBALS._player._characterScene[2] != 300) {
R2_GLOBALS._sound4.stop();
- } else if (R2_GLOBALS._v565F1[2] == 1) {
+ } else if (R2_GLOBALS._scannerFrequencies[2] == 1) {
R2_GLOBALS._sound4.stop();
} else {
- switch (R2_GLOBALS._v565F1[1]) {
+ switch (R2_GLOBALS._scannerFrequencies[1]) {
case 2:
R2_GLOBALS._sound4.play(45);
break;
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index 97042cb621..ac6ba523f6 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -21,6 +21,8 @@
*/
#include "common/config-manager.h"
+#include "common/rect.h"
+#include "tsage/graphics.h"
#include "tsage/scenes.h"
#include "tsage/tsage.h"
#include "tsage/staticres.h"
@@ -86,8 +88,10 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Cutscene - Walking in hall
return new Scene525();
case 600:
+ // Drive Room
return new Scene600();
case 700:
+ // Lander Bay 2
return new Scene700();
case 800:
// Sick bay
@@ -99,6 +103,7 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Deck #5 - By Lift
return new Scene850();
case 900:
+ // Lander Bay 2 - Crane Controls
return new Scene900();
/* Scene group #1 */
//
@@ -166,7 +171,7 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Ice Maze: Large empty room
return new Scene2400();
case 2425:
- // Ice Maze:
+ // Ice Maze: The Hall of Records
return new Scene2425();
case 2430:
// Ice Maze: Bedroom
@@ -213,7 +218,7 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
case 2900:
error("Missing scene %d from group 2", sceneNumber);
/* Scene group #3 */
- //
+ // ARM Base Hanager
case 3100:
return new Scene3100();
case 3125:
@@ -258,16 +263,22 @@ Scene *Ringworld2Game::createScene(int sceneNumber) {
// Cutscene - Ship landing
return new Scene3350();
case 3375:
+ // Outer walkway
return new Scene3375();
case 3385:
+ // Corridor
return new Scene3385();
case 3395:
+ // Walkway
return new Scene3395();
case 3400:
+ // Confrontation
return new Scene3400();
case 3500:
+ // Maze action sequencec
return new Scene3500();
case 3600:
+ // Cutscene - walking at gunpoint
return new Scene3600();
case 3700:
// Cutscene - Teleport outside
@@ -328,8 +339,7 @@ void SceneExt::postInit(SceneObjectList *OwnerList) {
int sceneNumber = R2_GLOBALS._sceneManager._sceneNumber;
if (((prevScene == -1) && (sceneNumber != 180) && (sceneNumber != 205) && (sceneNumber != 50))
|| (sceneNumber == 50)
- || ((prevScene == 205) && (sceneNumber == 100))
- || ((prevScene == 180) && (sceneNumber == 100))) {
+ || ((sceneNumber == 100) && (prevScene == 0 || prevScene == 180 || prevScene == 205))) {
static_cast<SceneHandlerExt *>(R2_GLOBALS._sceneHandler)->setupPaletteMaps();
R2_GLOBALS._uiElements._active = true;
R2_GLOBALS._uiElements.show();
@@ -407,17 +417,19 @@ bool SceneExt::display(CursorType action, Event &event) {
SceneItem::display2(5, 0);
break;
case R2_SONIC_STUNNER:
- if ((R2_GLOBALS._v565F1[1] == 2) || ((R2_GLOBALS._v565F1[1] == 1) &&
- (R2_GLOBALS._v565F1[2] == 2) && (R2_GLOBALS._sceneManager._previousScene == 300))) {
+ if ((R2_GLOBALS._scannerFrequencies[R2_QUINN] == 2)
+ || ((R2_GLOBALS._scannerFrequencies[R2_QUINN] == 1) &&
+ (R2_GLOBALS._scannerFrequencies[R2_SEEKER] == 2) &&
+ (R2_GLOBALS._sceneManager._previousScene == 300))) {
R2_GLOBALS._sound4.stop();
R2_GLOBALS._sound3.play(46);
SceneItem::display2(5, 15);
+
+ R2_GLOBALS._sound4.play(45);
} else {
R2_GLOBALS._sound3.play(43, 0);
- SceneItem::display2(2, 0);
+ SceneItem::display2(2, R2_SONIC_STUNNER);
}
-
- R2_GLOBALS._sound4.play(45);
break;
case R2_COM_SCANNER:
case R2_COM_SCANNER_2:
@@ -573,7 +585,7 @@ void SceneHandlerExt::process(Event &event) {
SceneExt *scene = static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene);
if (scene && R2_GLOBALS._player._uiEnabled) {
// Handle any scene areas that have been registered
- SynchronizedList<SceneArea *>::iterator saIter;
+ SynchronizedList<EventHandler *>::iterator saIter;
for (saIter = scene->_sceneAreas.begin(); saIter != scene->_sceneAreas.end() && !event.handled; ++saIter) {
(*saIter)->process(event);
}
@@ -583,11 +595,32 @@ void SceneHandlerExt::process(Event &event) {
SceneHandler::process(event);
}
+void SceneHandlerExt::postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad) {
+ if (priorSceneBeforeLoad == -1 || priorSceneBeforeLoad == 50
+ || priorSceneBeforeLoad == 180 || priorSceneBeforeLoad == 205)
+ setupPaletteMaps();
+
+ if (currentSceneBeforeLoad == 2900) {
+ R2_GLOBALS._gfxFontNumber = 50;
+ R2_GLOBALS._gfxColors.background = 0;
+ R2_GLOBALS._gfxColors.foreground = 59;
+ R2_GLOBALS._fontColors.background = 4;
+ R2_GLOBALS._fontColors.foreground = 15;
+ R2_GLOBALS._frameEdgeColour = 2;
+
+ R2_GLOBALS._scenePalette.loadPalette(0);
+ R2_GLOBALS._scenePalette.setEntry(255, 0xff, 0xff, 0xff);
+ R2_GLOBALS._fadePaletteFlag = false;
+ setupPaletteMaps();
+ }
+}
+
void SceneHandlerExt::setupPaletteMaps() {
byte *palP = &R2_GLOBALS._scenePalette._palette[0];
- if (!R2_GLOBALS._v1000Flag) {
- R2_GLOBALS._v1000Flag = true;
+ // Set up the mapping table for giving faded versions of pixels at different fade percentages
+ if (!R2_GLOBALS._fadePaletteFlag) {
+ R2_GLOBALS._fadePaletteFlag = true;
for (int idx = 0; idx < 10; ++idx) {
for (int palIndex = 0; palIndex < 224; ++palIndex) {
@@ -637,18 +670,19 @@ void SceneHandlerExt::setupPaletteMaps() {
foundIndex = pIndex2;
}
- R2_GLOBALS._palIndexList[idx][palIndex] = foundIndex;
+ R2_GLOBALS._fadePaletteMap[idx][palIndex] = foundIndex;
}
}
}
for (int palIndex = 0; palIndex < 224; ++palIndex) {
- int r = palP[palIndex * 3] >> 2;
- int g = palP[palIndex * 3 + 1] >> 2;
- int b = palP[palIndex * 3 + 2] >> 2;
+ int r = palP[palIndex * 3] >> 4;
+ int g = palP[palIndex * 3 + 1] >> 4;
+ int b = palP[palIndex * 3 + 2] >> 4;
- int idx = (((r << 4) | g) << 4) | b;
- R2_GLOBALS._v1000[idx] = palIndex;
+ int v = (r << 8) | (g << 4) | b;
+ assert(v < 0x1000);
+ R2_GLOBALS._paletteMap[v] = palIndex;
}
int vdx = 0;
@@ -656,9 +690,9 @@ void SceneHandlerExt::setupPaletteMaps() {
int palIndex = 224;
for (int vIndex = 0; vIndex < 4096; ++vIndex) {
- int v = R2_GLOBALS._v1000[vIndex];
+ int v = R2_GLOBALS._paletteMap[vIndex];
if (!v) {
- R2_GLOBALS._v1000[vIndex] = idx;
+ R2_GLOBALS._paletteMap[vIndex] = idx;
} else {
idx = v;
}
@@ -842,6 +876,7 @@ Ringworld2InvObjectList::Ringworld2InvObjectList():
_itemList.push_back(&_inv52);
_selectedItem = NULL;
+
}
void Ringworld2InvObjectList::reset() {
@@ -904,6 +939,9 @@ void Ringworld2InvObjectList::reset() {
setObjectScene(R2_ALCOHOL_LAMP_3, 2435);
setObjectScene(R2_BROKEN_DISPLAY, 1580);
setObjectScene(R2_TOOLBOX, 3260);
+
+ // Set up the select item handler method
+ T2_GLOBALS._onSelectItem = SelectItem;
}
void Ringworld2InvObjectList::setObjectScene(int objectNum, int sceneNumber) {
@@ -921,6 +959,127 @@ void Ringworld2InvObjectList::setObjectScene(int objectNum, int sceneNumber) {
T2_GLOBALS._uiElements.updateInventory();
}
+/**
+ * When an inventory item is selected, in Return to Ringworld two objects can be combined
+ */
+bool Ringworld2InvObjectList::SelectItem(int objectNumber) {
+ // If no existing item selected, don't go any further
+ int currentItem = R2_GLOBALS._events.getCursor();
+ if (currentItem >= 256)
+ return false;
+
+ switch (objectNumber) {
+ case R2_NEGATOR_GUN:
+ switch (currentItem) {
+ case R2_SENSOR_PROBE:
+ if (R2_GLOBALS.getFlag(1))
+ SceneItem::display2(5, 1);
+ else if (R2_INVENTORY.getObjectScene(R2_SPENT_POWER_CAPSULE) != 100)
+ SceneItem::display2(5, 3);
+ else {
+ R2_GLOBALS._sound3.play(48);
+ SceneItem::display2(5, 2);
+ R2_INVENTORY.setObjectScene(R2_SPENT_POWER_CAPSULE, 1);
+ }
+ break;
+ case R2_COM_SCANNER:
+ R2_GLOBALS._sound3.play(44);
+ if (R2_GLOBALS.getFlag(1))
+ SceneItem::display2(5, 9);
+ else if (R2_INVENTORY.getObjectScene(R2_SPENT_POWER_CAPSULE) == 100)
+ SceneItem::display2(5, 8);
+ else
+ SceneItem::display2(5, 10);
+
+ R2_GLOBALS._sound3.stop();
+ break;
+ case R2_CHARGED_POWER_CAPSULE:
+ if (R2_INVENTORY.getObjectScene(R2_SPENT_POWER_CAPSULE) == 1) {
+ R2_GLOBALS._sound3.play(49);
+ R2_INVENTORY.setObjectScene(R2_CHARGED_POWER_CAPSULE, 100);
+ R2_GLOBALS.setFlag(1);
+ SceneItem::display2(5, 4);
+ } else {
+ SceneItem::display2(5, 5);
+ }
+ break;
+ default:
+ selectDefault(objectNumber);
+ break;
+ }
+ break;
+ case R2_STEPPING_DISKS:
+ switch (currentItem) {
+ case R2_SENSOR_PROBE:
+ if (R2_INVENTORY.getObjectScene(R2_CHARGED_POWER_CAPSULE) == 400) {
+ R2_GLOBALS._sound3.play(48);
+ SceneItem::display2(5, 6);
+ R2_INVENTORY.setObjectScene(R2_CHARGED_POWER_CAPSULE, 1);
+ } else {
+ SceneItem::display2(5, 7);
+ }
+ break;
+ case R2_COM_SCANNER:
+ R2_GLOBALS._sound3.play(44);
+ if (R2_INVENTORY.getObjectScene(R2_CHARGED_POWER_CAPSULE) == 400)
+ SceneItem::display2(5, 16);
+ else
+ SceneItem::display2(5, 17);
+ R2_GLOBALS._sound3.stop();
+ break;
+ default:
+ selectDefault(objectNumber);
+ break;
+ }
+ break;
+ case R2_ATTRACTOR_UNIT:
+ case R2_CABLE_HARNESS:
+ if (currentItem == R2_CABLE_HARNESS ||
+ currentItem == R2_ATTRACTOR_UNIT) {
+ R2_INVENTORY.setObjectScene(R2_CABLE_HARNESS, 0);
+ R2_INVENTORY.setObjectScene(R2_ATTRACTOR_UNIT, 0);
+ R2_INVENTORY.setObjectScene(R2_ATTRACTOR_CABLE_HARNESS, 1);
+ } else {
+ selectDefault(objectNumber);
+ }
+ break;
+ case R2_TANNER_MASK:
+ case R2_PURE_GRAIN_ALCOHOL:
+ if (currentItem == R2_TANNER_MASK ||
+ currentItem == R2_PURE_GRAIN_ALCOHOL) {
+ R2_INVENTORY.setObjectScene(R2_TANNER_MASK, 0);
+ R2_INVENTORY.setObjectScene(R2_PURE_GRAIN_ALCOHOL, 0);
+ R2_INVENTORY.setObjectScene(R2_SOAKED_FACEMASK, 1);
+ } else {
+ selectDefault(objectNumber);
+ }
+ break;
+ default:
+ // Standard item selection
+ return false;
+ }
+
+ return true;
+}
+
+void Ringworld2InvObjectList::selectDefault(int objectNumber) {
+ Common::String msg1 = g_resourceManager->getMessage(4, 53);
+ Common::String msg2 = g_resourceManager->getMessage(4, R2_GLOBALS._events.getCursor());
+ Common::String msg3 = g_resourceManager->getMessage(4, 54);
+ Common::String msg4 = g_resourceManager->getMessage(4, objectNumber);
+ Common::String line = Common::String::format("%.5s%.5s%.5s%.5s%s %s %s %s.",
+ msg1.c_str(), msg2.c_str(), msg3.c_str(), msg4.c_str(),
+ msg1.c_str() + 5, msg2.c_str() + 5, msg3.c_str() + 5, msg4.c_str() + 5);
+
+ SceneItem::display(-1, -1, line.c_str(),
+ SET_WIDTH, 280,
+ SET_X, 160,
+ SET_Y, 20,
+ SET_POS_MODE, 1,
+ SET_EXT_BGCOLOR, 7,
+ LIST_END);
+}
+
/*--------------------------------------------------------------------------*/
void Ringworld2Game::start() {
@@ -1083,6 +1242,14 @@ void SceneActor::postInit(SceneObjectList *OwnerList) {
SceneObject::postInit();
}
+void SceneActor::remove() {
+ R2_GLOBALS._sceneItems.remove(this);
+ _field9C = NULL;
+ _linkedActor = NULL;
+
+ SceneObject::remove();
+}
+
bool SceneActor::startAction(CursorType action, Event &event) {
bool handled = true;
@@ -1115,6 +1282,32 @@ bool SceneActor::startAction(CursorType action, Event &event) {
return handled;
}
+GfxSurface SceneActor::getFrame() {
+ GfxSurface frame = SceneObject::getFrame();
+
+ // TODO: Proper effects handling
+ switch (_effect) {
+ case 0:
+ case 5:
+ // TODO: Figure out purpose of setting image flags to 64, and getting
+ // scene priorities -1 or _shade
+ break;
+ case 1:
+ // TODO: Transposing using R2_GLOBALS._pixelArrayMap
+ break;
+ case 2:
+ // No effect
+ break;
+ case 4:
+ break;
+ default:
+ // TODO: Default effect
+ break;
+ }
+
+ return frame;
+}
+
/*--------------------------------------------------------------------------*/
SceneArea::SceneArea(): EventHandler() {
@@ -1268,287 +1461,206 @@ void SceneAreaObject::setDetails(int resNum, int lookLineNum, int talkLineNum, i
/*****************************************************************************/
-UnkObject1200::UnkObject1200() {
- _field16 = _field3A = NULL;
- _field12 = _field14 = 0;
- _field26 = _field28 = _field2A = _field2C = _field2E = _field30 = 0;
- _field32 = _field34 = _field36 = _field38 = _field3E = _field40 = 0;
+MazeUI::MazeUI() {
+ _mapData = NULL;
+ _cellsVisible.x = _cellsVisible.y = 0;
+ _mapCells.x = _mapCells.y = 0;
+ _cellSize.x = _cellSize.y = 0;
+ _mapOffset.x = _mapOffset.y = 0;
+ _resNum = _cellsResNum = 0;
+ _frameCount = _resCount = _mapImagePitch = _unused = 0;
}
-void UnkObject1200::synchronize(Serializer &s) {
- SavedObject::synchronize(s);
+MazeUI::~MazeUI() {
+ DEALLOCATE(_mapData);
+}
- _rect1.synchronize(s);
- _rect2.synchronize(s);
+void MazeUI::synchronize(Serializer &s) {
+ SavedObject::synchronize(s);
- // FIXME: syncrhonize _field16 and _field3A
+ s.syncAsSint16LE(_resNum);
+ if (s.isLoading())
+ load(_resNum);
- s.syncAsSint16LE(_field12);
- s.syncAsSint16LE(_field14);
- s.syncAsSint16LE(_field26);
- s.syncAsSint16LE(_field28);
- s.syncAsSint16LE(_field2A);
- s.syncAsSint16LE(_field2C);
- s.syncAsSint16LE(_field2E);
- s.syncAsSint16LE(_field30);
- s.syncAsSint16LE(_field32);
- s.syncAsSint16LE(_field34);
- s.syncAsSint16LE(_field36);
- s.syncAsSint16LE(_field38);
- s.syncAsSint16LE(_field3E);
- s.syncAsSint16LE(_field40);
+ s.syncAsSint16LE(_mapOffset.x);
+ s.syncAsSint16LE(_mapOffset.y);
+ s.syncAsSint16LE(_unused);
}
-void UnkObject1200::sub51AE9(int arg1) {
- warning("STUB: UnkObject1200::sub51AE9()");
-}
+void MazeUI::load(int resNum) {
+ postInit();
+ clear();
+ _resNum = resNum;
-int UnkObject1200::sub51AF8(Common::Point pt) {
- if (!_rect1.contains(pt))
- return -1;
+ const byte *header = g_resourceManager->getResource(RT17, resNum, 0);
- int tmp1 = (pt.x - _rect1.left + _field2E) / _field2A;
- int tmp2 = (pt.y - _rect1.top + _field30) / _field2C;
+ _cellsResNum = resNum + 1000;
+ _mapCells.x = READ_LE_UINT16(header + 2);
+ _mapCells.y = READ_LE_UINT16(header + 4);
+ _frameCount = 10;
+ _resCount = _frameCount << 3;
- if ((tmp1 >= 0) && (tmp2 >= 0) && (_field26 > tmp1) && (_field28 > tmp2))
- return _field16[(((_field26 * tmp2) + tmp1)* 2)];
+ Visage visage;
+ visage.setVisage(_cellsResNum, 1);
- return -1;
+ GfxSurface frame = visage.getFrame(2);
+ _cellSize.x = frame.getBounds().width();
+ _cellSize.y = frame.getBounds().height();
+
+ _mapData = g_resourceManager->getResource(RT17, resNum, 1);
+
+ _mapOffset.y = _mapOffset.x = 0;
+ _cellsVisible.x = (_bounds.width() + _cellSize.x - 1) / _cellSize.x;
+ _cellsVisible.y = (_bounds.height() + _cellSize.y - 1) / _cellSize.y;
+
+ _mapImagePitch = (_cellsVisible.x + 1) * _cellSize.x;
+ _mapImage.create(_mapImagePitch, _cellSize.y);
+
+ _mapBounds = Rect(0, 0, _cellSize.x * _mapCells.x, _cellSize.y * _mapCells.y);
}
-bool UnkObject1200::sub51AFD(Common::Point pt) {
- int retval = false;
+void MazeUI::clear() {
+ if (!_resNum)
+ _resNum = 1;
- _field2E = pt.x;
- _field30 = pt.y;
+ if (_mapData)
+ DEALLOCATE(_mapData);
+ _mapData = NULL;
- if (_field2E < _rect2.top) {
- _field2E = _rect2.top;
+ _mapImage.clear();
+}
+
+bool MazeUI::setMazePosition(const Common::Point &pt) {
+ bool retval = false;
+
+ _mapOffset = pt;
+
+ if (_mapOffset.x < _mapBounds.top) {
+ _mapOffset.x = _mapBounds.top;
retval = true;
}
- if (_field30 < _rect2.left) {
- _field30 = _rect2.left;
+ if (_mapOffset.y < _mapBounds.left) {
+ _mapOffset.y = _mapBounds.left;
retval = true;
}
- if (_field2E + _rect1.width() > _rect2.right) {
- _field2E = _rect2.right - _rect1.width();
+ if (_mapOffset.x + _bounds.width() > _mapBounds.right) {
+ _mapOffset.x = _mapBounds.right - _bounds.width();
retval = true;
}
- if (_field30 + _rect1.height() > _rect2.bottom) {
- _field30 = _rect2.bottom - _rect1.height();
+ if (_mapOffset.y + _bounds.height() > _mapBounds.bottom) {
+ _mapOffset.y = _mapBounds.bottom - _bounds.height();
retval = true;
}
return retval;
}
-void UnkObject1200::sub51B02() {
- warning("STUB: UnkObject1200::sub51B02()");
+void MazeUI::reposition() {
}
-void UnkObject1200::sub9EDE8(Rect rect) {
- _rect1 = rect;
- warning("FIXME: UnkObject1200::sub9EDE8()");
-// _rect1.clip(g_globals->gfxManager()._bounds);
-}
+void MazeUI::draw() {
+ int yPos = 0;
+ int ySize;
+ Visage visage;
-int UnkObject1200::sub9EE22(int &arg1, int &arg2) {
- arg1 /= _field2A;
- arg2 /= _field2C;
+ _cellsVisible.y = ((_mapOffset.y % _cellSize.y) + _bounds.height() +
+ (_cellSize.y - 1)) / _cellSize.y;
- if ((arg1 >= 0) && (arg2 >= 0) && (_field26 > arg1) && (_field28 > arg2)) {
- return _field16[(((_field26 * arg2) + arg1) * 2)];
- }
+ // Loop to handle the cell rows of the visible display area one at a time
+ for (int yCtr = 0; yCtr < _cellsVisible.y; ++yCtr, yPos += ySize) {
+ int cellY = _mapOffset.y / _cellSize.y + yCtr;
- return -1;
-}
+ // Loop to iterate through the horizontal visible cells to build up
+ // an entire cell high horizontal slice of the map
+ for (int xCtr = 0; xCtr < _cellsVisible.x; ++xCtr) {
+ int cellX = _mapOffset.x / _cellSize.x + xCtr;
-void Scene1200::sub9DAD6(int indx) {
- _object1.sub9EE22(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4);
+ // Get the type of content to display in the cell
+ int cell = getCellFromCellXY(Common::Point(cellX, cellY)) - 1;
+ if (cell >= 0) {
+ int frameNum = (cell % _frameCount) + 1;
+ int rlbNum = (cell % _resCount) / _frameCount + 1;
+ int resNum = _cellsResNum + (cell / _resCount);
- switch (indx) {
- case 0:
- if ( ((_object1.sub51AF8(Common::Point(200, 50)) > 36) || (_object1.sub51AF8(Common::Point(200, 88)) > 36))
- && ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 33) && (_field418 != 4))
- || ((R2_GLOBALS._v56AA2 == 13) && (R2_GLOBALS._v56AA4 == 21) && (_field418 != 2))
- || ((R2_GLOBALS._v56AA2 == 29) && (R2_GLOBALS._v56AA4 == 17) && (_field418 != 1))
- || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 41)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1200;
- setAction(&_sequenceManager, this, 1200, &_actor1, NULL);
- } else if (_object1.sub51AF8(Common::Point(200, 69)) == 36) {
- switch (_field412 - 1) {
- case 0:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 15;
- else
- _sceneMode = 10;
- break;
- case 1:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 76;
- else
- _sceneMode = 75;
- break;
- case 2:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 101;
- else
- _sceneMode = 100;
- break;
- case 3:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 111;
- else
- _sceneMode = 110;
- break;
- default:
- break;
- }
- R2_GLOBALS._player.disableControl();
- _field412 = 1;
- signal();
- }
- break;
- case 1:
- if ( ((_object1.sub51AF8(Common::Point(120, 50)) > 36) || (_object1.sub51AF8(Common::Point(120, 88)) > 36))
- && ( ((R2_GLOBALS._v56AA2 == 7) && (R2_GLOBALS._v56AA4 == 33) && (_field418 != 4))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 21) && (_field418 != 2))
- || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 17) && (_field418 != 1))
- || ((R2_GLOBALS._v56AA2 == 5) && (R2_GLOBALS._v56AA4 == 5)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1201;
- setAction(&_sequenceManager, this, 1201, &_actor1, NULL);
- } else if (_object1.sub51AF8(Common::Point(120, 69)) == 36) {
- switch (_field412 - 1) {
- case 0:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 56;
- else
- _sceneMode = 55;
- break;
- case 1:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 25;
- else
- _sceneMode = 20;
- break;
- case 2:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 91;
- else
- _sceneMode = 90;
- break;
- case 3:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 121;
- else
- _sceneMode = 120;
- break;
- default:
- break;
- }
- R2_GLOBALS._player.disableControl();
- _field412 = 2;
- signal();
- }
- break;
- case 2:
- if ( ((_object1.sub51AF8(Common::Point(140, 110)) > 36) || (_object1.sub51AF8(Common::Point(178, 110)) > 36))
- && ( ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 5) && (_field418 != 3))
- || ((R2_GLOBALS._v56AA2 == 41) && (R2_GLOBALS._v56AA4 == 21)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1203;
- setAction(&_sequenceManager, this, 1203, &_actor1, NULL);
- } else if (_object1.sub51AF8(Common::Point(160, 110)) == 36) {
- switch (_field412 - 1) {
- case 0:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 51;
- else
- _sceneMode = 50;
- break;
- case 1:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 81;
- else
- _sceneMode = 80;
- break;
- case 2:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 35;
- else
- _sceneMode = 30;
- break;
- case 3:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 116;
- else
- _sceneMode = 115;
- break;
- default:
- break;
+ visage.setVisage(resNum, rlbNum);
+ GfxSurface frame = visage.getFrame(frameNum);
+
+ _mapImage.copyFrom(frame, xCtr * _cellSize.x, 0);
+ } else {
+ GfxSurface emptyRect;
+ emptyRect.create(_cellSize.x, _cellSize.y);
+
+ _mapImage.copyFrom(emptyRect, xCtr * _cellSize.x, 0);
}
- R2_GLOBALS._player.disableControl();
- _field412 = 3;
- signal();
}
- break;
- case 3:
- if ( ((_object1.sub51AF8(Common::Point(140, 30)) > 36) || (_object1.sub51AF8(Common::Point(178, 30)) > 36))
- && ( ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 9) && (_field418 != 3))
- || ((R2_GLOBALS._v56AA2 == 35) && (R2_GLOBALS._v56AA4 == 17)) )
- ) {
- R2_GLOBALS._player.disableControl();
- _sceneMode = 1202;
- setAction(&_sequenceManager, this, 1202, &_actor1, NULL);
- } else if (_object1.sub51AF8(Common::Point(160, 30)) == 36) {
- switch (_field412 - 1) {
- case 0:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 61;
- else
- _sceneMode = 60;
- break;
- case 1:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 71;
- else
- _sceneMode = 70;
- break;
- case 2:
- if (R2_GLOBALS._player._visage == 3156)
- _sceneMode = 96;
- else
- _sceneMode = 95;
- break;
- case 3:
- if (R2_GLOBALS._player._visage == 3155)
- _sceneMode = 45;
- else
- _sceneMode = 40;
- break;
- default:
- _sceneMode = 1;
- R2_GLOBALS._player.setup(3156, 4, 6);
- break;
+
+ if (yPos == 0) {
+ // First line of the map to be displayed - only the bottom portion of that
+ // first cell row may be visible
+ yPos = _bounds.top;
+ ySize = _cellSize.y - (_mapOffset.y % _cellSize.y);
+
+ Rect srcBounds(_mapOffset.x % _cellSize.x, _mapOffset.y % _cellSize.y,
+ (_mapOffset.x % _cellSize.x) + _bounds.width(), _cellSize.y);
+ Rect destBounds(_bounds.left, yPos, _bounds.right, yPos + ySize);
+
+ R2_GLOBALS.gfxManager().copyFrom(_mapImage, srcBounds, destBounds);
+ } else {
+ if ((yPos + _cellSize.y) < _bounds.bottom) {
+ ySize = _cellSize.y;
+ } else {
+ ySize = _bounds.bottom - yPos;
}
- R2_GLOBALS._player.disableControl();
- _field412 = 4;
- signal();
+
+ Rect srcBounds(_mapOffset.x % _cellSize.x, 0,
+ (_mapOffset.x % _cellSize.x) + _bounds.width(), ySize);
+ Rect destBounds(_bounds.left, yPos, _bounds.right, yPos + ySize);
+
+ R2_GLOBALS.gfxManager().copyFrom(_mapImage, srcBounds, destBounds);
}
- break;
- default:
- break;
}
}
+int MazeUI::getCellFromPixelXY(const Common::Point &pt) {
+ if (!_bounds.contains(pt))
+ return -1;
+
+ int cellX = (pt.x - _bounds.left + _mapOffset.x) / _cellSize.x;
+ int cellY = (pt.y - _bounds.top + _mapOffset.y) / _cellSize.y;
+
+ if ((cellX >= 0) && (cellY >= 0) && (cellX < _mapCells.x) && (cellY < _mapCells.y))
+ return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * cellY + cellX) * 2);
+
+ return -1;
+}
+
+int MazeUI::getCellFromCellXY(const Common::Point &p) {
+ if (p.x < 0 || p.y < 0 || p.x >= _mapCells.x || p.y >= _mapCells.y) {
+ return -1;
+ } else {
+ return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * p.y + p.x) * 2);
+ }
+}
+
+int MazeUI::pixelToCellXY(Common::Point &pt) {
+ pt.x /= _cellSize.x;
+ pt.y /= _cellSize.y;
+
+ if ((pt.x >= 0) && (pt.y >= 0) && (pt.x < _mapCells.x) && (pt.y < _mapCells.y)) {
+ return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * pt.y + pt.x) * 2);
+ }
+
+ return -1;
+}
+
+void MazeUI::setDisplayBounds(const Rect &r) {
+ _bounds = r;
+ _bounds.clip(g_globals->gfxManager()._bounds);
+}
+
/*--------------------------------------------------------------------------*/
void AnimationSlice::load(Common::File &f) {
@@ -2001,6 +2113,347 @@ void AnimationPlayerExt::synchronize(Serializer &s) {
s.syncAsSint16LE(_v);
}
+/*--------------------------------------------------------------------------*/
+
+ModalWindow::ModalWindow() {
+ _field20 = 0;
+}
+
+void ModalWindow::remove() {
+ R2_GLOBALS._sceneItems.remove(&_object1);
+ _object1.remove();
+
+ SceneArea::remove();
+
+ --R2_GLOBALS._insetUp;
+}
+
+void ModalWindow::synchronize(Serializer &s) {
+ SceneArea::synchronize(s);
+
+ s.syncAsByte(_field20);
+}
+
+void ModalWindow::process(Event &event) {
+ if (_field20 != R2_GLOBALS._insetUp)
+ return;
+
+ CursorType cursor = R2_GLOBALS._events.getCursor();
+
+ if (_object1._bounds.contains(event.mousePos.x + g_globals->gfxManager()._bounds.left , event.mousePos.y)) {
+ if (cursor == _cursorNum) {
+ R2_GLOBALS._events.setCursor(_savedCursorNum);
+ }
+ } else if (event.mousePos.y < 168) {
+ if (cursor != _cursorNum) {
+ _savedCursorNum = cursor;
+ R2_GLOBALS._events.setCursor(CURSOR_INVALID);
+ }
+ if (event.eventType == EVENT_BUTTON_DOWN) {
+ event.handled = true;
+ R2_GLOBALS._events.setCursor(_savedCursorNum);
+ remove();
+ }
+ }
+}
+
+void ModalWindow::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
+ Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
+
+ _object1.postInit();
+ _object1.setup(visage, stripFrameNum, frameNum);
+ _object1.setPosition(Common::Point(posX, posY));
+ _object1.fixPriority(250);
+ _cursorNum = CURSOR_INVALID;
+ scene->_sceneAreas.push_front(this);
+ ++R2_GLOBALS._insetUp;
+ _field20 = R2_GLOBALS._insetUp;
+}
+
+void ModalWindow::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
+ _object1.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
+}
+
+/*--------------------------------------------------------------------------*/
+
+ScannerDialog::Button::Button() {
+ _buttonId = 0;
+ _buttonDown = false;
+}
+
+void ScannerDialog::Button::setup(int buttonId) {
+ _buttonId = buttonId;
+ _buttonDown = false;
+ SceneActor::postInit();
+
+ SceneObject::setup(4, 2, 2);
+ fixPriority(255);
+
+ if (_buttonId == 1)
+ setPosition(Common::Point(141, 99));
+ else if (_buttonId == 2)
+ setPosition(Common::Point(141, 108));
+
+ static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene)->_sceneAreas.push_front(this);
+}
+
+void ScannerDialog::Button::synchronize(Serializer &s) {
+ SceneActor::synchronize(s);
+ s.syncAsSint16LE(_buttonId);
+}
+
+void ScannerDialog::Button::process(Event &event) {
+ if (event.eventType == EVENT_BUTTON_DOWN && R2_GLOBALS._events.getCursor() == CURSOR_USE
+ && _bounds.contains(event.mousePos) && !_buttonDown) {
+ setFrame(3);
+ _buttonDown = true;
+ event.handled = true;
+ }
+
+ if (event.eventType == EVENT_BUTTON_UP && _buttonDown) {
+ setFrame(2);
+ _buttonDown = false;
+ event.handled = true;
+
+ reset();
+ }
+}
+
+bool ScannerDialog::Button::startAction(CursorType action, Event &event) {
+ if (action == CURSOR_USE)
+ return false;
+
+ return startAction(action, event);
+}
+
+void ScannerDialog::Button::reset() {
+ Scene *scene = R2_GLOBALS._sceneManager._scene;
+ ScannerDialog &scanner = *R2_GLOBALS._scannerDialog;
+
+ switch (_buttonId) {
+ case 1:
+ // Talk button
+ switch (R2_GLOBALS._sceneManager._sceneNumber) {
+ case 1550:
+ scene->_sceneMode = 80;
+ scene->signal();
+ break;
+ case 1700:
+ scene->_sceneMode = 30;
+ scene->signal();
+ remove();
+ break;
+ default:
+ break;
+ }
+ break;
+ case 2:
+ // Scan button
+ switch (R2_GLOBALS._sceneManager._sceneNumber) {
+ case 1550:
+ scanner._obj4.setup(4, 3, 1);
+
+ scanner._obj5.postInit();
+ scanner._obj5.setup(4, 4, 1);
+ scanner._obj5.setPosition(Common::Point(R2_GLOBALS._v565EC[1] + 145,
+ R2_GLOBALS._v565EC[3] + 59));
+ scanner._obj5.fixPriority(257);
+
+ scanner._obj6.postInit();
+ scanner._obj6.setup(4, 4, 2);
+ scanner._obj6.setPosition(Common::Point(R2_GLOBALS._v565EC[2] + 145,
+ R2_GLOBALS._v565EC[4] + 59));
+ scanner._obj6.fixPriority(257);
+ break;
+ case 1700:
+ case 1800:
+ if (R2_GLOBALS._v565F8 < 0 || (R2_GLOBALS._v565F8 == 0 && R2_GLOBALS._v565F6 < 1201))
+ scanner._obj4.setup(4, 3, 3);
+ else if (R2_GLOBALS._v565F8 > 0 || (R2_GLOBALS._v565F8 == 0 && R2_GLOBALS._v565F6 < 1201))
+ scanner._obj4.setup(4, 3, 4);
+ else
+ scanner._obj4.setup(4, 3, 5);
+ break;
+ case 3800:
+ case 3900:
+ if ((R2_GLOBALS._v56A93 + 1) == 0 && R2_GLOBALS._v566A9 == 0) {
+ do {
+ R2_GLOBALS._v566A9 = R2_GLOBALS._randomSource.getRandomNumber(3);
+ } while (R2_GLOBALS._v566A9 == R2_GLOBALS._v566AA);
+ }
+
+ scanner._obj4.setup(4, 7, R2_GLOBALS._v566A9);
+ if (!R2_GLOBALS.getFlag(46))
+ R2_GLOBALS.setFlag(46);
+ break;
+ default:
+ scanner._obj4.setup(4, 3, 2);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
+ScannerDialog::Slider::Slider() {
+ _initial = _xStart = _yp = 0;
+ _width = _xInc = 0;
+ _sliderDown = false;
+}
+
+void ScannerDialog::Slider::synchronize(Serializer &s) {
+ SceneActor::synchronize(s);
+
+ s.syncAsSint16LE(_initial);
+ s.syncAsSint16LE(_xStart);
+ s.syncAsSint16LE(_yp);
+ s.syncAsSint16LE(_width);
+ s.syncAsSint16LE(_xInc);
+}
+
+void ScannerDialog::Slider::remove() {
+ static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene)->_sceneAreas.remove(this);
+ SceneActor::remove();
+}
+
+void ScannerDialog::Slider::process(Event &event) {
+ if (event.eventType == EVENT_BUTTON_DOWN && R2_GLOBALS._events.getCursor() == CURSOR_USE
+ && _bounds.contains(event.mousePos)) {
+ _sliderDown = true;
+ }
+
+ if (event.eventType == EVENT_BUTTON_UP && _sliderDown) {
+ _sliderDown = false;
+ event.handled = true;
+ update();
+ }
+
+ if (_sliderDown) {
+ event.handled = true;
+ if (event.mousePos.x < _xStart) {
+ setPosition(Common::Point(_xStart, _yp));
+ } else if (event.mousePos.x >= (_xStart + _width)) {
+ setPosition(Common::Point(_xStart + _width, _yp));
+ } else {
+ setPosition(Common::Point(event.mousePos.x, _yp));
+ }
+ }
+}
+
+bool ScannerDialog::Slider::startAction(CursorType action, Event &event) {
+ if (action == CURSOR_USE)
+ return false;
+
+ return startAction(action, event);
+}
+
+void ScannerDialog::Slider::update() {
+ int incHalf = (_width / (_xInc - 1)) / 2;
+ int newFrequency = ((_position.x - _xStart + incHalf) * _xInc) / (_width + incHalf * 2);
+ setPosition(Common::Point(_xStart + ((_width * newFrequency) / (_xInc - 1)), _yp));
+
+ R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex] = newFrequency + 1;
+
+ switch (newFrequency) {
+ case 0:
+ R2_GLOBALS._sound4.stop();
+ break;
+ case 1:
+ R2_GLOBALS._sound4.play(45);
+ break;
+ case 2:
+ R2_GLOBALS._sound4.play(4);
+ break;
+ case 3:
+ R2_GLOBALS._sound4.play(5);
+ break;
+ case 4:
+ R2_GLOBALS._sound4.play(6);
+ break;
+ default:
+ break;
+ }
+}
+
+void ScannerDialog::Slider::setup(int initial, int xStart, int yp, int width, int xInc) {
+ _initial = initial;
+ _xStart = xStart;
+ _yp = yp;
+ _width = width;
+ _xInc = xInc;
+ _sliderDown = false;
+ SceneActor::postInit();
+ SceneObject::setup(4, 2, 1);
+ fixPriority(255);
+ setPosition(Common::Point(_width * (_initial - 1) / (_xInc - 1) + _xStart, yp));
+
+ static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene)->_sceneAreas.push_front(this);
+}
+
+/*--------------------------------------------------------------------------*/
+
+ScannerDialog::ScannerDialog() {
+}
+
+void ScannerDialog::remove() {
+ switch (R2_GLOBALS._sceneManager._sceneNumber) {
+ case 1550:
+ case 1700:
+ R2_GLOBALS._events.setCursor(R2_GLOBALS._player._canWalk ? CURSOR_ARROW : CURSOR_USE);
+ break;
+ case 3800:
+ case 3900: {
+ Scene *scene = R2_GLOBALS._sceneManager._scene;
+ scene->_sceneMode = 3806;
+ scene->signal();
+ break;
+ }
+ default:
+ break;
+ }
+
+ SceneExt *scene = static_cast<SceneExt *>(R2_GLOBALS._sceneManager._scene);
+ scene->_sceneAreas.remove(&_talkButton);
+ scene->_sceneAreas.remove(&_scanButton);
+ _talkButton.remove();
+ _scanButton.remove();
+ _slider.remove();
+ _obj4.remove();
+ _obj5.remove();
+ _obj6.remove();
+ _obj7.remove();
+
+ ModalWindow::remove();
+}
+
+void ScannerDialog::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
+ // Stop player moving if currently doing so
+ if (R2_GLOBALS._player._mover)
+ R2_GLOBALS._player.addMover(NULL);
+
+ R2_GLOBALS._events.setCursor(CURSOR_USE);
+ ModalWindow::proc12(visage, stripFrameNum, frameNum, posX, posY);
+
+ proc13(100, -1, -1, -1);
+ _talkButton.setup(1);
+ _scanButton.setup(2);
+ _slider.setup(R2_GLOBALS._scannerFrequencies[R2_GLOBALS._player._characterIndex], 142, 124, 35, 5);
+
+ _obj4.postInit();
+ _obj4.setup(4, 3, 2);
+ _obj4.setPosition(Common::Point(160, 83));
+ _obj4.fixPriority(256);
+
+ if (R2_GLOBALS._sceneManager._sceneNumber == 3800 || R2_GLOBALS._sceneManager._sceneNumber == 3900) {
+ Scene *scene = R2_GLOBALS._sceneManager._scene;
+ scene->_sceneMode = 3805;
+ scene->signal();
+ }
+}
+
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_logic.h b/engines/tsage/ringworld2/ringworld2_logic.h
index 0b573bf7f0..2cf48f3cf3 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.h
+++ b/engines/tsage/ringworld2/ringworld2_logic.h
@@ -88,7 +88,7 @@ public:
SceneObject *_focusObject;
Visage _cursorVisage;
- SynchronizedList<SceneArea *> _sceneAreas;
+ SynchronizedList<EventHandler *> _sceneAreas;
Rect _v51C34;
public:
@@ -114,6 +114,7 @@ class SceneHandlerExt: public SceneHandler {
public:
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void process(Event &event);
+ virtual void postLoad(int priorSceneBeforeLoad, int currentSceneBeforeLoad);
void setupPaletteMaps();
};
@@ -159,6 +160,9 @@ public:
/*--------------------------------------------------------------------------*/
class Ringworld2InvObjectList : public InvObjectList {
+private:
+ static bool SelectItem(int objectNumber);
+ static void selectDefault(int obectNumber);
public:
InvObject _none;
InvObject _inv1;
@@ -260,7 +264,9 @@ class SceneActor: public SceneObject {
public:
virtual Common::String getClassName() { return "SceneActor"; }
virtual void postInit(SceneObjectList *OwnerList = NULL);
+ virtual void remove();
virtual bool startAction(CursorType action, Event &event);
+ virtual GfxSurface getFrame();
};
class SceneActorExt: public SceneActor {
@@ -276,6 +282,49 @@ public:
}
};
+enum MazeDirection { MAZEDIR_NONE = 0, MAZEDIR_NORTH = 1, MAZEDIR_NORTHEAST = 2, MAZEDIR_EAST = 3,
+ MAZEDIR_SOUTHEAST = 4, MAZEDIR_SOUTH = 5, MAZEDIR_SOUTHWEST = 6, MAZEDIR_WEST = 7,
+ MAZEDIR_NORTHWEST = 8 };
+
+class MazeUI: public SceneObject {
+private:
+ void clear();
+public:
+ // The dimensions (in cells) of the entire maze map
+ Rect _mapBounds;
+
+ // Encoded cell map specifying the features of the maze
+ byte *_mapData;
+ // Image surface used to store a line of the map for rendering
+ GfxSurface _mapImage;
+
+ Common::Point _cellsVisible;
+ Common::Point _mapCells;
+ Common::Point _cellSize;
+ Common::Point _mapOffset;
+ int _resNum;
+ int _cellsResNum;
+ int _frameCount;
+ int _resCount;
+ int _mapImagePitch;
+ int _unused;
+public:
+ MazeUI();
+ virtual ~MazeUI();
+
+ void setDisplayBounds(const Rect &r);
+ bool setMazePosition(const Common::Point &pt);
+ void load(int resNum);
+ int getCellFromPixelXY(const Common::Point &pt);
+ int getCellFromCellXY(const Common::Point &p);
+ int pixelToCellXY(Common::Point &pt);
+
+ virtual Common::String getClassName() { return "MazeUI"; }
+ void synchronize(Serializer &s);
+ virtual void reposition();
+ virtual void draw();
+};
+
class SceneAreaObject: public SceneArea {
class Object1: public SceneActor {
public:
@@ -290,41 +339,6 @@ public:
void setDetails(int resNum, int lookLineNum, int talkLineNum, int useLineNum);
};
-class UnkObject1200 : public SavedObject {
-public:
- Rect _rect1;
- Rect _rect2;
-
- int *_field16;
- int *_field3A;
-
- int _field12;
- int _field14;
- int _field26;
- int _field28;
- int _field2A;
- int _field2C;
- int _field2E;
- int _field30;
- int _field32;
- int _field34;
- int _field36;
- int _field38;
- int _field3E;
- int _field40;
-
- UnkObject1200();
- void synchronize(Serializer &s);
-
- void sub51AE9(int arg1);
- int sub51AF8(Common::Point pt);
- bool sub51AFD(Common::Point pt);
- void sub51B02();
- void sub9EDE8(Rect rect);
- int sub9EE22(int &arg1, int &arg2);
- virtual Common::String getClassName() { return "UnkObject1200"; }
-};
-
/*--------------------------------------------------------------------------*/
class AnimationSlice {
@@ -432,6 +446,74 @@ public:
virtual void synchronize(Serializer &s);
};
+class ModalWindow: public SceneArea {
+public:
+ SceneActor _object1;
+ byte _field20;
+public:
+ ModalWindow();
+
+ virtual void remove();
+ virtual void synchronize(Serializer &s);
+ virtual Common::String getClassName() { return "ModalWindow"; }
+ virtual void process(Event &event);
+ virtual void proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY);
+ virtual void proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum);
+};
+
+class ScannerDialog: public ModalWindow {
+
+ class Button: public SceneActor {
+ private:
+ void reset();
+ public:
+ int _buttonId;
+ bool _buttonDown;
+ public:
+ Button();
+ void setup(int buttonId);
+
+ virtual void synchronize(Serializer &s);
+ virtual Common::String getClassName() { return "ScannerButton"; }
+ virtual void process(Event &event);
+ virtual bool startAction(CursorType action, Event &event);
+ };
+ class Slider: public SceneActor {
+ private:
+ void update();
+ public:
+ int _initial;
+ int _xStart;
+ int _yp;
+ int _width;
+ int _xInc;
+ bool _sliderDown;
+ public:
+ Slider();
+ void setup(int initial, int xStart, int yp, int width, int xInc);
+
+ virtual void synchronize(Serializer &s);
+ virtual Common::String getClassName() { return "ScannerSlider"; }
+ virtual void remove();
+ virtual void process(Event &event);
+ virtual bool startAction(CursorType action, Event &event);
+ };
+public:
+ Button _talkButton;
+ Button _scanButton;
+ Slider _slider;
+ SceneActor _obj4;
+ SceneActor _obj5;
+ SceneActor _obj6;
+ SceneActor _obj7;
+public:
+ ScannerDialog();
+
+ virtual Common::String getClassName() { return "ScannerDialog"; }
+ virtual void remove();
+ void proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY);
+};
+
} // End of namespace Ringworld2
} // End of namespace TsAGE
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
index 3b7d283e44..4018921791 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
@@ -226,9 +226,9 @@ bool Scene100::Terminal::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
void Scene100::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(100);
R2_GLOBALS._scenePalette.loadPalette(0);
+ SceneExt::postInit();
if (R2_GLOBALS._sceneManager._previousScene != 125)
R2_GLOBALS._sound1.play(10);
@@ -573,23 +573,23 @@ void Scene125::Icon::hideIcon() {
/*--------------------------------------------------------------------------*/
-bool Scene125::Item4::startAction(CursorType action, Event &event) {
+bool Scene125::DiskSlot::startAction(CursorType action, Event &event) {
Scene125 *scene = (Scene125 *)R2_GLOBALS._sceneManager._scene;
switch (action) {
case CURSOR_USE:
if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == R2_GLOBALS._player._oldCharacterScene[1]) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 126;
- scene->setAction(&scene->_sequenceManager, scene, 126, &scene->_object7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 126, &scene->_infoDisk, NULL);
return true;
}
break;
case R2_OPTO_DISK:
if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == 1) {
R2_GLOBALS._player.disableControl();
- scene->_object7.postInit();
+ scene->_infoDisk.postInit();
scene->_sceneMode = 125;
- scene->setAction(&scene->_sequenceManager, scene, 125, &scene->_object7, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 125, &scene->_infoDisk, NULL);
return true;
}
break;
@@ -626,16 +626,16 @@ void Scene125::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player.disableControl();
if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == R2_GLOBALS._player._oldCharacterScene[1]) {
- _object7.postInit();
- _object7.setup(160, 3, 5);
- _object7.setPosition(Common::Point(47, 167));
+ _infoDisk.postInit();
+ _infoDisk.setup(160, 3, 5);
+ _infoDisk.setPosition(Common::Point(47, 167));
}
_object6.postInit();
_object6.setup(162, 1, 1);
_object6.setPosition(Common::Point(214, 168));
- _item4.setDetails(Rect(27, 145, 81, 159), 126, 9, -1, -1, 1, NULL);
+ _diskSlot.setDetails(Rect(27, 145, 81, 159), 126, 9, -1, -1, 1, NULL);
_item3.setDetails(Rect(144, 119, 286, 167), 126, 6, 7, 8, 1, NULL);
_item2.setDetails(1, 126, 3, 4, 5);
_background.setDetails(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 126, 0, 1, -1, 1, NULL);
@@ -782,10 +782,11 @@ void Scene125::signal() {
break;
case 125:
R2_INVENTORY.setObjectScene(R2_OPTO_DISK, R2_GLOBALS._player._oldCharacterScene[1]);
+ R2_GLOBALS._player.enableControl();
break;
case 126:
R2_INVENTORY.setObjectScene(R2_OPTO_DISK, 1);
- _object7.remove();
+ _infoDisk.remove();
R2_GLOBALS._player.enableControl();
R2_GLOBALS._player._canWalk = false;
break;
@@ -2042,8 +2043,8 @@ void Scene200::WestExit::changeScene() {
/*--------------------------------------------------------------------------*/
void Scene200::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(200);
+ SceneExt::postInit();
_westExit.setDetails(Rect(94, 0, 123, 58), EXITCURSOR_W, 175);
_westExit.setDest(Common::Point(125, 52));
@@ -2597,8 +2598,8 @@ void Scene250::synchronize(Serializer &s) {
}
void Scene250::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(250);
+ SceneExt::postInit();
R2_GLOBALS._player.postInit();
R2_GLOBALS._player.setVisage(10);
@@ -2708,6 +2709,8 @@ void Scene250::signal() {
case 7:
_field418 = 1;
if ((_field414 + 12) == _field412)
+ _sceneMode = 9;
+ else
_sceneMode = 8;
signal();
break;
@@ -2741,7 +2744,7 @@ void Scene250::signal() {
R2_GLOBALS._sceneManager.changeScene(300);
break;
case 139:
- R2_GLOBALS._sceneManager.changeScene(139);
+ R2_GLOBALS._sceneManager.changeScene(700);
break;
case 91:
R2_GLOBALS._sceneManager.changeScene(850);
@@ -3048,7 +3051,7 @@ bool Scene300::Seeker::startAction(CursorType action, Event &event) {
R2_GLOBALS._player.disableControl();
if (R2_GLOBALS._player._characterIndex == R2_QUINN) {
- if (R2_GLOBALS.getFlag(44)) {
+ if (!R2_GLOBALS.getFlag(44)) {
if (!R2_GLOBALS.getFlag(38)) {
R2_GLOBALS._sound1.play(69);
scene->_stripId = 181;
@@ -3171,6 +3174,9 @@ bool Scene300::Doorway::startAction(CursorType action, Event &event) {
Scene300::Scene300(): SceneExt() {
_stripId = 0;
_rotation = NULL;
+
+ _stripManager.setColors(60, 255);
+ _stripManager.setFontNumber(3);
}
void Scene300::synchronize(Serializer &s) {
@@ -3181,8 +3187,9 @@ void Scene300::synchronize(Serializer &s) {
}
void Scene300::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(300);
+ SceneExt::postInit();
+
_sound1.play(23);
setZoomPercents(75, 93, 120, 100);
@@ -3191,8 +3198,6 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._player._characterIndex = R2_QUINN;
}
- _stripManager.setColors(60, 255);
- _stripManager.setFontNumber(3);
_stripManager.addSpeaker(&_mirandaSpeaker);
_stripManager.addSpeaker(&_seekerSpeaker);
_stripManager.addSpeaker(&_quinnSpeaker);
@@ -3233,7 +3238,7 @@ void Scene300::postInit(SceneObjectList *OwnerList) {
_protocolDisplay.postInit();
_protocolDisplay.setup(300, 6, 1);
_protocolDisplay.setPosition(Common::Point(287, 71));
- _protocolDisplay.animate(ANIM_MODE_7, NULL);
+ _protocolDisplay.animate(ANIM_MODE_7, 0, NULL);
_protocolDisplay._numFrames = 5;
_object6.postInit();
@@ -3484,27 +3489,27 @@ void Scene300::remove() {
void Scene300::signal() {
switch (_sceneMode) {
case 10:
- switch (_stripManager._field2E8) {
- case 0:
+ switch (_stripManager._exitMode) {
+ case 1:
R2_GLOBALS._sound1.changeSound(10);
R2_GLOBALS.setFlag(38);
break;
- case 1:
+ case 2:
R2_GLOBALS.setFlag(3);
break;
- case 2:
+ case 3:
R2_GLOBALS.setFlag(4);
break;
- case 3:
+ case 4:
R2_GLOBALS.setFlag(13);
if (R2_GLOBALS._stripManager_lookupList[1] == 6)
R2_GLOBALS.setFlag(40);
break;
- case 4:
+ case 5:
if (R2_GLOBALS._stripManager_lookupList[1] == 6)
R2_GLOBALS.setFlag(40);
break;
- case 5:
+ case 6:
R2_GLOBALS._sceneManager.changeScene(1000);
break;
default:
@@ -3624,6 +3629,8 @@ void Scene300::signal() {
case 309:
signal309();
R2_GLOBALS._events.setCursor(CURSOR_ARROW);
+ R2_GLOBALS._events._currentCursor = CURSOR_ARROW;
+
_sceneMode = 10;
_stripManager.start3(_stripId, this, R2_GLOBALS._stripManager_lookupList);
break;
@@ -4908,7 +4915,7 @@ bool Scene500::Doorway::startAction(CursorType action, Event &event) {
scene->setAction(&scene->_sequenceManager1, scene, 524, &R2_GLOBALS._player, NULL);
} else {
scene->_sceneMode = 500;
- scene->setAction(&scene->_sequenceManager1, scene, 500, &R2_GLOBALS._player, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 500, &R2_GLOBALS._player, this, NULL);
}
return true;
@@ -4986,7 +4993,7 @@ bool Scene500::SonicStunner::startAction(CursorType action, Event &event) {
if ((action == CURSOR_USE) && (R2_GLOBALS._player._characterIndex == R2_QUINN)) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = R2_GLOBALS.getFlag(26) ? 520 : 502;
- scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, scene->_sceneMode, &R2_GLOBALS._player, this, NULL);
return true;
} else {
return SceneActor::startAction(action, event);
@@ -5075,7 +5082,7 @@ void Scene500::postInit(SceneObjectList *OwnerList) {
}
}
- if ((R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) != 500) && R2_GLOBALS.getFlag(27)) {
+ if ((R2_INVENTORY.getObjectScene(R2_REBREATHER_TANK) == 500) && R2_GLOBALS.getFlag(27)) {
_tanks1.postInit();
_tanks1.setup(502, 7, 1);
_tanks1.setPosition(Common::Point(281, 120));
@@ -5230,7 +5237,7 @@ void Scene500::signal() {
R2_GLOBALS._sceneManager.changeScene(700);
break;
case 501:
- if (R2_GLOBALS._player._characterScene[R2_QUINN] == 500) {
+ if (R2_GLOBALS._player._characterScene[R2_MIRANDA] == 500) {
_stripNumber = 1100;
_sceneMode = 523;
setAction(&_sequenceManager1, this, 523, &R2_GLOBALS._player, NULL);
@@ -5338,28 +5345,16 @@ void Scene525::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 600 -
+ * Scene 600 - Drive Room
*
*--------------------------------------------------------------------------*/
-Scene600::Scene600() {
- _field412 = 0;
- for (int i = 0; i < 256; i++)
- _fieldAD2[i] = 0;
-}
-
-void Scene600::synchronize(Serializer &s) {
- SceneExt::synchronize(s);
- s.syncAsSint16LE(_field412);
- for (int i = 0; i < 256; i++)
- s.syncAsByte(_fieldAD2[i]);
-}
-
-bool Scene600::Item1::startAction(CursorType action, Event &event) {
+bool Scene600::CompartmentHotspot::startAction(CursorType action, Event &event) {
if ((action != R2_NEGATOR_GUN) || (!R2_GLOBALS.getFlag(5)) || (R2_GLOBALS.getFlag(8)))
return SceneHotspot::startAction(action, event);
- SceneItem::display(600, 32, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(600, 32, SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, ALIGN_CENTER,
+ SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END);
return true;
}
@@ -5368,12 +5363,14 @@ bool Scene600::Item4::startAction(CursorType action, Event &event) {
return SceneHotspot::startAction(action, event);
if ((R2_GLOBALS.getFlag(5)) && (!R2_GLOBALS.getFlag(8))) {
- SceneItem::display(600, 32, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(600, 32, SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, ALIGN_CENTER,
+ SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END);
return true;
}
- if (R2_GLOBALS.getFlag(5)) {
- SceneItem::display(600, 30, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ if (!R2_GLOBALS.getFlag(5)) {
+ SceneItem::display(600, 30, SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, ALIGN_CENTER,
+ SET_Y, 20, SET_EXT_BGCOLOR, 7, LIST_END);
return true;
}
@@ -5389,30 +5386,46 @@ bool Scene600::Item4::startAction(CursorType action, Event &event) {
scene->_actor2.postInit();
scene->_sceneMode = 612;
- setAction(&scene->_sequenceManager1, this, 612, &scene->_actor3, &scene->_actor2, &R2_GLOBALS._player, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 612, &scene->_actor3, &scene->_actor2, &R2_GLOBALS._player, NULL);
return true;
}
void Scene600::Actor4::signal() {
- Common::Point pt(36, 177 + R2_GLOBALS._randomSource.getRandomNumber(5));
+ Common::Point pt(177 + R2_GLOBALS._randomSource.getRandomNumber(5),
+ 108 + R2_GLOBALS._randomSource.getRandomNumber(3));
NpcMover *mover = new NpcMover();
addMover(mover, &pt, this);
}
bool Scene600::Actor4::startAction(CursorType action, Event &event) {
- if ((action >= CURSOR_WALK) && (action < R2CURSORS_START))
+ if (action >= CURSOR_WALK)
// Only action cursors
return SceneActor::startAction(action, event);
return false;
}
-void Scene600::Actor4::draw() {
- warning("TODO: Actor4::draw()");
- SceneActor::draw();
+GfxSurface Scene600::Actor4::getFrame() {
+ GfxSurface frame = SceneActor::getFrame();
+
+ if (_effect) {
+ // Translate the frame using the scene's pixel map
+ byte *pixelMap = static_cast<Scene600 *>(R2_GLOBALS._sceneManager._scene)->_pixelMap;
+ Graphics::Surface surface = frame.lockSurface();
+ byte *srcP = (byte *)surface.pixels;
+
+ while (srcP < ((byte *)surface.pixels + (surface.w * surface.h))) {
+ *srcP = pixelMap[*srcP];
+ srcP++;
+ }
+
+ frame.unlockSurface();
+ }
+
+ return frame;
}
-bool Scene600::Actor5::startAction(CursorType action, Event &event) {
+bool Scene600::Doorway::startAction(CursorType action, Event &event) {
if ((action < CURSOR_WALK) && (action >= R2CURSORS_START))
return false;
@@ -5423,10 +5436,10 @@ bool Scene600::Actor5::startAction(CursorType action, Event &event) {
if ((R2_INVENTORY.getObjectScene(R2_CLAMP) == 600) && (!R2_GLOBALS.getFlag(6))) {
R2_GLOBALS._player.disableControl();
- scene->_actor6.setDetails(600, 11, -1, -1, 3, (SceneItem *) NULL);
+ scene->_laser.setDetails(600, 11, -1, -1, 3, (SceneItem *) NULL);
R2_GLOBALS.setFlag(6);
scene->_sceneMode = 609;
- scene->setAction(&scene->_sequenceManager1, scene, 609, &R2_GLOBALS._player, &scene->_actor5, &scene->_actor6, &scene->_actor1, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 609, &R2_GLOBALS._player, &scene->_doorway, &scene->_laser, &scene->_actor1, NULL);
return true;
}
@@ -5436,7 +5449,7 @@ bool Scene600::Actor5::startAction(CursorType action, Event &event) {
if (!R2_GLOBALS.getFlag(6)) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 616;
- scene->setAction(&scene->_sequenceManager1, scene, 616, &R2_GLOBALS._player, &scene->_actor5, &scene->_actor6, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 616, &R2_GLOBALS._player, &scene->_doorway, &scene->_laser, NULL);
return true;
}
@@ -5445,15 +5458,15 @@ bool Scene600::Actor5::startAction(CursorType action, Event &event) {
else {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 601;
- scene->setAction(&scene->_sequenceManager1, scene, 601, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 601, &R2_GLOBALS._player, &scene->_doorway, NULL);
}
return true;
}
-bool Scene600::Actor6::startAction(CursorType action, Event &event) {
+bool Scene600::Laser::startAction(CursorType action, Event &event) {
Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene;
- if ((action < CURSOR_WALK) && (action >= R2CURSORS_START)) {
+ if (action < CURSOR_WALK) {
switch (action) {
case R2_COM_SCANNER:
if (R2_GLOBALS.getFlag(6)) {
@@ -5463,7 +5476,7 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) {
} else {
R2_GLOBALS._player.disableControl();
scene->_actor8.postInit();
- scene->_actor8.setDetails(600, 20, -1, -1, 4, &scene->_actor6);
+ scene->_actor8.setDetails(600, 20, -1, -1, 4, &scene->_laser);
scene->_sceneMode = 607;
scene->setAction(&scene->_sequenceManager1, scene, 607, &R2_GLOBALS._player, &scene->_actor8, NULL);
return true;
@@ -5478,8 +5491,8 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) {
return true;
} else {
R2_GLOBALS._player.disableControl();
- scene->_actor7.postInit();
- scene->_actor7.setDetails(600, 27, -1, -1, 5, &scene->_actor6);
+ scene->_aerosol.postInit();
+ scene->_aerosol.setDetails(600, 27, -1, -1, 5, &scene->_laser);
scene->_actor4.postInit();
scene->_actor4.setup(601, 3, 1);
@@ -5487,11 +5500,11 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) {
scene->_actor4._moveDiff = Common::Point(1, 1);
scene->_actor4._moveRate = 2;
scene->_actor4._numFrames = 3;
- scene->_actor4.setDetails(600, 24, 25, 26, 5, &scene->_actor7);
+ scene->_actor4.setDetails(600, 24, 25, 26, 5, &scene->_aerosol);
scene->_sceneMode = 605;
- scene->setAction(&scene->_sequenceManager1, scene, 605, &R2_GLOBALS._player, &scene->_actor7, &scene->_actor4, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 605, &R2_GLOBALS._player, &scene->_aerosol, &scene->_actor4, &scene->_doorway, NULL);
return true;
}
break;
@@ -5499,7 +5512,7 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) {
if (R2_GLOBALS.getFlag(5)) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 606;
- scene->setAction(&scene->_sequenceManager1, scene, 606, &R2_GLOBALS._player, &scene->_actor6, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 606, &R2_GLOBALS._player, &scene->_laser, NULL);
return true;
} else {
return SceneActor::startAction(action, event);
@@ -5509,7 +5522,7 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) {
return false;
break;
}
- } else if (action != CURSOR_USE) {
+ } else if (action == CURSOR_USE) {
if (R2_GLOBALS.getFlag(5)) {
return SceneActor::startAction(action, event);
} else {
@@ -5522,7 +5535,7 @@ bool Scene600::Actor6::startAction(CursorType action, Event &event) {
return SceneActor::startAction(action, event);
}
-bool Scene600::Actor7::startAction(CursorType action, Event &event) {
+bool Scene600::Aerosol::startAction(CursorType action, Event &event) {
Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene;
if ((action < CURSOR_WALK) && (action >= R2CURSORS_START)) {
@@ -5530,13 +5543,28 @@ bool Scene600::Actor7::startAction(CursorType action, Event &event) {
} else if (action == CURSOR_USE) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 614;
- scene->setAction(&scene->_sequenceManager1, scene, 614, &R2_GLOBALS._player, &scene->_actor7, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 614, &R2_GLOBALS._player, &scene->_aerosol, NULL);
return true;
} else {
return SceneActor::startAction(action, event);
}
}
+/*--------------------------------------------------------------------------*/
+
+Scene600::Scene600() {
+ _field412 = 0;
+ Common::fill(&_pixelMap[0], &_pixelMap[256], 0);
+}
+
+void Scene600::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+
+ s.syncAsSint16LE(_field412);
+ for (int i = 0; i < 256; i++)
+ s.syncAsByte(_pixelMap[i]);
+}
+
bool Scene600::Actor8::startAction(CursorType action, Event &event) {
Scene600 *scene = (Scene600 *)R2_GLOBALS._sceneManager._scene;
@@ -5544,7 +5572,7 @@ bool Scene600::Actor8::startAction(CursorType action, Event &event) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 615;
scene->setAction(&scene->_sequenceManager1, scene, 615, &R2_GLOBALS._player, &scene->_actor8, NULL);
- } else if ((action == R2_SONIC_STUNNER) && (R2_INVENTORY.getObjectScene(9) == 600) && (R2_GLOBALS._v565F1[1] == 2) && (!R2_GLOBALS.getFlag(8))){
+ } else if ((action == R2_SONIC_STUNNER) && (R2_INVENTORY.getObjectScene(9) == 600) && (R2_GLOBALS._scannerFrequencies[1] == 2) && (!R2_GLOBALS.getFlag(8))){
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 608;
scene->setAction(&scene->_sequenceManager1, scene, 608, &R2_GLOBALS._player, &scene->_actor4, NULL);
@@ -5562,23 +5590,31 @@ void Scene600::postInit(SceneObjectList *OwnerList) {
R2_GLOBALS._walkRegions.enableRegion(3);
_field412 = 0;
- warning("FIXME: loop to initialize _fieldAD2[]");
+ // Initialise pixel map for the obscuring effect
+ ScenePalette &pal = R2_GLOBALS._scenePalette;
+ uint r, g, b;
+ for (int i = 0; i < 256; ++i) {
+ pal.getEntry(i, &r, &g, &b);
+ int av = ((r + g + b) / 48);
- _actor5.postInit();
- _actor5.setVisage(600);
- _actor5.setPosition(Common::Point(29, 147));
- _actor5.fixPriority(10);
- _actor5.setDetails(300, 3, -1, -1, 1, (SceneItem *) NULL);
+ _pixelMap[i] = R2_GLOBALS._paletteMap[(av << 8) | (av << 4) | av];
+ }
- _actor6.postInit();
- _actor6.setPosition(Common::Point(246, 41));
+ _doorway.postInit();
+ _doorway.setVisage(600);
+ _doorway.setPosition(Common::Point(29, 147));
+ _doorway.fixPriority(10);
+ _doorway.setDetails(300, 3, -1, -1, 1, (SceneItem *) NULL);
+
+ _laser.postInit();
+ _laser.setPosition(Common::Point(246, 41));
if (R2_INVENTORY.getObjectScene(9) == 600) {
_actor8.postInit();
_actor8.setup(602, 5, 1);
_actor8.setPosition(Common::Point(246, 41));
_actor8.setDetails(600, 20, -1, -1, 1, (SceneItem *) NULL);
- switch (R2_GLOBALS._v565F1[1] - 2) {
+ switch (R2_GLOBALS._scannerFrequencies[1] - 2) {
case 0:
R2_GLOBALS._sound4.play(45);
break;
@@ -5597,11 +5633,11 @@ void Scene600::postInit(SceneObjectList *OwnerList) {
}
if (R2_GLOBALS.getFlag(6)) {
- _actor6.setup(602, 7, 1);
- _actor6.setDetails(600, 11, -1, -1, 1, (SceneItem *) NULL);
+ _laser.setup(602, 7, 1);
+ _laser.setDetails(600, 11, -1, -1, 1, (SceneItem *) NULL);
} else {
- _actor6.setup(600, 2, 1);
- _actor6.setDetails(600, 10, -1, -1, 1, (SceneItem *) NULL);
+ _laser.setup(600, 2, 1);
+ _laser.setDetails(600, 10, -1, -1, 1, (SceneItem *) NULL);
_actor1.postInit();
_actor1.setup(600, 3, 5);
@@ -5614,10 +5650,10 @@ void Scene600::postInit(SceneObjectList *OwnerList) {
if (R2_GLOBALS.getFlag(5)) {
if (R2_INVENTORY.getObjectScene(12) == 600) {
- _actor7.postInit();
- _actor7.setup(602, 2, 2);
- _actor7.setPosition(Common::Point(189, 95));
- _actor7.setDetails(600, 27, -1, -1, 1, (SceneItem *) NULL);
+ _aerosol.postInit();
+ _aerosol.setup(602, 2, 2);
+ _aerosol.setPosition(Common::Point(189, 95));
+ _aerosol.setDetails(600, 27, -1, -1, 1, (SceneItem *) NULL);
}
if (R2_GLOBALS.getFlag(8)) {
@@ -5651,30 +5687,30 @@ void Scene600::postInit(SceneObjectList *OwnerList) {
_item3.setDetails(11, 600, 14, -1, -1);
if (R2_GLOBALS.getFlag(9)) {
- _item1.setDetails(Rect(159, 3, 315, 95), 600, 7, -1, -1, 1, NULL);
+ _background.setDetails(Rect(159, 3, 315, 95), 600, 7, -1, -1, 1, NULL);
} else {
_item4.setDetails(Rect(173, 15, 315, 45), 600, 21, -1, 23, 1, NULL);
- _item1.setDetails(Rect(159, 3, 315, 95), 600, 6, -1, -1, 1, NULL);
+ _background.setDetails(Rect(159, 3, 315, 95), 600, 6, -1, -1, 1, NULL);
}
_item5.setDetails(Rect(0, 0, 320, 200), 600, 0, -1, -1, 1, NULL);
_sceneMode = 600;
if (R2_GLOBALS._sceneManager._previousScene == 700) {
if (R2_GLOBALS.getFlag(6)) {
- setAction(&_sequenceManager1, this, 600, &R2_GLOBALS._player, &_actor5, NULL);
+ setAction(&_sequenceManager1, this, 600, &R2_GLOBALS._player, &_doorway, NULL);
} else if (R2_GLOBALS.getFlag(5)) {
- setAction(&_sequenceManager1, this, 603, &R2_GLOBALS._player, &_actor5, &_actor6, &_actor1, NULL);
+ setAction(&_sequenceManager1, this, 603, &R2_GLOBALS._player, &_doorway, &_laser, &_actor1, NULL);
} else {
- setAction(&_sequenceManager1, this, 602, &R2_GLOBALS._player, &_actor5, &_actor6, &_actor1, NULL);
+ setAction(&_sequenceManager1, this, 602, &R2_GLOBALS._player, &_doorway, &_laser, &_actor1, NULL);
}
} else if (R2_GLOBALS.getFlag(5)) {
R2_GLOBALS._player.setPosition(Common::Point(50, 140));
R2_GLOBALS._player.setStrip(3);
- _actor6.setFrame(_actor6.getFrameCount());
+ _laser.setFrame(_laser.getFrameCount());
signal();
} else {
- _actor5.setFrame(7);
- _actor6.setFrame(7);
+ _doorway.setFrame(7);
+ _laser.setFrame(7);
R2_GLOBALS._player.setPosition(Common::Point(28, 140));
R2_GLOBALS._player.setStrip(5);
signal();
@@ -5703,7 +5739,7 @@ void Scene600::signal() {
R2_GLOBALS._walkRegions.enableRegion(9);
R2_GLOBALS._walkRegions.enableRegion(10);
- R2_INVENTORY.setObjectScene(12, 600);
+ R2_INVENTORY.setObjectScene(R2_AEROSOL, 600);
R2_GLOBALS.setFlag(5);
_actor4._effect = 3;
@@ -5730,12 +5766,12 @@ void Scene600::signal() {
_actor3.remove();
R2_GLOBALS._sceneItems.remove(&_item4);
_actor2.setDetails(600, 21, -1, 23, 4, &_item4);
- _item1.setDetails(600, 7, -1, -1, 3, (SceneItem *) NULL);
+ _background.setDetails(600, 7, -1, -1, 3, (SceneItem *) NULL);
R2_GLOBALS._player.enableControl(CURSOR_USE);
break;
case 614:
R2_GLOBALS._player.enableControl();
- _actor7.remove();
+ _aerosol.remove();
R2_INVENTORY.setObjectScene(12, 1);
R2_GLOBALS._walkRegions.disableRegion(7);
break;
@@ -5753,8 +5789,9 @@ void Scene600::signal() {
}
void Scene600::process(Event &event) {
- if ((!R2_GLOBALS._player._canWalk) && (!R2_GLOBALS.getFlag(6)) && (event.eventType == EVENT_BUTTON_DOWN) && (R2_GLOBALS._events.getCursor() == R2_NEGATOR_GUN)) {
- if (!_actor5.contains(event.mousePos) || (_actor5._frame <= 1)) {
+ if (R2_GLOBALS._player._canWalk && (!R2_GLOBALS.getFlag(6)) && (event.eventType == EVENT_BUTTON_DOWN)
+ && (R2_GLOBALS._events.getCursor() == CURSOR_WALK)) {
+ if (!_doorway.contains(event.mousePos) || (_doorway._frame <= 1)) {
if (R2_GLOBALS.getFlag(5)) {
_field412 += 10;
} else {
@@ -5766,7 +5803,7 @@ void Scene600::process(Event &event) {
} else {
R2_GLOBALS._player.disableControl();
_sceneMode = 613;
- setAction(&_sequenceManager1, this, 613, &R2_GLOBALS._player, &_actor6, NULL);
+ setAction(&_sequenceManager1, this, 613, &R2_GLOBALS._player, &_laser, NULL);
event.handled = true;
}
} else if ((!R2_GLOBALS.getFlag(6)) && (R2_GLOBALS._player._mover) && (_field412 < 10)){
@@ -5778,9 +5815,9 @@ void Scene600::process(Event &event) {
void Scene600::dispatch() {
if ((_field412 != 0) && (_sceneMode != 600) && (_sceneMode != 603) && (_sceneMode != 602)) {
- if ( ((_actor6._strip == 4) && (_actor6._frame > 1))
+ if ( ((_laser._strip == 4) && (_laser._frame > 1))
|| (_sceneMode == 601)
- || ((_sceneMode == 616) && (_actor5._frame > 1)) )
+ || ((_sceneMode == 616) && (_doorway._frame > 1)) )
_field412 = 0;
else {
_field412--;
@@ -5803,7 +5840,7 @@ void Scene600::dispatch() {
}
/*--------------------------------------------------------------------------
- * Scene 700 -
+ * Scene 700 - Lander Bay 2
*
*--------------------------------------------------------------------------*/
Scene700::Scene700() {
@@ -5849,7 +5886,7 @@ bool Scene700::Item12::startAction(CursorType action, Event &event) {
break;
}
- scene->setAction(&scene->_sequenceManager, this, 707, &R2_GLOBALS._player, &scene->_actor5, NULL);
+ scene->setAction(&scene->_sequenceManager, scene, 707, &R2_GLOBALS._player, &scene->_actor5, NULL);
return true;
}
@@ -5910,7 +5947,7 @@ bool Scene700::Actor5::startAction(CursorType action, Event &event) {
case 0:
if ((_strip == 2) && (_frame == 1)) {
R2_GLOBALS._player.disableControl();
- if (R2_GLOBALS._player._position.x <= 100) {
+ if (R2_GLOBALS._player._position.y <= 100) {
scene->_sceneMode = 710;
scene->setAction(&scene->_sequenceManager, scene, 710, &R2_GLOBALS._player, this, NULL);
} else {
@@ -5969,10 +6006,10 @@ bool Scene700::Actor6::startAction(CursorType action, Event &event) {
}
void Scene700::postInit(SceneObjectList *OwnerList) {
+ loadScene(700);
if (R2_GLOBALS._sceneManager._previousScene == 900)
- g_globals->gfxManager()._bounds.moveTo(Common::Point(160, 0));
+ _sceneBounds = Rect(160, 0, 480, 200);
- loadScene(700);
R2_GLOBALS._v558B6.set(60, 0, 260, 200);
SceneExt::postInit();
@@ -5994,7 +6031,7 @@ void Scene700::postInit(SceneObjectList *OwnerList) {
_actor1.postInit();
_actor1.setup(700, 4, 1);
- _actor1.setPosition(Common::Point(355 - ((R2_GLOBALS._v565E3 * 8) / 5), ((R2_GLOBALS._v565E1 + 20 ) / 5) - 12));
+ _actor1.setPosition(Common::Point(355 - ((R2_GLOBALS._electromagnetZoom * 8) / 5), ((R2_GLOBALS._electromagnetChangeAmount + 20 ) / 5) - 12));
_actor1.fixPriority(10);
_actor1.setDetails(700, 12, -1, 14, 1, (SceneItem *) NULL);
@@ -6041,7 +6078,7 @@ void Scene700::postInit(SceneObjectList *OwnerList) {
case 700:
switch (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS)) {
case 0:
- if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70))
+ if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70))
_actor5.setup(701, 2, 1);
else
_actor5.setup(701, 2, 8);
@@ -6158,9 +6195,7 @@ void Scene700::signal() {
}
break;
case 3:
- R2_INVENTORY.setObjectScene(5, 600);
- R2_INVENTORY.setObjectScene(16, 700);
- R2_GLOBALS._player.enableControl();
+ R2_GLOBALS._sceneManager.changeScene(600);
break;
case 4:
_sceneMode = 5;
@@ -6206,7 +6241,7 @@ void Scene700::signal() {
_sceneMode = 17;
_actor5.setup(701, 1, 8);
_actor5.setDetails(700, 38, -1, -1, 3, (SceneItem *) NULL);
- if ((R2_GLOBALS._v565E5 != 0) && (_actor5._position.x == _actor1._position.x + 1) && (_actor5._position.x == 148 - (((R2_GLOBALS._v565E1 + 10) / 5) * 4))) {
+ if ((R2_GLOBALS._v565E5 != 0) && (_actor5._position.x == _actor1._position.x + 1) && (_actor5._position.x == 148 - (((R2_GLOBALS._electromagnetChangeAmount + 10) / 5) * 4))) {
_actor5.animate(ANIM_MODE_6, NULL);
Common::Point pt(_actor5._position.x, _actor1._position.y + 120);
NpcMover *mover = new NpcMover();
@@ -6231,7 +6266,7 @@ void Scene700::signal() {
break;
case 21:
_actor5.fixPriority(77);
- if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70))
+ if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70))
_actor5.animate(ANIM_MODE_6, NULL);
R2_INVENTORY.setObjectScene(R2_ATTRACTOR_CABLE_HARNESS, 700);
@@ -6249,7 +6284,7 @@ void Scene700::signal() {
case 706:
_actor5.setDetails(700, 38, -1, -1, 3, (SceneItem *) NULL);
_actor5.fixPriority(77);
- if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70))
+ if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70))
_actor5.animate(ANIM_MODE_6, NULL);
R2_INVENTORY.setObjectScene(R2_ATTRACTOR_UNIT, 0);
R2_INVENTORY.setObjectScene(R2_ATTRACTOR_CABLE_HARNESS, 700);
@@ -6317,12 +6352,26 @@ bool Scene800::DeviceSlot::startAction(CursorType action, Event &event) {
break;
R2_GLOBALS._player.disableControl();
- scene->_reader.postInit();
+ _lookLineNum = 27;
+ scene->_sceneMode = 809;
if (R2_INVENTORY.getObjectScene(R2_OPTICAL_FIBRE) == 800)
- scene->setAction(&scene->_sequenceManager1, scene, 814, &R2_GLOBALS._player, &scene->_reader, &scene->_opticalFibre, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 815, &R2_GLOBALS._player, &scene->_reader, &scene->_opticalFibre, NULL);
else
- scene->setAction(&scene->_sequenceManager1, scene, 804, &R2_GLOBALS._player, &scene->_reader, NULL);
+ scene->setAction(&scene->_sequenceManager1, scene, 809, &R2_GLOBALS._player, &scene->_reader, NULL);
+ return true;
+ case R2_READER:
+ R2_GLOBALS._player.disableControl();
+ scene->_reader.postInit();
+ scene->_sceneMode = 804;
+
+ if (R2_INVENTORY.getObjectScene(R2_OPTICAL_FIBRE) == 800) {
+ scene->setAction(&scene->_sequenceManager1, scene, 814, &R2_GLOBALS._player,
+ &scene->_reader, &scene->_opticalFibre, NULL);
+ } else {
+ scene->setAction(&scene->_sequenceManager1, scene, 804, &R2_GLOBALS._player,
+ &scene->_reader, NULL);
+ }
return true;
default:
break;
@@ -6416,8 +6465,8 @@ bool Scene800::Cabinet::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
void Scene800::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(800);
+ SceneExt::postInit();
_door.postInit();
_door.setVisage(800);
@@ -6826,8 +6875,9 @@ void Scene825::doButtonPress(int buttonId) {
_sceneText.setup(NO_TREATMENT_REQUIRED);
} else {
_button6._buttonId = 5;
-
+ _sceneMode = 827;
_object5.postInit();
+
setAction(&_sequenceManager1, this, 827, &_object5, NULL);
}
} else {
@@ -7006,8 +7056,8 @@ bool Scene850::Panel::startAction(CursorType action, Event &event) {
/*--------------------------------------------------------------------------*/
void Scene850::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
loadScene(850);
+ SceneExt::postInit();
_liftDoor.postInit();
_liftDoor.setup(850, 2, 1);
@@ -7103,44 +7153,47 @@ void Scene850::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 900 -
+ * Scene 900 - Lander Bay 2 - Crane Controls
*
*--------------------------------------------------------------------------*/
-Scene900::Actor4::Actor4() {
- _fieldA4 = 0;
+
+Scene900::Button::Button() {
+ _buttonId = 0;
}
-void Scene900::Actor4::synchronize(Serializer &s) {
+void Scene900::Button::synchronize(Serializer &s) {
SceneActor::synchronize(s);
- s.syncAsSint16LE(_fieldA4);
+ s.syncAsSint16LE(_buttonId);
}
-void Scene900::Actor4::sub96135(int arg1) {
- _fieldA4 = arg1;
+
+void Scene900::Button::initButton(int buttonId) {
+ _buttonId = buttonId;
+ postInit();
setDetails(900, -1, -1, -1, 2, (SceneItem *) NULL);
}
Scene900::Scene900() {
_field412 = 0;
- _field414 = 0;
- _field416 = 0;
+ _magnetChangeAmount.x = 0;
+ _magnetChangeAmount.y = 0;
}
void Scene900::synchronize(Serializer &s) {
SceneExt::synchronize(s);
s.syncAsSint16LE(_field412);
- s.syncAsSint16LE(_field414);
- s.syncAsSint16LE(_field416);
+ s.syncAsSint16LE(_magnetChangeAmount.x);
+ s.syncAsSint16LE(_magnetChangeAmount.y);
}
-bool Scene900::Actor4::startAction(CursorType action, Event &event) {
+bool Scene900::Button::startAction(CursorType action, Event &event) {
Scene900 *scene = (Scene900 *)R2_GLOBALS._sceneManager._scene;
if (action == CURSOR_USE) {
R2_GLOBALS._sound2.play(14);
- switch (_fieldA4) {
+ switch (_buttonId) {
case 2:
if (scene->_field412 == 1) {
scene->_sceneMode = 2;
@@ -7150,15 +7203,15 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) {
scene->_aSound1.play(30);
setup(900, 3, 11);
R2_GLOBALS._v565E5 = 1;
- if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS == 700)) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70) && (scene->_actor2._animateMode != ANIM_MODE_6)) {
+ if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS == 700)) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70) && (scene->_actor2._animateMode != ANIM_MODE_6)) {
scene->_actor2.animate(ANIM_MODE_6, NULL);
} else {
- if (((scene->_actor3._percent * 49) / 100) + scene->_actor3._position.x == scene->_actor2._position.x) {
- if (scene->_actor2._position.x == 166 - (R2_GLOBALS._v565E3 / 15)) {
+ if (((scene->_electromagnet._percent * 49) / 100) + scene->_electromagnet._position.x == scene->_actor2._position.x) {
+ if (scene->_actor2._position.x == 166 - (R2_GLOBALS._electromagnetZoom / 15)) {
R2_GLOBALS._player.disableControl();
scene->_sceneMode = 4;
- scene->_actor2._moveDiff.y = (scene->_actor2._position.y - (scene->_actor3._position.y + ((scene->_actor3._percent * 3) / 10) - 2)) / 9;
- Common::Point pt(scene->_actor3._position.x + ((scene->_actor3._percent * 49) / 100), scene->_actor3._position.y + ((scene->_actor3._percent * 3) / 10) - 2);
+ scene->_actor2._moveDiff.y = (scene->_actor2._position.y - (scene->_electromagnet._position.y + ((scene->_electromagnet._percent * 3) / 10) - 2)) / 9;
+ Common::Point pt(scene->_electromagnet._position.x + ((scene->_electromagnet._percent * 49) / 100), scene->_electromagnet._position.y + ((scene->_electromagnet._percent * 3) / 10) - 2);
NpcMover *mover = new NpcMover();
scene->_actor2.addMover(mover, &pt, this);
scene->_actor2.animate(ANIM_MODE_6, NULL);
@@ -7179,7 +7232,7 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) {
scene->_sceneMode = 5;
scene->_actor2.animate(ANIM_MODE_5, NULL);
scene->_actor2._moveDiff.y = (166 - scene->_actor2._position.y) / 9;
- Common::Point pt(scene->_actor2._position.x, 166 - (R2_GLOBALS._v565E3 / 15));
+ Common::Point pt(scene->_actor2._position.x, 166 - (R2_GLOBALS._electromagnetZoom / 15));
NpcMover *mover = new NpcMover();
scene->_actor2.addMover(mover, &pt, this);
}
@@ -7196,30 +7249,30 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) {
return true;
break;
case 4:
- if ((scene->_field416 == 0) && (scene->_field414 == 0) && (R2_GLOBALS._v565E3 != 0)) {
+ if ((scene->_magnetChangeAmount.y == 0) && (scene->_magnetChangeAmount.x == 0) && (R2_GLOBALS._electromagnetZoom != 0)) {
scene->_aSound1.play(38);
- scene->_field416 = -5;
+ scene->_magnetChangeAmount.y = -5;
}
return true;
break;
case 5:
- if ((scene->_field416 == 0) && (scene->_field414 == 0) && (R2_GLOBALS._v565E3 < 135)) {
+ if ((scene->_magnetChangeAmount.y == 0) && (scene->_magnetChangeAmount.x == 0) && (R2_GLOBALS._electromagnetZoom < 135)) {
scene->_aSound1.play(38);
- scene->_field416 = 5;
+ scene->_magnetChangeAmount.y = 5;
}
return true;
break;
case 6:
- if ((scene->_field416 == 0) && (scene->_field414 == 0) && (R2_GLOBALS._v565E1 > -10)) {
+ if ((scene->_magnetChangeAmount.y == 0) && (scene->_magnetChangeAmount.x == 0) && (R2_GLOBALS._electromagnetChangeAmount > -10)) {
scene->_aSound1.play(38);
- scene->_field414 = -5;
+ scene->_magnetChangeAmount.x = -5;
}
return true;
break;
case 7:
- if ((scene->_field416 == 0) && (scene->_field414 == 0) && (R2_GLOBALS._v565E1 < 20)) {
+ if ((scene->_magnetChangeAmount.y == 0) && (scene->_magnetChangeAmount.x == 0) && (R2_GLOBALS._electromagnetChangeAmount < 20)) {
scene->_aSound1.play(38);
- scene->_field414 = 5;
+ scene->_magnetChangeAmount.x = 5;
}
return true;
break;
@@ -7234,12 +7287,12 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) {
default:
if (scene->_field412 == 1) {
R2_GLOBALS._player.disableControl();
- scene->_actor5.remove();
- scene->_actor6.remove();
- scene->_actor7.remove();
- scene->_actor8.remove();
- scene->_actor9.remove();
- scene->_actor10.remove();
+ scene->_button2.remove();
+ scene->_button3.remove();
+ scene->_button4.remove();
+ scene->_button5.remove();
+ scene->_button6.remove();
+ scene->_button7.remove();
R2_GLOBALS._sound2.play(37);
scene->_sceneMode = 901;
scene->setAction(&scene->_sequenceManager1, scene, 901, &scene->_actor1, this ,NULL);
@@ -7252,10 +7305,8 @@ bool Scene900::Actor4::startAction(CursorType action, Event &event) {
break;
}
} else if (action == CURSOR_LOOK) {
- if ((_fieldA4 == 2) && (scene->_field412 == 2))
- SceneItem::display(900, 21, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
- else
- SceneItem::display(900, _fieldA4, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
+ SceneItem::display(900, ((_buttonId == 2) && (scene->_field412 == 2)) ? 21 : _buttonId + 11,
+ SET_WIDTH, 280, SET_X, 160, SET_POS_MODE, 1, SET_Y, 20, SET_EXT_BGCOLOR, 7, -999);
return true;
} else {
return SceneActor::startAction(action, event);
@@ -7275,16 +7326,15 @@ void Scene900::postInit(SceneObjectList *OwnerList) {
_actor1.postInit();
_actor1.setDetails(900, 3, -1, -1, 1, (SceneItem *) NULL);
- _field414 = 0;
- _field416 = 0;
+ _magnetChangeAmount.x = 0;
+ _magnetChangeAmount.y = 0;
- _actor3.postInit();
- _actor3.fixPriority(1);
- // useless, the original use it for debugging purposes: strcpy(_actor3._actorName, "Crane");
- _actor3.setup(900, 1, 2);
- _actor3.setPosition(Common::Point(89, 0));
- _actor3._effect = 1;
- _actor3.setDetails(900, 6, -1, 8, 1, (SceneItem *) NULL);
+ _electromagnet.postInit();
+ _electromagnet.fixPriority(1);
+ _electromagnet.setup(900, 1, 2);
+ _electromagnet.setPosition(Common::Point(89, 0));
+ _electromagnet._effect = 1;
+ _electromagnet.setDetails(900, 6, -1, 8, 1, (SceneItem *) NULL);
if ((R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) != 1) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) != 1)) {
_actor2.postInit();
@@ -7294,7 +7344,7 @@ void Scene900::postInit(SceneObjectList *OwnerList) {
if (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) {
if (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) != 700) {
_actor2.setup(901, 3, 2);
- } else if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70)) {
+ } else if ((R2_GLOBALS._v565E5 != 0) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70)) {
_actor2.setup(901, 2, 1);
} else {
_actor2.setup(901, 2, 8);
@@ -7306,7 +7356,7 @@ void Scene900::postInit(SceneObjectList *OwnerList) {
if (R2_GLOBALS._v565E7 == 0) {
_actor2.setup(901, 1, 8);
// Original set two times the same values: skipped
- _actor2.setPosition(Common::Point((((100 - ((R2_GLOBALS._v565EB * 350) / 100)) * 49) / 100) + ((R2_GLOBALS._v565E9 * _actor3._percent * 6) / 100) + 89, 166 - (R2_GLOBALS._v565EB / 3)));
+ _actor2.setPosition(Common::Point((((100 - ((R2_GLOBALS._v565EB * 350) / 100)) * 49) / 100) + ((R2_GLOBALS._v565E9 * _electromagnet._percent * 6) / 100) + 89, 166 - (R2_GLOBALS._v565EB / 3)));
_actor2.changeZoom(((100 - ((R2_GLOBALS._v565EB * 350) / 100) + 52) / 10) * 10);
}
}
@@ -7329,68 +7379,68 @@ void Scene900::signal() {
_field412 = 1;
R2_GLOBALS._sound2.play(37);
- _actor5.remove();
- _actor6.remove();
- _actor7.remove();
- _actor8.remove();
- _actor9.remove();
- _actor10.remove();
+ _button2.remove();
+ _button3.remove();
+ _button4.remove();
+ _button5.remove();
+ _button6.remove();
+ _button7.remove();
- _actor5.sub96135(2);
- _actor5.setup(900, 2, 1);
- _actor5.setPosition(Common::Point(36, 166));
+ _button2.initButton(2);
+ _button2.setup(900, 2, 1);
+ _button2.setPosition(Common::Point(36, 166));
- _actor6.sub96135(3);
- _actor6.setup(900, 2, 5);
- _actor6.setPosition(Common::Point(117, 166));
+ _button3.initButton(3);
+ _button3.setup(900, 2, 5);
+ _button3.setPosition(Common::Point(117, 166));
break;
case 2:
_field412 = 2;
- _actor5.remove();
- _actor6.remove();
+ _button2.remove();
+ _button3.remove();
- _actor5.sub96135(2);
+ _button2.initButton(2);
if (R2_GLOBALS._v565E5 == 0)
- _actor5.setup(900, 3, 9);
+ _button2.setup(900, 3, 9);
else
- _actor5.setup(900, 3, 11);
- _actor5.setPosition(Common::Point(36, 166));
+ _button2.setup(900, 3, 11);
+ _button2.setPosition(Common::Point(36, 166));
- _actor7.sub96135(5);
- _actor7.setup(900, 3, 3);
- _actor7.setPosition(Common::Point(76, 134));
+ _button4.initButton(5);
+ _button4.setup(900, 3, 3);
+ _button4.setPosition(Common::Point(76, 134));
- _actor8.sub96135(4);
- _actor8.setup(900, 3, 7);
- _actor8.setPosition(Common::Point(76, 156));
+ _button5.initButton(4);
+ _button5.setup(900, 3, 7);
+ _button5.setPosition(Common::Point(76, 156));
- _actor9.sub96135(6);
- _actor9.setup(900, 3, 1);
- _actor9.setPosition(Common::Point(55, 144));
+ _button6.initButton(6);
+ _button6.setup(900, 3, 1);
+ _button6.setPosition(Common::Point(55, 144));
- _actor10.sub96135(7);
- _actor10.setup(900, 3, 5);
- _actor10.setPosition(Common::Point(99, 144));
+ _button7.initButton(7);
+ _button7.setup(900, 3, 5);
+ _button7.setPosition(Common::Point(99, 144));
break;
case 3:
_field412 = 3;
- _actor5.remove();
- _actor6.remove();
- _actor7.remove();
- _actor8.remove();
- _actor9.remove();
- _actor10.remove();
+ _button2.remove();
+ _button3.remove();
+ _button4.remove();
+ _button5.remove();
+ _button6.remove();
+ _button7.remove();
- _actor5.sub96135(8);
- _actor5.setup(900, 4, 1);
- _actor5.setPosition(Common::Point(36, 166));
+ _button2.initButton(8);
+ _button2.setup(900, 4, 1);
+ _button2.setPosition(Common::Point(36, 166));
- _actor6.sub96135(9);
- _actor6.setup(900, 4, 5);
- _actor6.setPosition(Common::Point(117, 166));
+ _button3.initButton(9);
+ _button3.setup(900, 4, 5);
+ _button3.setPosition(Common::Point(117, 166));
break;
case 4:
_sceneMode = 0;
@@ -7404,9 +7454,9 @@ void Scene900::signal() {
_actor1.setup(900, 1, 1);
- _actor4.sub96135(1);
- _actor4.setup(900, 1, 3);
- _actor4.setPosition(Common::Point(77, 168));
+ _button1.initButton(1);
+ _button1.setup(900, 1, 3);
+ _button1.setPosition(Common::Point(77, 168));
_sceneMode = 1;
signal();
@@ -7425,26 +7475,28 @@ void Scene900::signal() {
}
void Scene900::dispatch() {
- if (_field416 != 0) {
- if (_field416 < 0) {
- R2_GLOBALS._v565E3--;
- ++_field416;
+ if (_magnetChangeAmount.y != 0) {
+ if (_magnetChangeAmount.y < 0) {
+ R2_GLOBALS._electromagnetZoom--;
+ ++_magnetChangeAmount.y;
} else {
- ++R2_GLOBALS._v565E3;
- _field416--;
+ ++R2_GLOBALS._electromagnetZoom;
+ _magnetChangeAmount.y--;
}
}
- if (_field414 != 0) {
- R2_GLOBALS._v565E1--;
- ++_field414;
- } else {
- ++R2_GLOBALS._v565E1;
- _field414++;
+ if (_magnetChangeAmount.x != 0) {
+ if (_magnetChangeAmount.x < 0) {
+ R2_GLOBALS._electromagnetChangeAmount--;
+ ++_magnetChangeAmount.x;
+ } else {
+ ++R2_GLOBALS._electromagnetChangeAmount;
+ _magnetChangeAmount.x--;
+ }
}
if (R2_GLOBALS._sceneObjects->contains(&_actor2)) {
- if ((R2_GLOBALS._v565E5 != 0) && (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (R2_GLOBALS._v565E1 == 20) && (R2_GLOBALS._v565E3 == 70)) {
+ if ((R2_GLOBALS._v565E5 != 0) && (R2_INVENTORY.getObjectScene(R2_CABLE_HARNESS) == 0) && (R2_INVENTORY.getObjectScene(R2_ATTRACTOR_CABLE_HARNESS) == 700) && (R2_GLOBALS._electromagnetChangeAmount == 20) && (R2_GLOBALS._electromagnetZoom == 70)) {
if ((_actor2._frame > 1) && (_actor2._animateMode != ANIM_MODE_6))
_actor2.animate(ANIM_MODE_6, NULL);
} else {
@@ -7453,17 +7505,17 @@ void Scene900::dispatch() {
}
}
- _actor3.changeZoom(100 - ((R2_GLOBALS._v565E3 * 70) / 100));
- _actor3.setPosition(Common::Point(((_actor3._percent * R2_GLOBALS._v565E1 * 6) / 100) + 89, R2_GLOBALS._v565E3));
+ _electromagnet.changeZoom(100 - ((R2_GLOBALS._electromagnetZoom * 70) / 100));
+ _electromagnet.setPosition(Common::Point(((_electromagnet._percent * R2_GLOBALS._electromagnetChangeAmount * 6) / 100) + 89, R2_GLOBALS._electromagnetZoom));
if ((R2_GLOBALS._sceneObjects->contains(&_actor2)) && (R2_GLOBALS._v565E7 != 0) && (!_actor2._mover) && (_actor2._animateMode == ANIM_MODE_NONE)) {
- _actor2.setPosition(Common::Point(_actor3._position.x + ((_actor3._percent * 49) / 100), _actor3._position.y + ((_actor3._percent * 3) / 10)));
- if (R2_GLOBALS._v565E3 >= 75) {
+ _actor2.setPosition(Common::Point(_electromagnet._position.x + ((_electromagnet._percent * 49) / 100), _electromagnet._position.y + ((_electromagnet._percent * 3) / 10)));
+ if (R2_GLOBALS._electromagnetZoom >= 75) {
_actor2.setup(901, 1, 1);
- _actor2.changeZoom(((_actor3._percent + 52) / 10) * 10);
+ _actor2.changeZoom(((_electromagnet._percent + 52) / 10) * 10);
} else {
_actor2.setup(901, 5, 1);
- _actor2.changeZoom(((_actor3._percent / 10) * 10) + 30);
+ _actor2.changeZoom(((_electromagnet._percent / 10) * 10) + 30);
}
}
Scene::dispatch();
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.h b/engines/tsage/ringworld2/ringworld2_scenes0.h
index 2f52f9578f..80dab89b32 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.h
@@ -126,7 +126,7 @@ class Scene125: public SceneExt {
};
/* Items */
- class Item4: public NamedHotspot {
+ class DiskSlot: public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
@@ -135,8 +135,8 @@ public:
ScenePalette _palette;
ASoundExt _sound1;
NamedHotspot _background, _item2, _item3;
- Item4 _item4;
- SceneActor _object1, _object2, _object3, _object4, _object5, _object6, _object7;
+ DiskSlot _diskSlot;
+ SceneActor _object1, _object2, _object3, _object4, _object5, _object6, _infoDisk;
Icon _icon1, _icon2, _icon3, _icon4, _icon5, _icon6;
SequenceManager _sequenceManager;
SceneText _sceneText;
@@ -615,7 +615,7 @@ public:
};
class Scene600 : public SceneExt {
- class Item1 : public NamedHotspot {
+ class CompartmentHotspot : public NamedHotspot {
public:
virtual bool startAction(CursorType action, Event &event);
};
@@ -628,17 +628,17 @@ class Scene600 : public SceneExt {
public:
virtual void signal();
virtual bool startAction(CursorType action, Event &event);
- virtual void draw();
+ virtual GfxSurface getFrame();
};
- class Actor5 : public SceneActor {
+ class Doorway : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor6 : public SceneActor {
+ class Laser : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
- class Actor7 : public SceneActor {
+ class Aerosol : public SceneActor {
public:
virtual bool startAction(CursorType action, Event &event);
};
@@ -648,24 +648,24 @@ class Scene600 : public SceneExt {
};
public:
int _field412;
- Item1 _item1;
- Item1 _item2;
- Item1 _item3;
+ CompartmentHotspot _background;
+ CompartmentHotspot _item2;
+ CompartmentHotspot _item3;
Item4 _item4;
- Item1 _item5;
+ CompartmentHotspot _item5;
BackgroundSceneObject _object1;
SceneActor _actor1;
SceneActor _actor2;
SceneActor _actor3;
Actor4 _actor4;
- Actor5 _actor5;
- Actor6 _actor6;
- Actor7 _actor7;
+ Doorway _doorway;
+ Laser _laser;
+ Aerosol _aerosol;
Actor8 _actor8;
ASoundExt _aSound1;
SequenceManager _sequenceManager1;
SequenceManager _sequenceManager2;
- byte _fieldAD2[256];
+ byte _pixelMap[256];
Scene600();
virtual void postInit(SceneObjectList *OwnerList = NULL);
@@ -865,30 +865,29 @@ public:
};
class Scene900 : public SceneExt {
- class Actor4 : public SceneActor {
+ class Button : public SceneActor {
public:
- int _fieldA4;
+ int _buttonId;
- Actor4();
- void sub96135(int arg1);
+ Button();
+ void initButton(int buttonId);
virtual void synchronize(Serializer &s);
virtual bool startAction(CursorType action, Event &event);
};
public:
int _field412;
- int _field414;
- int _field416;
+ Common::Point _magnetChangeAmount;
NamedHotspot _item1;
SceneActor _actor1;
SceneActor _actor2;
- SceneActor _actor3;
- Actor4 _actor4;
- Actor4 _actor5;
- Actor4 _actor6;
- Actor4 _actor7;
- Actor4 _actor8;
- Actor4 _actor9;
- Actor4 _actor10;
+ SceneActor _electromagnet;
+ Button _button1;
+ Button _button2;
+ Button _button3;
+ Button _button4;
+ Button _button5;
+ Button _button6;
+ Button _button7;
ASoundExt _aSound1;
SequenceManager _sequenceManager1;
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.cpp b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
index af62ab6916..ba62a119a8 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.cpp
@@ -858,16 +858,17 @@ void Scene1100::saveCharacter(int characterIndex) {
}
/*--------------------------------------------------------------------------
- * Scene 1200 -
+ * Scene 1200 - Air Ducts Maze
*
*--------------------------------------------------------------------------*/
+
Scene1200::Scene1200() {
_field412 = 0;
_field414 = 0;
_field416 = 0;
_field418 = 0;
_field41A = 0;
- _field41C = 1; //CHECKME: Only if fixup_flag == 6??
+ _fixupMaze = false;
}
void Scene1200::synchronize(Serializer &s) {
@@ -878,20 +879,13 @@ void Scene1200::synchronize(Serializer &s) {
s.syncAsSint16LE(_field416);
s.syncAsSint16LE(_field418);
s.syncAsSint16LE(_field41A);
- s.syncAsSint16LE(_field41C);
-}
-
-Scene1200::Area1::Area1() {
- _field20 = 0;
+ s.syncAsSint16LE(_fixupMaze);
}
-void Scene1200::Area1::synchronize(Serializer &s) {
- SceneArea::synchronize(s);
-
- s.syncAsByte(_field20);
+Scene1200::LaserPanel::LaserPanel() {
}
-void Scene1200::Area1::Actor3::init(int state) {
+void Scene1200::LaserPanel::Jumper::init(int state) {
_state = state;
SceneActor::postInit();
@@ -912,6 +906,7 @@ void Scene1200::Area1::Actor3::init(int state) {
default:
break;
}
+ break;
case 2:
switch (R2_GLOBALS._v56AA7) {
case 1:
@@ -929,6 +924,7 @@ void Scene1200::Area1::Actor3::init(int state) {
default:
break;
}
+ break;
case 3:
switch (R2_GLOBALS._v56AA8) {
case 1:
@@ -942,6 +938,7 @@ void Scene1200::Area1::Actor3::init(int state) {
default:
break;
}
+ break;
default:
break;
}
@@ -949,7 +946,7 @@ void Scene1200::Area1::Actor3::init(int state) {
setDetails(1200, 12, -1, -1, 2, (SceneItem *) NULL);
}
-bool Scene1200::Area1::Actor3::startAction(CursorType action, Event &event) {
+bool Scene1200::LaserPanel::Jumper::startAction(CursorType action, Event &event) {
if (action != CURSOR_USE)
return SceneActor::startAction(action, event);
@@ -1018,7 +1015,7 @@ bool Scene1200::Area1::Actor3::startAction(CursorType action, Event &event) {
return true;
}
-void Scene1200::Area1::postInit(SceneObjectList *OwnerList) {
+void Scene1200::LaserPanel::postInit(SceneObjectList *OwnerList) {
Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
scene->_field41A = 1;
@@ -1026,81 +1023,35 @@ void Scene1200::Area1::postInit(SceneObjectList *OwnerList) {
proc12(1003, 1, 1, 100, 40);
proc13(1200, 11, -1, -1);
R2_GLOBALS._sound2.play(259);
- _actor3.init(1);
- _actor4.init(2);
- _actor5.init(3);
+ _jumper1.init(1);
+ _jumper2.init(2);
+ _jumper3.init(3);
R2_GLOBALS._player._canWalk = false;
}
-void Scene1200::Area1::remove() {
+void Scene1200::LaserPanel::remove() {
Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
scene->_field41A = 0;
warning("Unexpected _sceneAreas.remove() call");
-// scene->_sceneAreas.remove(&_actor3);
-// scene->_sceneAreas.remove(&_actor4);
-// scene->_sceneAreas.remove(&_actor5);
- _actor3.remove();
- _actor4.remove();
- _actor5.remove();
+// scene->_sceneAreas.remove(&_jumper1);
+// scene->_sceneAreas.remove(&_jumper2);
+// scene->_sceneAreas.remove(&_jumper3);
+ _jumper1.remove();
+ _jumper2.remove();
+ _jumper3.remove();
// sub201EA
R2_GLOBALS._sceneItems.remove((SceneItem *)this);
- _actor2.remove();
+ _object1.remove();
SceneArea::remove();
R2_GLOBALS._insetUp--;
- //
R2_GLOBALS._player._canWalk = true;
}
-void Scene1200::Area1::process(Event &event) {
- if (_field20 != R2_GLOBALS._insetUp)
- return;
-
- CursorType cursor = R2_GLOBALS._events.getCursor();
-
- if (_actor2._bounds.contains(event.mousePos.x + g_globals->gfxManager()._bounds.left , event.mousePos.y)) {
- if (cursor == _cursorNum) {
- warning("TODO: _cursorState = ???");
- R2_GLOBALS._events.setCursor(_savedCursorNum); //, _cursorState);
- }
- } else if (event.mousePos.y < 168) {
- if (cursor != _cursorNum) {
- _savedCursorNum = cursor;
- warning("TODO: _cursorState = ???");
- R2_GLOBALS._events.setCursor(CURSOR_INVALID);
- }
- if (event.eventType == EVENT_BUTTON_DOWN) {
- event.handled = true;
- warning("TODO: _cursorState = ???");
- R2_GLOBALS._events.setCursor(_savedCursorNum); //, _cursorState);
- remove();
- }
- }
-}
-
-void Scene1200::Area1::proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY) {
- Scene1200 *scene = (Scene1200 *)R2_GLOBALS._sceneManager._scene;
-
- _actor2.postInit();
- _actor2.setup(visage, stripFrameNum, frameNum);
- _actor2.setPosition(Common::Point(posX, posY));
- _actor2.fixPriority(250);
- _cursorNum = CURSOR_INVALID;
- scene->_sceneAreas.push_front(this);
- ++R2_GLOBALS._insetUp;
- _field20 = R2_GLOBALS._insetUp;
-}
-
-void Scene1200::Area1::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
- _actor2.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
-}
-
void Scene1200::postInit(SceneObjectList *OwnerList) {
- Rect tmpRect;
-
loadScene(1200);
SceneExt::postInit();
@@ -1112,7 +1063,6 @@ void Scene1200::postInit(SceneObjectList *OwnerList) {
_field416 = 0;
_field418 = 0;
_field41A = 0;
- _field41C = 0;
if ((R2_GLOBALS._v56AA6 == 1) && (R2_GLOBALS._v56AA7 == 1) && (R2_GLOBALS._v56AA8 == 1))
_field418 = 1;
@@ -1133,14 +1083,10 @@ void Scene1200::postInit(SceneObjectList *OwnerList) {
_actor1.postInit();
_actor1.hide();
- tmpRect.set(110, 20, 210, 120);
- _object1.sub9EDE8(tmpRect);
+ _mazeUI.setDisplayBounds(Rect(110, 20, 210, 120));
- _object1.sub51AE9(1);
- _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
- warning("int unk = set_pane_p(_paneNumber);");
- _object1.sub51B02();
- warning("set_pane_p(unk);");
+ _mazeUI.load(1);
+ _mazeUI.setMazePosition(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
R2_GLOBALS._player.enableControl();
_item1.setDetails(Rect(0, 0, 320, 200), 1200, 0, 1, 2, 1, NULL);
@@ -1337,7 +1283,7 @@ void Scene1200::signal() {
case 111:
// No break on purpose
case 116:
- R2_GLOBALS._player.setup(3157, 3, 1);
+ R2_GLOBALS._player.setup(3157, 4, 1);
R2_GLOBALS._player.animate(ANIM_MODE_5, this);
break;
case 78:
@@ -1396,50 +1342,52 @@ void Scene1200::process(Event &event) {
return;
if (event.eventType == EVENT_BUTTON_DOWN) {
- _object1.sub9EE22(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4);
- int unk = _object1.sub51AF8(event.mousePos);
+ Common::Point cellPos(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4);
+ _mazeUI.pixelToCellXY(cellPos);
+
+ int cellId = _mazeUI.getCellFromPixelXY(event.mousePos);
switch (R2_GLOBALS._events.getCursor()) {
- case CURSOR_ARROW:
+ case CURSOR_WALK:
event.handled = true;
if ((event.mousePos.x > 179) && (event.mousePos.x < 210) && (event.mousePos.y > 50) && (event.mousePos.y < 89))
- sub9DAD6(1);
+ startCrawling(CRAWL_EAST);
if ((event.mousePos.x > 109) && (event.mousePos.x < 140) && (event.mousePos.y > 50) && (event.mousePos.y < 89))
- sub9DAD6(2);
+ startCrawling(CRAWL_WEST);
if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 89) && (event.mousePos.y < 120))
- sub9DAD6(3);
+ startCrawling(CRAWL_SOUTH);
if ((event.mousePos.x > 140) && (event.mousePos.x < 179) && (event.mousePos.y > 19) && (event.mousePos.y < 50))
- sub9DAD6(4);
+ startCrawling(CRAWL_NORTH);
break;
case CURSOR_USE:
- if (unk > 36) {
- if ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 33))
- || ((R2_GLOBALS._v56AA2 == 7) && (R2_GLOBALS._v56AA4 == 33))
- || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 41))
- || ((R2_GLOBALS._v56AA2 == 5) && (R2_GLOBALS._v56AA4 == 5))
- || ((R2_GLOBALS._v56AA2 == 13) && (R2_GLOBALS._v56AA4 == 21))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 21))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 5))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 9))
- || ((R2_GLOBALS._v56AA2 == 29) && (R2_GLOBALS._v56AA4 == 17))
- || ((R2_GLOBALS._v56AA2 == 33) && (R2_GLOBALS._v56AA4 == 17))
- || ((R2_GLOBALS._v56AA2 == 35) && (R2_GLOBALS._v56AA4 == 17))
- || ((R2_GLOBALS._v56AA2 == 41) && (R2_GLOBALS._v56AA4 == 21)) ) {
- _area1.postInit();
+ if (cellId > 36) {
+ if ( ((cellPos.x == 3) && (cellPos.y == 33))
+ || ((cellPos.x == 7) && (cellPos.y == 33))
+ || ((cellPos.x == 33) && (cellPos.y == 41))
+ || ((cellPos.x == 5) && (cellPos.y == 5))
+ || ((cellPos.x == 13) && (cellPos.y == 21))
+ || ((cellPos.x == 17) && (cellPos.y == 21))
+ || ((cellPos.x == 17) && (cellPos.y == 5))
+ || ((cellPos.x == 17) && (cellPos.y == 9))
+ || ((cellPos.x == 29) && (cellPos.y == 17))
+ || ((cellPos.x == 33) && (cellPos.y == 17))
+ || ((cellPos.x == 35) && (cellPos.y == 17))
+ || ((cellPos.x == 41) && (cellPos.y == 21)) ) {
+ _laserPanel.postInit();
event.handled = true;
}
}
- if ((unk == 1) || (unk == 4) || (unk == 11) || (unk == 14)) {
- if ( ((R2_GLOBALS._v56AA2 == 3) && (R2_GLOBALS._v56AA4 == 9))
- || ((R2_GLOBALS._v56AA2 == 11) && (R2_GLOBALS._v56AA4 == 27))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 7))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 27))
- || ((R2_GLOBALS._v56AA2 == 17) && (R2_GLOBALS._v56AA4 == 33))
- || (R2_GLOBALS._v56AA2 == 33) ) {
- switch (R2_GLOBALS._v56AA2) {
+ if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) {
+ if ( ((cellPos.x == 3) && (cellPos.y == 9))
+ || ((cellPos.x == 11) && (cellPos.y == 27))
+ || ((cellPos.x == 17) && (cellPos.y == 7))
+ || ((cellPos.x == 17) && (cellPos.y == 27))
+ || ((cellPos.x == 17) && (cellPos.y == 33))
+ || (cellPos.x == 33) ) {
+ switch (cellPos.x) {
case 3:
R2_GLOBALS._sceneManager.changeScene(3150);
break;
@@ -1458,23 +1406,25 @@ void Scene1200::process(Event &event) {
}
break;
case CURSOR_LOOK:
- if ((unk == 1) || (unk == 4) || (unk == 11) || (unk == 14)) {
+ if ((cellId == 1) || (cellId == 4) || (cellId == 11) || (cellId == 14)) {
event.handled = true;
- switch (R2_GLOBALS._v56AA2) {
+ switch (cellPos.x) {
case 3:
+ // It was your cell.
SceneItem::display(1200, 8, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
break;
case 9:
R2_GLOBALS._sceneManager.changeScene(3240);
break;
case 11:
- if (R2_GLOBALS._v56AA4 == 27)
+ if (cellPos.y == 27)
R2_GLOBALS._sceneManager.changeScene(3210);
else
+ // A vent grill
SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
break;
case 17:
- switch (R2_GLOBALS._v56AA4) {
+ switch (cellPos.y) {
case 5:
R2_GLOBALS._sceneManager.changeScene(3230);
break;
@@ -1485,6 +1435,7 @@ void Scene1200::process(Event &event) {
R2_GLOBALS._sceneManager.changeScene(3200);
break;
default:
+ // A vent grill
SceneItem::display(1200, 10, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
break;
}
@@ -1496,7 +1447,8 @@ void Scene1200::process(Event &event) {
break;
}
}
- if (unk > 36) {
+ if (cellId > 36) {
+ // "An anti-pest laser"
event.handled = true;
SceneItem::display(1200, 9, 0, 280, 1, 160, 9, 1, 2, 20, 7, 7, -999);
}
@@ -1516,19 +1468,19 @@ void Scene1200::process(Event &event) {
switch (event.kbd.keycode) {
case Common::KEYCODE_1:
warning("FIXME: keycode = 0x4800");
- sub9DAD6(4);
+ startCrawling(CRAWL_NORTH);
break;
case Common::KEYCODE_2:
warning("FIXME: keycode = 0x4B00");
- sub9DAD6(2);
+ startCrawling(CRAWL_WEST);
break;
case Common::KEYCODE_3:
warning("FIXME: keycode = 0x4D00");
- sub9DAD6(1);
+ startCrawling(CRAWL_EAST);
break;
case Common::KEYCODE_4:
warning("FIXME: keycode = 0x5000");
- sub9DAD6(3);
+ startCrawling(CRAWL_SOUTH);
break;
default:
event.handled = false;
@@ -1543,13 +1495,13 @@ void Scene1200::process(Event &event) {
void Scene1200::dispatch() {
Rect tmpRect;
Scene::dispatch();
- if (_field41C != 0) {
- _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
- warning("int unk = set_pane_p(_paneNumber);");
- _object1.sub51B02();
+
+ if (_fixupMaze) {
+ _mazeUI.setMazePosition(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
+
warning("_gfxManager.sub294AC(unk);");
warning("tmpRect.sub14DF3();");
- _field41C = 0;
+ _fixupMaze = false;
}
if (_field414 != 0) {
@@ -1571,11 +1523,10 @@ void Scene1200::dispatch() {
default:
break;
}
- _object1.sub51AFD(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
- warning("int unk = set_pane_p(_paneNumber);");
- _object1.sub51B02();
- warning("_gfxManager.sub294AC(unk);");
- warning("tmpRect.sub14DF3();");
+ _mazeUI.setMazePosition(Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4));
+
+ debug("_gfxManager.sub294AC(unk);");
+ debug("tmpRect.sub14DF3();");
if (_field416 != 0) {
switch(_field412 - 1) {
@@ -1608,6 +1559,190 @@ void Scene1200::saveCharacter(int characterIndex) {
SceneExt::saveCharacter(characterIndex);
}
+void Scene1200::startCrawling(CrawlDirection dir) {
+ Common::Point cellPos = Common::Point(R2_GLOBALS._v56AA2, R2_GLOBALS._v56AA4);
+ _mazeUI.pixelToCellXY(cellPos);
+
+ switch (dir) {
+ case CRAWL_EAST:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(200, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(200, 88)) > 36))
+ && ( ((cellPos.x == 3) && (cellPos.y == 33) && (_field418 != 4))
+ || ((cellPos.x == 13) && (cellPos.y == 21) && (_field418 != 2))
+ || ((cellPos.x == 29) && (cellPos.y == 17) && (_field418 != 1))
+ || ((cellPos.x == 33) && (cellPos.y == 41)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1200;
+ setAction(&_sequenceManager, this, 1200, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(200, 69)) == 36) {
+ switch (_field412 - 1) {
+ case 0:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 15;
+ else
+ _sceneMode = 10;
+ break;
+ case 1:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 76;
+ else
+ _sceneMode = 75;
+ break;
+ case 2:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 101;
+ else
+ _sceneMode = 100;
+ break;
+ case 3:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 111;
+ else
+ _sceneMode = 110;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _field412 = 1;
+ signal();
+ }
+ break;
+ case CRAWL_WEST:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(120, 50)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(120, 88)) > 36))
+ && ( ((cellPos.x == 7) && (cellPos.y == 33) && (_field418 != 4))
+ || ((cellPos.x == 17) && (cellPos.y == 21) && (_field418 != 2))
+ || ((cellPos.x == 33) && (cellPos.y == 17) && (_field418 != 1))
+ || ((cellPos.x == 5) && (cellPos.y == 5)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1201;
+ setAction(&_sequenceManager, this, 1201, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(120, 69)) == 36) {
+ switch (_field412 - 1) {
+ case 0:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 56;
+ else
+ _sceneMode = 55;
+ break;
+ case 1:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 25;
+ else
+ _sceneMode = 20;
+ break;
+ case 2:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 91;
+ else
+ _sceneMode = 90;
+ break;
+ case 3:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 121;
+ else
+ _sceneMode = 120;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _field412 = 2;
+ signal();
+ }
+ break;
+ case CRAWL_SOUTH:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 110)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 110)) > 36))
+ && ( ((cellPos.x == 17) && (cellPos.y == 5) && (_field418 != 3))
+ || ((cellPos.x == 41) && (cellPos.y == 21)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1203;
+ setAction(&_sequenceManager, this, 1203, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 110)) == 36) {
+ switch (_field412 - 1) {
+ case 0:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 51;
+ else
+ _sceneMode = 50;
+ break;
+ case 1:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 81;
+ else
+ _sceneMode = 80;
+ break;
+ case 2:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 35;
+ else
+ _sceneMode = 30;
+ break;
+ case 3:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 116;
+ else
+ _sceneMode = 115;
+ break;
+ default:
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _field412 = 3;
+ signal();
+ }
+ break;
+ case CRAWL_NORTH:
+ if ( ((_mazeUI.getCellFromPixelXY(Common::Point(140, 30)) > 36) || (_mazeUI.getCellFromPixelXY(Common::Point(178, 30)) > 36))
+ && ( ((cellPos.x == 17) && (cellPos.y == 9) && (_field418 != 3))
+ || ((cellPos.x == 35) && (cellPos.y == 17)) )
+ ) {
+ R2_GLOBALS._player.disableControl();
+ _sceneMode = 1202;
+ setAction(&_sequenceManager, this, 1202, &_actor1, NULL);
+ } else if (_mazeUI.getCellFromPixelXY(Common::Point(160, 30)) == 36) {
+ switch (_field412 - 1) {
+ case 0:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 61;
+ else
+ _sceneMode = 60;
+ break;
+ case 1:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 71;
+ else
+ _sceneMode = 70;
+ break;
+ case 2:
+ if (R2_GLOBALS._player._visage == 3156)
+ _sceneMode = 96;
+ else
+ _sceneMode = 95;
+ break;
+ case 3:
+ if (R2_GLOBALS._player._visage == 3155)
+ _sceneMode = 45;
+ else
+ _sceneMode = 40;
+ break;
+ default:
+ _sceneMode = 1;
+ R2_GLOBALS._player.setup(3156, 4, 6);
+ break;
+ }
+ R2_GLOBALS._player.disableControl();
+ _field412 = 4;
+ signal();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
/*--------------------------------------------------------------------------
* Scene 1337 - Card game
*
@@ -6924,7 +7059,7 @@ void Scene1550::UnkArea1550::remove() {
}
void Scene1550::UnkArea1550::process(Event &event) {
-// This is a copy of Scene1200::Area1::process
+// This is a copy of Scene1200::LaserPanel::process
if (_field20 != R2_GLOBALS._insetUp)
return;
@@ -6988,7 +7123,7 @@ void Scene1550::UnkArea1550::proc12(int visage, int stripFrameNum, int frameNum,
}
void Scene1550::UnkArea1550::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
- // Copy of Scene1200::Area1::proc13
+ // Copy of Scene1200::LaserPanel::proc13
_areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
}
@@ -8751,7 +8886,7 @@ void Scene1575::Hotspot1::process(Event &event) {
di -= 2;
scene->_field41A -= 2;
- for (int i = 0; i < 178; i++)
+ for (int i = 0; i < 17; i++)
scene->_arrActor[i].setPosition(Common::Point(scene->_arrActor[i]._position.x - 2, scene->_arrActor[i]._position.y));
scene->_actor13.setPosition(Common::Point(scene->_actor13._position.x - 2, scene->_actor13._position.y));
@@ -12947,7 +13082,7 @@ void Scene1950::Area1::remove() {
}
void Scene1950::Area1::process(Event &event) {
-// This is a copy of Scene1200::Area1::process
+// This is a copy of Scene1200::LaserPanel::process
if (_field20 != R2_GLOBALS._insetUp)
return;
@@ -13000,7 +13135,7 @@ void Scene1950::Area1::proc12(int visage, int stripFrameNum, int frameNum, int p
}
void Scene1950::Area1::proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum) {
- // Copy of Scene1200::Area1::proc13()
+ // Copy of Scene1200::LaserPanel::proc13()
_areaActor.setDetails(resNum, lookLineNum, talkLineNum, useLineNum, 2, (SceneItem *) NULL);
}
diff --git a/engines/tsage/ringworld2/ringworld2_scenes1.h b/engines/tsage/ringworld2/ringworld2_scenes1.h
index f65a89972d..0da6b3f93d 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes1.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes1.h
@@ -118,36 +118,31 @@ public:
};
class Scene1200 : public SceneExt {
- class Area1: public SceneArea {
+ enum CrawlDirection { CRAWL_EAST = 1, CRAWL_WEST = 2, CRAWL_SOUTH = 3, CRAWL_NORTH = 4 };
+
+ class LaserPanel: public ModalWindow {
public:
- class Actor3 : public SceneActorExt {
+ class Jumper : public SceneActorExt {
public:
void init(int state);
virtual bool startAction(CursorType action, Event &event);
};
- SceneActor _actor2;
- Actor3 _actor3;
- Actor3 _actor4;
- Actor3 _actor5;
-
- byte _field20;
+ Jumper _jumper1;
+ Jumper _jumper2;
+ Jumper _jumper3;
- Area1();
- void synchronize(Serializer &s);
+ LaserPanel();
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
- virtual void process(Event &event);
- virtual void proc12(int visage, int stripFrameNum, int frameNum, int posX, int posY);
- virtual void proc13(int resNum, int lookLineNum, int talkLineNum, int useLineNum);
};
public:
NamedHotspot _item1;
SceneActor _actor1;
- Area1 _area1;
- UnkObject1200 _object1;
+ LaserPanel _laserPanel;
+ MazeUI _mazeUI;
SequenceManager _sequenceManager;
int _field412;
@@ -155,12 +150,12 @@ public:
int _field416;
int _field418;
int _field41A;
- int _field41C;
+ bool _fixupMaze;
Scene1200();
void synchronize(Serializer &s);
- void sub9DAD6(int indx);
+ void startCrawling(CrawlDirection dir);
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void signal();
diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.cpp b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
index 6a030e5b44..9246c4b6a4 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes2.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes2.cpp
@@ -630,6 +630,7 @@ void Scene2000::Exit3::changeScene() {
break;
}
}
+
void Scene2000::Exit4::changeScene() {
Scene2000 *scene = (Scene2000 *)R2_GLOBALS._sceneManager._scene;
@@ -756,19 +757,21 @@ void Scene2000::Exit5::changeScene() {
}
}
-void Scene2000::postInit(SceneObjectList *OwnerList) {
- SceneExt::postInit();
- loadScene(2000);
-
+Scene2000::Scene2000(): SceneExt() {
if (R2_GLOBALS._sceneManager._previousScene != -1) {
R2_GLOBALS._v56605[1] = 21;
R2_GLOBALS._v56605[2] = 21;
}
- if ((R2_GLOBALS._player._characterScene[R2_GLOBALS._player._characterIndex] != R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex]) && (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] != 2350)) {
+ if ((R2_GLOBALS._player._characterScene[R2_GLOBALS._player._characterIndex]
+ != R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex])
+ && (R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] != 2350)) {
R2_GLOBALS._player._oldCharacterScene[R2_GLOBALS._player._characterIndex] = 0;
}
+
_exitingFlag = false;
+}
+void Scene2000::postInit(SceneObjectList *OwnerList) {
_exit1.setDetails(Rect(0, 100, 14, 140), EXITCURSOR_W, 2000);
_exit1.setDest(Common::Point(14, 129));
_exit2.setDetails(Rect(305, 100, 320, 140), EXITCURSOR_E, 2000);
@@ -917,6 +920,8 @@ void Scene2000::postInit(SceneObjectList *OwnerList) {
initPlayer();
_item1.setDetails(Rect(0, 0, 320, 200), 2000, 0, -1, 23, 1, NULL);
+
+ SceneExt::postInit();
}
void Scene2000::remove() {
@@ -998,6 +1003,8 @@ void Scene2000::signal() {
g_globals->_sceneManager.changeScene(2350);
break;
default:
+ R2_GLOBALS._v56AAB = 0;
+ R2_GLOBALS._player.enableControl();
break;
}
}
diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.h b/engines/tsage/ringworld2/ringworld2_scenes2.h
index 281d1da366..feceaa1537 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes2.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes2.h
@@ -80,6 +80,7 @@ public:
Action1 _action1, _action2, _action3, _action4, _action5;
SequenceManager _sequenceManager;
+ Scene2000();
virtual void postInit(SceneObjectList *OwnerList = NULL);
virtual void remove();
virtual void signal();
diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.cpp b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
index 61711d0a4f..6af2a0cad4 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes3.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes3.cpp
@@ -2885,9 +2885,10 @@ void Scene3400::signal() {
}
/*--------------------------------------------------------------------------
- * Scene 3500 -
+ * Scene 3500 - Cavern Maze
*
*--------------------------------------------------------------------------*/
+
Scene3500::Action1::Action1() {
_field1E = 0;
_field20 = 0;
@@ -2919,9 +2920,10 @@ void Scene3500::Action1::sub108670(int arg1) {
else
scene->_actor5.show();
- if (scene->_actor1._frame % 2 == 0)
- scene->_actor1._frameChange = _field1E;
- scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ if (scene->_actor1._frame % 2 == 0) {
+ scene->_actor1._frameChange = _field1E;
+ scene->_actor1.setFrame(scene->_actor1.changeFrame());
+ }
setActionIndex(0);
}
@@ -2977,219 +2979,6 @@ void Scene3500::Action1::sub108732(int arg1) {
}
}
-Scene3500::Action2::Action2() {
- _field1E = 0;
-}
-
-void Scene3500::Action2::synchronize(Serializer &s) {
- Action::synchronize(s);
-
- s.syncAsSint16LE(_field1E);
-}
-
-Scene3500::Item4::Item4() {
- _field34 = 0;
-}
-
-void Scene3500::Item4::synchronize(Serializer &s) {
- NamedHotspot::synchronize(s);
-
- s.syncAsSint16LE(_field34);
-}
-
-Scene3500::Actor7::Actor7() {
- _fieldA4 = 0;
- _fieldA6 = 0;
- _fieldA8 = 0;
- _fieldAA = 0;
- _fieldAC = 0;
- _fieldAE = 0;
-}
-
-void Scene3500::Actor7::synchronize(Serializer &s) {
- SceneActor::synchronize(s);
-
- s.syncAsSint16LE(_fieldA4);
- s.syncAsSint16LE(_fieldA6);
- s.syncAsSint16LE(_fieldA8);
- s.syncAsSint16LE(_fieldAA);
- s.syncAsSint16LE(_fieldAC);
- s.syncAsSint16LE(_fieldAE);
-}
-
-void Scene3500::Actor7::sub109466(int arg1, int arg2, int arg3, int arg4, int arg5) {
- _fieldAE = 0;
- _fieldA4 = arg1;
- _fieldA6 = arg2;
- _fieldA8 = arg3;
- _fieldAA = arg4;
- _fieldAC = _fieldAA / _fieldA8;
-
- postInit();
- setup(10501, 3, 1);
- fixPriority(255);
- sub109663(arg5);
-}
-
-void Scene3500::Actor7::sub1094ED() {
- Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
-
- scene->_field1270 = _position.x - _fieldA4;
-}
-
-void Scene3500::Actor7::sub109663(int arg1){
- sub109693(Common::Point(_fieldA4 + arg1, _fieldA6 - (_fieldAC * arg1)));
-}
-
-void Scene3500::Actor7::sub109693(Common::Point Pt) {
- setPosition(Pt);
-}
-
-int Scene3500::UnkObject3500::sub1097C9(int arg1) {
- return (_field2A / 2) + arg1 - (arg1 % _field2A);
-}
-
-int Scene3500::UnkObject3500::sub1097EF(int arg1) {
- return (_field2C / 2) + arg1 - (arg1 % _field2C);
-}
-
-int Scene3500::UnkObject3500::sub109C09(Common::Point pt) {
- int vx = pt.x / _field2A;
- int vy = pt.y / _field2C;
-
- if ((vx >= 0) && (_field26 > vx) && (_field28 > vy)) {
- return _field16[((_field26 * vy) + vx) * 2];
- } else
- return -1;
-}
-
-int Scene3500::UnkObject3500::sub109C5E(int &x, int &y) {
- int retVal = sub51AFD(Common::Point(x, y));
- x = _field2E;
- y = _field30;
-
- return retVal;
-}
-
-Scene3500::Scene3500() {
- _fieldAF8 = 0;
- _fieldB9E = 0;
- _rotation = NULL;
- _field126E = 0;
- _field1270 = 0;
- _field1272 = 0;
- _field1274 = 0;
- _field1276 = 0;
- _field1278 = 0;
- _field127A = 0;
- _field127C = 0;
- _field127E = 0;
- _field1280 = 0;
- _field1282 = 0;
- _field1284 = 0;
- _field1286 = 0;
-}
-
-void Scene3500::synchronize(Serializer &s) {
- SceneExt::synchronize(s);
- SYNC_POINTER(_rotation);
-
- s.syncAsSint16LE(_fieldAF8);
- s.syncAsSint16LE(_fieldB9E);
- s.syncAsSint16LE(_field126E);
- s.syncAsSint16LE(_field1270);
- s.syncAsSint16LE(_field1272);
- s.syncAsSint16LE(_field1274);
- s.syncAsSint16LE(_field1276);
- s.syncAsSint16LE(_field1278);
- s.syncAsSint16LE(_field127A);
- s.syncAsSint16LE(_field127C);
- s.syncAsSint16LE(_field127E);
- s.syncAsSint16LE(_field1280);
- s.syncAsSint16LE(_field1282);
- s.syncAsSint16LE(_field1284);
- s.syncAsSint16LE(_field1286);
-}
-
-void Scene3500::sub107F71(int arg1) {
- switch (arg1) {
- case -1:
- _actor7.sub1094ED();
- if (_field1270 != 0) {
- _field1270--;
- _actor7.sub109663(_field1270);
- }
- if (_action1._field24 != 0)
- _field1270 = 0;
- break;
- case 1:
- _actor7.sub1094ED();
- if (_field1270 < 16) {
- ++_field1270;
- _actor7.sub109663(_field1270);
- }
- if (_action1._field24 != 0)
- _field1270 = 0;
- break;
- case 88:
- if ((_action == 0) || (_action1._field24 == 0)) {
- // The original makes a second useless check on action, skipped
- _action2.sub10831F(2);
- if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != 2))) {
- _action2.signal();
- } else {
- _actor9.setAction(&_action2, &_actor9, NULL);
- }
- }
- break;
- case 96:
- if ((_action) && (_action1._field24 != 0) && (_action2._field1E != 1)) {
- _field1278 = 0;
- _action1.sub108732(0);
- } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) {
- _field1278 = arg1;
- } else if ((_action) && (_action1._field24 == 0)) {
- _action1.sub108670(1);
- _action1.signal();
- } else if (_action == 0) {
- _action1.sub108670(1);
- setAction(&_action1, &_actor1, NULL);
- }
- break;
- case 104:
- if ((_action == 0) || (_action1._field24 == 0)) {
- _action2.sub10831F(-1);
- if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != -1))) {
- _action2.signal();
- } else {
- _actor9.setAction(&_action2, &_actor9, NULL);
- }
- }
- break;
- case 112:
- if ((_action) && (_action1._field24 != 0) && (_action2._field1E != -1)) {
- _field1278 = 0;
- _action1.sub108732(0);
- } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) {
- _field1278 = arg1;
- } else if ((_action) && (_action1._field24 == 0)) {
- _action1.sub108670(-1);
- _action1.signal();
- } else if (_action == 0) {
- _action1.sub108670(-1);
- setAction(&_action1, &_actor1, NULL);
- }
- break;
- default:
- _field1270 = arg1;
- _actor7.sub109663(arg1);
- if (_action1._field24 != 0) {
- _field1270 = 0;
- }
- break;
- }
-}
-
void Scene3500::Action1::signal() {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
@@ -3199,13 +2988,13 @@ void Scene3500::Action1::signal() {
scene->_field1286 = 0;
if (scene->_field1270 != 0) {
scene->_field1270 = 0;
- scene->_field126E = 0;
+ scene->_mazeChangeAmount = 0;
scene->_field1272 = 0;
scene->_rotation->_idxChange = 0;
}
break;
case 1:
- if ((scene->_actor1._frame % 2) == 0) {
+ if ((scene->_actor1._frame % 2) == 1) {
setDelay(1);
return;
}
@@ -3216,25 +3005,28 @@ void Scene3500::Action1::signal() {
setDelay(1);
break;
case 4: {
- int si = scene->_unkObj1.sub109C09(Common::Point(scene->_field127A + 70, scene->_field127C + 46));
- int var2 = scene->_unkObj1.sub1097C9(scene->_field127A + 70) - 70;
- int var4 = scene->_unkObj1.sub1097EF(scene->_field127C + 46) - 46;
- int di = abs(var2 - scene->_field127A);
- int var6 = abs(var4 - scene->_field127C);
+ int si = scene->_mazeUI.getCellFromMapXY(Common::Point(scene->_mazePosition.x + 70, scene->_mazePosition.y + 46));
+ int var2 = scene->_mazeUI.cellFromX(scene->_mazePosition.x + 70) - 70;
+ int var4 = scene->_mazeUI.cellFromY(scene->_mazePosition.y + 46) - 46;
+ int di = abs(var2 - scene->_mazePosition.x);
+ int var6 = abs(var4 - scene->_mazePosition.y);
if ((scene->_actor1._frame % 2) != 0) {
scene->_actor1._frameChange = _field1E;
scene->_actor1.setFrame(scene->_actor1.changeFrame());
}
- int var8 = (scene->_action1._field1E * 2 + scene->_field1276);
- if (var8 > 7)
- var8 = 1;
- else if (var8 < 1)
- var8 = 7;
+ // Get the new direction starting on
+ int var8 = (scene->_action1._field1E * 2 + scene->_mazeDirection);
+ if (var8 > MAZEDIR_NORTHWEST)
+ var8 = MAZEDIR_NORTH;
+ else if (var8 < MAZEDIR_NORTH)
+ var8 = MAZEDIR_WEST;
+ // Check whether movement is allowed in that direction. If so, then
+ // movement is started again
switch (var8) {
- case 0:
+ case MAZEDIR_NORTH:
if ( ((si != 2) && (si != 3) && (si != 6) && (si != 1) && (si != 23) && (si != 24) && (si != 4) && (si != 11))
|| (var6 != 0)) {
if ((si != 25) && (si != 26) && (si != 5) && (si != 14) && (si != 15))
@@ -3246,7 +3038,7 @@ void Scene3500::Action1::signal() {
} else
_field20 = 1;
break;
- case 2:
+ case MAZEDIR_EAST:
if ( ((si != 12) && (si != 13) && (si != 11) && (si != 16) && (si != 26) && (si != 24) && (si != 15) && (si != 6) && (si != 31))
|| (di != 0)) {
if ((si != 25) && (si != 23) && (si != 14) && (si != 5) && (si != 4))
@@ -3258,7 +3050,7 @@ void Scene3500::Action1::signal() {
} else
_field20 = 1;
break;
- case 4:
+ case MAZEDIR_SOUTH:
if ( ((si != 2) && (si != 3) && (si != 6) && (si != 1) && (si != 25) && (si != 26) && (si != 5) && (si != 16) && (si != 31))
|| (var6 != 0)) {
if ((si != 23) && (si != 24) && (si != 4) && (si != 14) && (si != 15))
@@ -3270,7 +3062,7 @@ void Scene3500::Action1::signal() {
} else
_field20 = 1;
break;
- case 6:
+ case MAZEDIR_WEST:
if ( ((si != 12) && (si != 13) && (si != 11) && (si != 16) && (si != 25) && (si != 23) && (si != 14) && (si != 1) && (si != 31))
|| (var6 != 0)) {
if ((si != 26) && (si != 24) && (si != 15) && (si != 5) && (si != 4))
@@ -3288,14 +3080,14 @@ void Scene3500::Action1::signal() {
// No break on purpose
case 2: {
scene->_actor8.setPosition(Common::Point(160, 73));
- scene->_actor8._moveDiff.x = 160 - scene->_field126E;
+ scene->_actor8._moveDiff.x = 160 - scene->_mazeChangeAmount;
scene->_fieldAF8 = 160 - ((_field1E * 2) * 160);
Common::Point pt(scene->_fieldAF8, 73);
NpcMover *mover = new NpcMover();
scene->_actor8.addMover(mover, &pt, this);
scene->_actor9.setPosition(Common::Point(160 + ((_field1E * 2) * 160), 73));
- scene->_actor9._moveDiff.x = 160 - scene->_field126E;
+ scene->_actor9._moveDiff.x = 160 - scene->_mazeChangeAmount;
scene->_fieldB9E = 160;
Common::Point pt2(scene->_fieldB9E, 73);
NpcMover *mover2 = new NpcMover();
@@ -3304,8 +3096,8 @@ void Scene3500::Action1::signal() {
break;
case 5:
scene->_actor1._frameChange = _field1E;
- scene->_field1276 = scene->_actor1.changeFrame();
- scene->_actor1.setFrame(scene->_field1276);
+ scene->_mazeDirection = scene->_actor1.changeFrame();
+ scene->_actor1.setFrame(scene->_mazeDirection);
setDelay(1);
break;
case 6:
@@ -3325,8 +3117,8 @@ void Scene3500::Action1::signal() {
case 7:
if ((scene->_actor1._frame % 2) == 0) {
scene->_actor1._frameChange = _field1E;
- scene->_field1276 = scene->_actor1.changeFrame();
- scene->_actor1.setFrame(scene->_field1276);
+ scene->_mazeDirection = scene->_actor1.changeFrame();
+ scene->_actor1.setFrame(scene->_mazeDirection);
}
setDelay(1);
break;
@@ -3342,7 +3134,7 @@ void Scene3500::Action1::signal() {
// but it's clearly a cut and paste error from case 4.
// The following code allows the switch to work properly.
warning("Checkme: fix for dead code");
- int var_8 = (_field1E * 2 + scene->_field1276);
+ int var_8 = (_field1E * 2 + scene->_mazeDirection);
if (var_8 > 7)
var_8 = 1;
else if (var_8 < 1)
@@ -3353,12 +3145,12 @@ void Scene3500::Action1::signal() {
case 0:
// No break on purpose
case 4:
- scene->_field127A = scene->_unkObj1.sub1097C9(scene->_field127A + 70) - 70;
+ scene->_mazePosition.x = scene->_mazeUI.cellFromX(scene->_mazePosition.x + 70) - 70;
break;
case 2:
// No break on purpose
case 6:
- scene->_field127C = scene->_unkObj1.sub1097EF(scene->_field127C + 46) - 46;
+ scene->_mazePosition.y = scene->_mazeUI.cellFromY(scene->_mazePosition.y + 46) - 46;
break;
default:
break;
@@ -3368,7 +3160,7 @@ void Scene3500::Action1::signal() {
_field24 = 0;
if (_field20 == 0) {
scene->_actor7.sub1094ED();
- if (scene->_field126E == scene->_field1270)
+ if (scene->_mazeChangeAmount == scene->_field1270)
scene->_aSound1.play(276);
}
break;
@@ -3416,12 +3208,232 @@ void Scene3500::Action1::dispatch() {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
Action::dispatch();
- if ((_actionIndex == 1) && (scene->_field126E <= 4)) {
+ if ((_actionIndex == 1) && (scene->_mazeChangeAmount <= 4)) {
scene->_rotation->_idxChange = 0;
signal();
}
}
+/*--------------------------------------------------------------------------*/
+
+Scene3500::Action2::Action2() {
+ _field1E = 0;
+}
+
+void Scene3500::Action2::synchronize(Serializer &s) {
+ Action::synchronize(s);
+
+ s.syncAsSint16LE(_field1E);
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene3500::Item4::Item4() {
+ _field34 = 0;
+}
+
+void Scene3500::Item4::synchronize(Serializer &s) {
+ NamedHotspot::synchronize(s);
+
+ s.syncAsSint16LE(_field34);
+}
+
+/*--------------------------------------------------------------------------*/
+
+Scene3500::Actor7::Actor7() {
+ _fieldA4 = 0;
+ _fieldA6 = 0;
+ _fieldA8 = 0;
+ _fieldAA = 0;
+ _fieldAC = 0;
+ _fieldAE = 0;
+}
+
+void Scene3500::Actor7::synchronize(Serializer &s) {
+ SceneActor::synchronize(s);
+
+ s.syncAsSint16LE(_fieldA4);
+ s.syncAsSint16LE(_fieldA6);
+ s.syncAsSint16LE(_fieldA8);
+ s.syncAsSint16LE(_fieldAA);
+ s.syncAsSint16LE(_fieldAC);
+ s.syncAsSint16LE(_fieldAE);
+}
+
+void Scene3500::Actor7::sub109466(int arg1, int arg2, int arg3, int arg4, int arg5) {
+ _fieldAE = 0;
+ _fieldA4 = arg1;
+ _fieldA6 = arg2;
+ _fieldA8 = arg3;
+ _fieldAA = arg4;
+ _fieldAC = _fieldAA / _fieldA8;
+
+ postInit();
+ setup(1050, 3, 1);
+ fixPriority(255);
+ sub109663(arg5);
+}
+
+void Scene3500::Actor7::sub1094ED() {
+ Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
+
+ scene->_field1270 = _position.x - _fieldA4;
+}
+
+void Scene3500::Actor7::sub109663(int arg1){
+ sub109693(Common::Point(_fieldA4 + arg1, _fieldA6 - (_fieldAC * arg1)));
+}
+
+void Scene3500::Actor7::sub109693(Common::Point Pt) {
+ setPosition(Pt);
+}
+
+/*--------------------------------------------------------------------------*/
+
+int Scene3500::MazeUI3500::cellFromX(int x) {
+ return (_cellSize.x / 2) + x - (x % _cellSize.x);
+}
+
+int Scene3500::MazeUI3500::cellFromY(int y) {
+ return (_cellSize.y / 2) + y - (y % _cellSize.y) - 1;
+}
+
+int Scene3500::MazeUI3500::getCellFromMapXY(Common::Point pt) {
+ int cellX = pt.x / _cellSize.x;
+ int cellY = pt.y / _cellSize.y;
+
+ if ((cellX >= 0) && (cellY >= 0) && (cellX < _mapCells.x) && (cellY < _mapCells.y)) {
+ return (int16)READ_LE_UINT16(_mapData + (_mapCells.x * cellY + cellX) * 2);
+ } else
+ return -1;
+}
+
+bool Scene3500::MazeUI3500::setMazePosition2(Common::Point &p) {
+ bool retVal = setMazePosition(p);
+ p = _mapOffset;
+
+ return retVal;
+}
+
+Scene3500::Scene3500() {
+ _fieldAF8 = 0;
+ _fieldB9E = 0;
+ _rotation = NULL;
+ _mazeChangeAmount = 0;
+ _field1270 = 0;
+ _field1272 = 0;
+ _field1274 = 0;
+ _mazeDirection = MAZEDIR_NONE;
+ _field1278 = 0;
+ _mazePosition.x = 0;
+ _mazePosition.y = 0;
+ _field127E = 0;
+ _field1280 = 0;
+ _field1282 = 0;
+ _field1284 = 0;
+ _field1286 = 0;
+}
+
+void Scene3500::synchronize(Serializer &s) {
+ SceneExt::synchronize(s);
+ SYNC_POINTER(_rotation);
+
+ s.syncAsSint16LE(_fieldAF8);
+ s.syncAsSint16LE(_fieldB9E);
+ s.syncAsSint16LE(_mazeChangeAmount);
+ s.syncAsSint16LE(_field1270);
+ s.syncAsSint16LE(_field1272);
+ s.syncAsSint16LE(_field1274);
+ s.syncAsSint16LE(_mazeDirection);
+ s.syncAsSint16LE(_field1278);
+ s.syncAsSint16LE(_mazePosition.x);
+ s.syncAsSint16LE(_mazePosition.y);
+ s.syncAsSint16LE(_field127E);
+ s.syncAsSint16LE(_field1280);
+ s.syncAsSint16LE(_field1282);
+ s.syncAsSint16LE(_field1284);
+ s.syncAsSint16LE(_field1286);
+}
+
+void Scene3500::sub107F71(int arg1) {
+ switch (arg1) {
+ case -1:
+ _actor7.sub1094ED();
+ if (_field1270 != 0) {
+ _field1270--;
+ _actor7.sub109663(_field1270);
+ }
+ if (_action1._field24 != 0)
+ _field1270 = 0;
+ break;
+ case 1:
+ _actor7.sub1094ED();
+ if (_field1270 < 16) {
+ ++_field1270;
+ _actor7.sub109663(_field1270);
+ }
+ if (_action1._field24 != 0)
+ _field1270 = 0;
+ break;
+ case 88:
+ if ((_action == 0) || (_action1._field24 == 0)) {
+ // The original makes a second useless check on action, skipped
+ _action2.sub10831F(2);
+ if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != 2))) {
+ _action2.signal();
+ } else {
+ _actor9.setAction(&_action2, &_actor9, NULL);
+ }
+ }
+ break;
+ case 96:
+ if ((_action) && (_action1._field24 != 0) && (_action2._field1E != 1)) {
+ _field1278 = 0;
+ _action1.sub108732(0);
+ } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) {
+ _field1278 = arg1;
+ } else if ((_action) && (_action1._field24 == 0)) {
+ _action1.sub108670(1);
+ _action1.signal();
+ } else if (_action == 0) {
+ _action1.sub108670(1);
+ setAction(&_action1, &_actor1, NULL);
+ }
+ break;
+ case 104:
+ if ((_action == 0) || (_action1._field24 == 0)) {
+ _action2.sub10831F(-1);
+ if ((_action) && ((_action2.getActionIndex() != 0) || (_action2._field1E != -1))) {
+ _action2.signal();
+ } else {
+ _actor9.setAction(&_action2, &_actor9, NULL);
+ }
+ }
+ break;
+ case 112:
+ if ((_action) && (_action1._field24 != 0) && (_action2._field1E != -1)) {
+ _field1278 = 0;
+ _action1.sub108732(0);
+ } else if ((_action) && (_field1278 == 0) && (_action1._field24 != 0)) {
+ _field1278 = arg1;
+ } else if ((_action) && (_action1._field24 == 0)) {
+ _action1.sub108670(-1);
+ _action1.signal();
+ } else if (_action == 0) {
+ _action1.sub108670(-1);
+ setAction(&_action1, &_actor1, NULL);
+ }
+ break;
+ default:
+ _field1270 = arg1;
+ _actor7.sub109663(arg1);
+ if (_action1._field24 != 0) {
+ _field1270 = 0;
+ }
+ break;
+ }
+}
+
void Scene3500::Action2::sub10831F(int arg1) {
Scene3500 *scene = (Scene3500 *)R2_GLOBALS._sceneManager._scene;
@@ -3452,17 +3464,17 @@ void Scene3500::Action2::signal() {
di = scene->_fieldB9E;
}
- scene->_actor8._moveDiff.y = 9 - (scene->_field126E / 2);
+ scene->_actor8._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
Common::Point pt(si, 73 - (_field1E * 12));
NpcMover *mover = new NpcMover();
scene->_actor8.addMover(mover, &pt, NULL);
- scene->_actor9._moveDiff.y = 9 - (scene->_field126E / 2);
+ scene->_actor9._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
Common::Point pt2(di, 73 - (_field1E * 12));
NpcMover *mover2 = new NpcMover();
scene->_actor9.addMover(mover2, &pt2, NULL);
- scene->_field126E = (scene->_field126E / 2) + (scene->_field126E % 2);
- setDelay(17 - scene->_field126E);
+ scene->_mazeChangeAmount = (scene->_mazeChangeAmount / 2) + (scene->_mazeChangeAmount % 2);
+ setDelay(17 - scene->_mazeChangeAmount);
}
break;
case 1: {
@@ -3477,12 +3489,12 @@ void Scene3500::Action2::signal() {
scene->_actor7.sub1094ED();
- scene->_actor8._moveDiff.y = 9 - (scene->_field126E / 2);
+ scene->_actor8._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
Common::Point pt(si, 73);
NpcMover *mover = new NpcMover();
scene->_actor8.addMover(mover, &pt, NULL);
- scene->_actor9._moveDiff.y = 9 - (scene->_field126E / 2);
+ scene->_actor9._moveDiff.y = 9 - (scene->_mazeChangeAmount / 2);
Common::Point pt2(di, 73);
NpcMover *mover2 = new NpcMover();
scene->_actor9.addMover(mover2, &pt2, NULL);
@@ -3559,7 +3571,6 @@ bool Scene3500::Actor7::startAction(CursorType action, Event &event) {
void Scene3500::postInit(SceneObjectList *OwnerList) {
byte tmpPal[768];
- Rect tmpRect;
loadScene(1050);
R2_GLOBALS._uiElements._active = false;
@@ -3574,9 +3585,8 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_field1278 = 0;
_field1272 = 1;
_field1270 = 4;
- _field126E = 4;
- _field127A = 860;
- _field127C = 891;
+ _mazeChangeAmount = 4;
+ _mazePosition = Common::Point(860, 891);
_rotation = R2_GLOBALS._scenePalette.addRotation(240, 254, -1);
_rotation->setDelay(0);
_rotation->_idxChange = 1;
@@ -3615,7 +3625,7 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_item7.setDetails(96, 3500, 12, 10, -1);
_actor8.postInit();
- _actor8.setup(10501, 1, 1);
+ _actor8.setup(1050, 1, 1);
_actor8.setPosition(Common::Point(160, 73));
_actor8.fixPriority(1);
@@ -3630,8 +3640,8 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_item1.setDetails(Rect(0, 0, 320, 200), 3500, 0, -1, 2, 1, NULL);
_actor1.postInit();
- _field1276 = 1;
- _actor1.setup(1004, 1, _field1276);
+ _mazeDirection = MAZEDIR_NORTH;
+ _actor1.setup(1004, 1, _mazeDirection);
_actor1.setPosition(Common::Point(230, 135));
_actor1.fixPriority(200);
_actor1._frameChange = 1;
@@ -3654,7 +3664,7 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_actor6.hide();
_actor2.postInit();
- _actor2.setup(1004, 4, _field126E + 1);
+ _actor2.setup(1004, 4, _mazeChangeAmount + 1);
_actor2.setPosition(Common::Point(126, 137));
_actor2.fixPriority(200);
@@ -3663,15 +3673,12 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
_actor3.setPosition(Common::Point(126, 108));
_actor3.fixPriority(200);
- tmpRect.set(160, 89, 299, 182);
- _unkObj1.sub9EDE8(tmpRect);
- _unkObj1.sub51AE9(2);
- _unkObj1.sub51AFD(Common::Point(_field127A, _field127C));
+ _mazeUI.setDisplayBounds(Rect(160, 89, 299, 182));
+ _mazeUI.load(2);
+ _mazeUI.setMazePosition(_mazePosition);
_action1._field24 = 0;
- warning("gfx_set_pane_p()");
- _unkObj1.sub51B02();
- warning("gfx_set_pane_p()");
+ _mazeUI.draw();
_field1286 = 1;
R2_GLOBALS._player.postInit();
@@ -3682,7 +3689,6 @@ void Scene3500::postInit(SceneObjectList *OwnerList) {
}
void Scene3500::remove() {
- _rotation->remove();
R2_GLOBALS._sound2.fadeOut2(NULL);
SceneExt::remove();
}
@@ -3699,64 +3705,58 @@ void Scene3500::process(Event &event) {
if (event.eventType == EVENT_KEYPRESS) {
switch (event.kbd.keycode) {
- case Common::KEYCODE_1:
- warning("FIXME: keycode = 0x4700");
+ case Common::KEYCODE_KP7:
R2_GLOBALS._sound2.play(338);
sub107F71(16);
event.handled = true;
break;
- case Common::KEYCODE_2:
- warning("FIXME: keycode = 0x4800");
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_KP8:
R2_GLOBALS._sound2.play(14, NULL, 63);
sub107F71(88);
event.handled = true;
break;
- case Common::KEYCODE_3:
- warning("FIXME: keycode = 0x4900");
+ case Common::KEYCODE_KP9:
if (_field1270 < 16)
R2_GLOBALS._sound2.play(338);
sub107F71(1);
event.handled = true;
break;
- case Common::KEYCODE_4:
- warning("FIXME: keycode = 0x4B00");
+ case Common::KEYCODE_KP4:
+ case Common::KEYCODE_LEFT:
R2_GLOBALS._sound2.play(14, NULL, 63);
sub107F71(112);
event.handled = true;
break;
- case Common::KEYCODE_5:
- warning("FIXME: keycode = 0x4D00");
+ case Common::KEYCODE_KP6:
+ case Common::KEYCODE_RIGHT:
R2_GLOBALS._sound2.play(14, NULL, 63);
sub107F71(96);
event.handled = true;
break;
- case Common::KEYCODE_6:
- warning("FIXME: keycode = 0x4F00");
+ case Common::KEYCODE_KP1:
R2_GLOBALS._sound2.play(338);
sub107F71(0);
event.handled = true;
break;
- case Common::KEYCODE_7:
- warning("FIXME: keycode = 0x5000");
+ case Common::KEYCODE_KP2:
+ case Common::KEYCODE_DOWN:
R2_GLOBALS._sound2.play(14, NULL, 63);
sub107F71(104);
event.handled = true;
break;
- case Common::KEYCODE_8:
- warning("FIXME: keycode = 0x5100");
+ case Common::KEYCODE_KP3:
if (_field1270 != 0)
R2_GLOBALS._sound2.play(338);
sub107F71(-1);
event.handled = true;
break;
- case Common::KEYCODE_9:
- warning("FIXME: keycode = 0x5200");
+ case Common::KEYCODE_KP0:
R2_GLOBALS._sound2.play(338);
sub107F71(8);
event.handled = true;
break;
- case Common::KEYCODE_0:
- warning("FIXME: keycode = 0x5300");
+ case Common::KEYCODE_KP_PERIOD:
R2_GLOBALS._sound2.play(338);
sub107F71(4);
event.handled = true;
@@ -3787,9 +3787,10 @@ void Scene3500::process(Event &event) {
void Scene3500::dispatch() {
Rect tmpRect;
Scene::dispatch();
+
if (((_actor1._frame % 2) == 0) && (_action1._field24 == 0)) {
_actor1.setFrame(_actor1.changeFrame());
- _field1276 = _actor1._frame;
+ _mazeDirection = _actor1._frame;
}
int oldField1278;
if ((_field1278 != 0) && (_action1._field24 == 0)) {
@@ -3801,90 +3802,90 @@ void Scene3500::dispatch() {
if (!_rotation)
return;
- int var_field127A = 0;
- int di = 0;
+ int newMazeX = 0;
+ int newMazeY = 0;
int var_4 = 0;
int var_6 = 0;
int var_8 = 0;
int var_a = 0;
int dx = 0;
- int tmpVar = 0;
+ int cellId = 0;
- if ((_field126E == 0) && (_field1282 == 0)) {
+ if ((_mazeChangeAmount == 0) && (_field1282 == 0)) {
if (_field1284 == 2)
R2_GLOBALS._sceneManager.changeScene(1000);
} else {
_field1282 = 0;
tmpRect.set(160, 89, 299, 182);
- var_field127A = _field127A;
- di = _field127C;
- var_4 = _unkObj1.sub1097C9(70) - 70;
- var_6 = _unkObj1.sub1097EF(_field127C + 46) - 46;
- var_8 = abs(var_4 - var_field127A);
- var_a = abs(var_6 - di);
+ newMazeX = _mazePosition.x;
+ newMazeY = _mazePosition.y;
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ var_6 = _mazeUI.cellFromY(_mazePosition.y + 46) - 46;
+ var_8 = abs(var_4 - newMazeX);
+ var_a = abs(var_6 - newMazeY);
dx = 0;
- switch (_field1276) {
- case 0:
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, 46));
- if ( ((tmpVar == 2) || (tmpVar == 3) || (tmpVar == 6) || (tmpVar == 1))
- || (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 > 3)) ) {
+ switch (_mazeDirection) {
+ case MAZEDIR_NORTH:
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 2) || (cellId == 3) || (cellId == 6) || (cellId == 1)) ||
+ ((cellId == 25 || cellId == 26 || cellId == 5 || cellId == 14 || cellId == 15) && var_8 > 3)) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_6 = _unkObj1.sub1097EF(di + 46) - 46;
- di = _field127C - _field126E;
- dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4)) && (tmpVar != dx)) {
- di = var_6;
+ var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ newMazeY = _mazePosition.y - _mazeChangeAmount;
+ dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (cellId != dx)) {
+ newMazeY = var_6;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 11) && (tmpVar != dx)) {
- di = var_6 + 3;
+ } else if ((cellId == 11) && (cellId != dx)) {
+ newMazeY = var_6 + 3;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_6 = _unkObj1.sub1097EF(di + 46) - 46;
- var_a = abs(var_6 - di);
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
-
- if ( (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4)) && (di <= var_6) && (_field127C>= var_6))
- || (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)) && (_field126E >= var_a) && (_field126E > 3) && (_action1._field24 != 0)) ) {
- di = var_6;
- if ((tmpVar != 25) && (tmpVar != 26) && (tmpVar != 5) && (tmpVar != 14) && (tmpVar == 15))
+ var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ var_a = abs(var_6 - newMazeY);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+
+ if ( (((cellId == 23) || (cellId == 24) || (cellId == 4)) && (newMazeY <= var_6) && (_mazePosition.y>= var_6))
+ || (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= var_a) && (_mazeChangeAmount > 3) && (_action1._field24 != 0)) ) {
+ newMazeY = var_6;
+ if ((cellId != 25) && (cellId != 26) && (cellId != 5) && (cellId != 14) && (cellId == 15))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 11) && (var_6 + 3 >= di) && (_field127C >= var_6 + 3)) {
+ } else if ((cellId == 11) && (var_6 + 3 >= newMazeY) && (_mazePosition.y >= var_6 + 3)) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 != 0) && (var_8 <= 3)) {
- var_field127A = var_4;
+ } else if (((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)) && (var_8 != 0) && (var_8 <= 3)) {
+ newMazeX = var_4;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -3892,65 +3893,65 @@ void Scene3500::dispatch() {
}
}
break;
- case 2:
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( ((tmpVar == 12) || (tmpVar == 13) || (tmpVar == 11) || (tmpVar == 16) || (tmpVar == 31))
- || (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) && (var_a > 3)) ) {
+ case MAZEDIR_EAST:
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( ((cellId == 12) || (cellId == 13) || (cellId == 11) || (cellId == 16) || (cellId == 31))
+ || (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (var_a > 3)) ) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70;
- var_field127A = _field127A + _field126E;
- dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15)) && (tmpVar != dx)) {
- var_field127A = var_4;
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ newMazeX = _mazePosition.x + _mazeChangeAmount;
+ dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 26) || (cellId == 24) || (cellId == 15)) && (cellId != dx)) {
+ newMazeX = var_4;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 6) && (tmpVar != dx)) {
- var_field127A = var_4 - 5;
+ } else if ((cellId == 6) && (cellId != dx)) {
+ newMazeX = var_4 - 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70;
- var_8 = abs(var_field127A - var_4);
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, tmpVar + 46));
- if ( (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15)) && (var_field127A >= var_4) && (_field127A <= var_4))
- || (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) && (_field126E >= var_8) && (_field126E <= 3) && (_action1._field24 != 0)) ) {
- var_field127A = var_4;
- if ((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4))
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ var_8 = abs(newMazeX - var_4);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( (((cellId == 26) || (cellId == 24) || (cellId == 15)) && (newMazeX >= var_4) && (_mazePosition.x <= var_4))
+ || (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (_mazeChangeAmount >= var_8) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ) {
+ newMazeX = var_4;
+ if ((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 6) && (var_4 - 5 <= var_field127A) && (_field127A <= var_4 - 5)) {
- var_field127A = var_4 - 5;
+ } else if ((cellId == 6) && (var_4 - 5 <= newMazeX) && (_mazePosition.x <= var_4 - 5)) {
+ newMazeX = var_4 - 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)) && (var_a != 0) && (var_a <= 3)) {
- di = var_6;
+ } else if (((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)) && (var_a != 0) && (var_a <= 3)) {
+ newMazeY = var_6;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -3958,84 +3959,87 @@ void Scene3500::dispatch() {
}
}
break;
- case 4:
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( ((tmpVar == 2) || (tmpVar == 3) || (tmpVar == 6) || (tmpVar == 1))
- || (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 > 3)) ) {
+ case MAZEDIR_SOUTH:
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( ((cellId == 2) || (cellId == 3) || (cellId == 6) || (cellId == 1))
+ || (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (var_8 > 3)) ) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_6 = _unkObj1.sub1097EF(di + 46) - 46;
- di = _field127C + _field126E;
- dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5)) && (tmpVar == dx)) {
+ var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ newMazeY = _mazePosition.y + _mazeChangeAmount;
+ dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+
+ if (((cellId == 25) || (cellId == 26) || (cellId == 5)) && (cellId != dx)) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 16) && (tmpVar == dx)) {
- di = var_6 - 3;
+ } else if ((cellId == 16) && (cellId != dx)) {
+ newMazeY = var_6 - 3;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 31) && (tmpVar == dx)) {
- di = var_6 + 4;
+ } else if ((cellId == 31) && (cellId != dx)) {
+ newMazeY = var_6 + 4;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_6 = _unkObj1.sub1097EF(di + 46) - 46;
- var_a = abs(di - var_6);
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( (((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5)) && (di >= var_6) && (_field127C <= var_6))
- || (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)) && (_field126E >= var_a) && (_field126E <= 3) && (_action1._field24 != 0)) ){
- if ((tmpVar != 23) && (tmpVar != 24) && (tmpVar != 4) && (tmpVar != 14) && (tmpVar != 15))
+ var_6 = _mazeUI.cellFromY(newMazeY + 46) - 46;
+ var_a = abs(newMazeY - var_6);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( (((cellId == 25) || (cellId == 26) || (cellId == 5)) && (newMazeY >= var_6) && (_mazePosition.y <= var_6))
+ || (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (_mazeChangeAmount >= var_a) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ){
+ newMazeY = var_6;
+
+ if ((cellId != 23) && (cellId != 24) && (cellId != 4) && (cellId != 14) && (cellId != 15))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 16) && (var_6 - 3 <= di) && (_field127C <= var_6 - 3)) {
- di = var_6 - 3;
+ } else if ((cellId == 16) && (var_6 - 3 <= newMazeY) && (_mazePosition.y <= var_6 - 3)) {
+ newMazeY = var_6 - 3;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 31) && (var_6 + 4 <= di) && (_field127C <= var_6 + 4)) {
- di = var_6 + 4;
+ } else if ((cellId == 31) && (var_6 + 4 <= newMazeY) && (_mazePosition.y <= var_6 + 4)) {
+ newMazeY = var_6 + 4;
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- if ((var_field127A == 660) && (_field126E + 306 <= di) && (di <= 307))
+ if ((newMazeX == 660) && (_mazeChangeAmount + 306 <= newMazeY) && (newMazeY <= 307))
++_field1284;
else
R2_GLOBALS._sound2.play(339);
- } else if (((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)) && (var_8 != 0) && (var_8 <= 3)) {
- var_field127A = var_4;
+ } else if (((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)) && (var_8 != 0) && (var_8 <= 3)) {
+ newMazeX = var_4;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -4043,65 +4047,65 @@ void Scene3500::dispatch() {
}
}
break;
- case 6:
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( ((tmpVar == 12) || (tmpVar == 13) || (tmpVar == 11) || (tmpVar == 16) || (tmpVar == 31))
- || (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) && (var_a > 3)) ) {
+ case MAZEDIR_WEST:
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( ((cellId == 12) || (cellId == 13) || (cellId == 11) || (cellId == 16) || (cellId == 31))
+ || (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (var_a > 3)) ) {
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70;
- var_field127A = _field127A - _field126E;
- dx = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14)) && (tmpVar != dx)) {
- var_field127A = var_4;
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ newMazeX = _mazePosition.x - _mazeChangeAmount;
+ dx = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if (((cellId == 25) || (cellId == 23) || (cellId == 14)) && (cellId != dx)) {
+ newMazeX = var_4;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 1) && (tmpVar != dx)) {
- var_field127A = var_4 + 5;
+ } else if ((cellId == 1) && (cellId != dx)) {
+ newMazeX = var_4 + 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
} else {
- var_4 = _unkObj1.sub1097C9(var_field127A + 70) - 70;
- var_8 = abs(var_4 - var_field127A);
- tmpVar = _unkObj1.sub109C09(Common::Point(var_field127A + 70, di + 46));
- if ( (((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14)) && (var_field127A <= var_4) && (_field127A >= var_4))
- || (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) && (_field126E >= var_8) && (_field126E <= 3) && (_action1._field24 != 0)) ) {
- var_field127A = var_4;
- if ((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4))
+ var_4 = _mazeUI.cellFromX(newMazeX + 70) - 70;
+ var_8 = abs(var_4 - newMazeX);
+ cellId = _mazeUI.getCellFromMapXY(Common::Point(newMazeX + 70, newMazeY + 46));
+ if ( (((cellId == 25) || (cellId == 23) || (cellId == 14)) && (newMazeX <= var_4) && (_mazePosition.x >= var_4))
+ || (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (_mazeChangeAmount >= var_8) && (_mazeChangeAmount <= 3) && (_action1._field24 != 0)) ) {
+ newMazeX = var_4;
+ if ((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4))
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if ((tmpVar == 1) && (var_field127A >= var_4 + 5) && (_field127A >= var_4 + 5)) {
- var_field127A = var_4 + 5;
+ } else if ((cellId == 1) && (newMazeX >= var_4 + 5) && (_mazePosition.x >= var_4 + 5)) {
+ newMazeX = var_4 + 5;
R2_GLOBALS._sound2.play(339);
_rotation->_idxChange = 0;
_field1270 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1272 = 0;
if (_action1._field24 == 0)
_actor8.hide();
- } else if (((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4)) && (var_a != 0) && (var_a <= 3)) {
- di = var_6;
+ } else if (((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4)) && (var_a != 0) && (var_a <= 3)) {
+ newMazeY = var_6;
R2_GLOBALS._sound2.play(339);
} else {
// Nothing
@@ -4114,49 +4118,49 @@ void Scene3500::dispatch() {
}
if (_field1284 < 2) {
- _field127A = var_field127A;
- _field127C = di;
- if (_unkObj1.sub109C5E(_field127A, _field127C) != 0) {
+ _mazePosition.x = newMazeX;
+ _mazePosition.y = newMazeY;
+ if (_mazeUI.setMazePosition2(_mazePosition) != 0) {
_field1272 = 0;
- _field126E = 0;
+ _mazeChangeAmount = 0;
_field1270 = 0;
_rotation->setDelay(0);
_rotation->_idxChange = 0;
}
- warning("gfx_set_pane_p");
- _unkObj1.sub51B02();
+
+ _mazeUI.draw();
if (_field1284 != 0)
++_field1284;
}
}
if (_field1272 == 0) {
- if (_field126E != _field1270) {
- if (_field126E >= _field1270) {
- if (_field126E == 1) {
+ if (_mazeChangeAmount != _field1270) {
+ if (_mazeChangeAmount >= _field1270) {
+ if (_mazeChangeAmount == 1) {
if (_action1._field24 != 0) {
- if ( ((_field1276 == 1) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((tmpVar == 25) || (tmpVar == 26) || (tmpVar == 5) || (tmpVar == 14) || (tmpVar == 15)))
- || ((_field1276 == 3) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((tmpVar == 25) || (tmpVar == 23) || (tmpVar == 14) || (tmpVar == 5) || (tmpVar == 4)))
- || ((_field1276 == 5) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((tmpVar == 23) || (tmpVar == 24) || (tmpVar == 4) || (tmpVar == 14) || (tmpVar == 15)))
- || ((_field1276 == 7) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((tmpVar == 26) || (tmpVar == 24) || (tmpVar == 15) || (tmpVar == 5) || (tmpVar == 4))) ){
- _field126E = 1;
+ if ( ((_mazeDirection == 1) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((cellId == 25) || (cellId == 26) || (cellId == 5) || (cellId == 14) || (cellId == 15)))
+ || ((_mazeDirection == 3) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((cellId == 25) || (cellId == 23) || (cellId == 14) || (cellId == 5) || (cellId == 4)))
+ || ((_mazeDirection == 5) && (var_8 == 0) && (var_a != 0) && (var_a <= 3) && ((cellId == 23) || (cellId == 24) || (cellId == 4) || (cellId == 14) || (cellId == 15)))
+ || ((_mazeDirection == 7) && (var_a == 0) && (var_8 != 0) && (var_8 <= 3) && ((cellId == 26) || (cellId == 24) || (cellId == 15) || (cellId == 5) || (cellId == 4))) ){
+ _mazeChangeAmount = 1;
} else
- _field126E--;
+ _mazeChangeAmount--;
} else
- _field126E--;
+ _mazeChangeAmount--;
} else
- _field126E--;
+ _mazeChangeAmount--;
} else
- ++_field126E;
+ ++_mazeChangeAmount;
_field1272 = 1;
}
- _actor2.setFrame2(_field126E);
+ _actor2.setFrame2(_mazeChangeAmount + 1);
}
if (_field1272 == 1) {
- if (_field126E == 0)
+ if (_mazeChangeAmount == 0)
_rotation->_idxChange = 0;
- else if (_field126E > 8)
+ else if (_mazeChangeAmount > 8)
_rotation->_idxChange = 2;
else
_rotation->_idxChange = 1;
@@ -4165,9 +4169,9 @@ void Scene3500::dispatch() {
if (_field1272 != 0)
_field1272--;
- if (_field126E != 0) {
- R2_GLOBALS._player._uiEnabled = false;
- if (_field126E != _field1270)
+ if (_mazeChangeAmount != 0) {
+ R2_GLOBALS._player._uiEnabled = false;
+ if (_mazeChangeAmount != _field1270)
_aSound1.play(276);
} else {
R2_GLOBALS._player._uiEnabled = true;
diff --git a/engines/tsage/ringworld2/ringworld2_scenes3.h b/engines/tsage/ringworld2/ringworld2_scenes3.h
index 44787b9eef..85e5674433 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes3.h
+++ b/engines/tsage/ringworld2/ringworld2_scenes3.h
@@ -633,12 +633,12 @@ class Scene3500 : public SceneExt {
// TODO: double check if nothing specific is present, then remove this class
};
- class UnkObject3500 : public UnkObject1200 {
+ class MazeUI3500 : public MazeUI {
public:
- int sub1097C9(int arg1);
- int sub1097EF(int arg1);
- int sub109C09(Common::Point pt);
- int sub109C5E(int &x, int &y);
+ int cellFromX(int arg1);
+ int cellFromY(int arg1);
+ int getCellFromMapXY(Common::Point pt);
+ bool setMazePosition2(Common::Point &p);
};
public:
Action1 _action1;
@@ -650,6 +650,7 @@ public:
Item4 _item5;
Item4 _item6;
Item4 _item7;
+ // Glyph of vessel on top of the maze ui
SceneActor _actor1;
SceneActor _actor2;
SceneActor _actor3;
@@ -660,20 +661,19 @@ public:
Actor8 _actor8;
Actor8 _actor9;
ASoundExt _aSound1;
- UnkObject3500 _unkObj1;
+ MazeUI3500 _mazeUI;
SequenceManager _sequenceManager;
int _fieldAF8;
int _fieldB9E;
PaletteRotation *_rotation;
- int _field126E;
+ int _mazeChangeAmount;
int _field1270;
int _field1272;
int _field1274;
- int _field1276;
+ int _mazeDirection;
int _field1278;
- int _field127A;
- int _field127C;
+ Common::Point _mazePosition;
int _field127E;
int _field1280;
int _field1282;
diff --git a/engines/tsage/ringworld2/ringworld2_speakers.cpp b/engines/tsage/ringworld2/ringworld2_speakers.cpp
index da1449efdf..b8d593b90a 100644
--- a/engines/tsage/ringworld2/ringworld2_speakers.cpp
+++ b/engines/tsage/ringworld2/ringworld2_speakers.cpp
@@ -40,7 +40,7 @@ VisualSpeaker::VisualSpeaker(): Speaker() {
_color1 = 8;
_color2 = 0;
_displayMode = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
}
void VisualSpeaker::remove() {
@@ -49,27 +49,104 @@ void VisualSpeaker::remove() {
_fieldF8 = 0;
_object1.setStrip(_object1._strip - 1);
_object1.setFrame(_object1.getFrameCount());
- _object1.animate(ANIM_MODE_6, (_fieldF6 == 0xff) ? this : NULL);
+ _object1.animate(ANIM_MODE_6, (_speakerMode == 0xff) ? this : NULL);
} else {
- _object1.animate(ANIM_MODE_6, (_fieldF6 == 0xff) ? this : NULL);
+ _object1.animate(ANIM_MODE_6, (_speakerMode == 0xff) ? this : NULL);
}
}
Speaker::remove();
}
+void VisualSpeaker::signal() {
+ // TODO: _action->_field18 = 1;
+ if (_speakerMode == 0xff)
+ proc16();
+
+ _speakerMode = 0;
+ if (_numFrames) {
+ if (_object2) {
+ _object1.setStrip(_object1._strip + 1);
+ _object1.animate(ANIM_MODE_2, NULL);
+ _fieldF8 = 1;
+ }
+
+ if ((R2_GLOBALS._speechSubtitles & SPEECH_TEXT) || _soundId)
+ _sceneText.show();
+
+ if ((R2_GLOBALS._speechSubtitles & SPEECH_VOICE) && _soundId) {
+ // TODO: Check global that is passed
+ setFrame2(/* word_55F90 */ 0);
+ }
+ } else if (_action && _object2) {
+ _action->setDelay(1);
+ _sceneText.remove();
+
+ R2_GLOBALS._playStream.stop();
+ }
+}
+
+void VisualSpeaker::dispatch() {
+ uint32 frameNumber = R2_GLOBALS._events.getFrameNumber();
+
+ // Delay check for character animation
+ if (_delayAmount) {
+ if (frameNumber >= _frameNumber) {
+ _delayAmount = _delayAmount - (_frameNumber - frameNumber);
+ _frameNumber = frameNumber;
+
+ if (_delayAmount <= 0) {
+ _delayAmount = 0;
+ _object1.animate(ANIM_MODE_NONE, NULL);
+ _object1.setFrame(1);
+ }
+ }
+ }
+
+ // Delay check for voice
+ if (_delayAmount2) {
+ if (frameNumber >= _frameNumber2) {
+ _delayAmount2 = _delayAmount2 - (_frameNumber2 - frameNumber);
+ _frameNumber2 = frameNumber;
+
+ if (_delayAmount2 <= 0) {
+ _delayAmount2 = 0;
+ if (R2_GLOBALS._playStream.play(0, NULL)) {
+ _numFrames = 2;
+ _soundId = 0;
+ } else {
+ _sceneText.show();
+ }
+ }
+ }
+ }
+
+ if ((R2_GLOBALS._speechSubtitles & SPEECH_VOICE) && (_numFrames == 2) &&
+ !R2_GLOBALS._playStream.isPlaying()) {
+ _numFrames = 0;
+ _object1.animate(ANIM_MODE_NONE);
+ _object1.setFrame(1);
+
+ if (!(R2_GLOBALS._speechSubtitles & SPEECH_TEXT)) {
+ _action->setDelay(1);
+ }
+ }
+}
+
void VisualSpeaker::synchronize(Serializer &s) {
Speaker::synchronize(s);
SYNC_POINTER(_object2);
- s.syncAsSint16LE(_fieldF6);
+ s.syncAsSint16LE(_speakerMode);
s.syncAsSint16LE(_fieldF8);
s.syncAsSint16LE(_displayMode);
s.syncAsSint16LE(_soundId);
- s.syncAsSint16LE(_delayAmount);
s.syncAsByte(_removeObject);
- s.syncAsSint32LE(_frameNumber);
s.syncAsSint16LE(_numFrames);
+ s.syncAsSint16LE(_delayAmount);
+ s.syncAsUint32LE(_frameNumber);
+ s.syncAsSint16LE(_delayAmount2);
+ s.syncAsUint32LE(_frameNumber2);
}
void VisualSpeaker::setText(const Common::String &msg) {
@@ -159,8 +236,7 @@ void VisualSpeaker::setText(const Common::String &msg) {
if (s.empty())
_numFrames = 0;
-
- if (_fieldF6) {
+ if (_speakerMode) {
if ((R2_GLOBALS._speechSubtitles & SPEECH_TEXT) || !_soundId)
_sceneText.hide();
} else {
@@ -173,11 +249,11 @@ void VisualSpeaker::setText(const Common::String &msg) {
void VisualSpeaker::proc16() {
R2_GLOBALS._playStream.stop();
- _fieldF6 = 0;
+ _speakerMode = 0;
_object1.remove();
- assert(_object2);
- _object2->show();
+ if (_object2)
+ _object2->show();
_object2 = NULL;
_fieldF8 = 0;
}
@@ -187,6 +263,11 @@ void VisualSpeaker::setFrame(int numFrames) {
_frameNumber = R2_GLOBALS._events.getFrameNumber();
}
+void VisualSpeaker::setFrame2(int numFrames) {
+ _delayAmount2 = numFrames;
+ _frameNumber2 = R2_GLOBALS._events.getFrameNumber();
+}
+
void VisualSpeaker::setDelay(int delay) {
_delayAmount = delay;
_frameNumber = R2_GLOBALS._events.getFrameNumber();
@@ -211,7 +292,7 @@ SpeakerCaptain3210::SpeakerCaptain3210() {
_speakerName = "Captain";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -220,7 +301,7 @@ SpeakerCaptain3210::SpeakerCaptain3210() {
}
void SpeakerCaptain3210::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3210 *scene = (Scene3210 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -250,7 +331,7 @@ SpeakerCaretaker2450::SpeakerCaretaker2450() {
_speakerName = "CARETAKER";
_color1 = 43;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -266,7 +347,7 @@ SpeakerChief1100::SpeakerChief1100() {
_speakerName = "CHIEF";
_color1 = 8;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -275,7 +356,7 @@ SpeakerChief1100::SpeakerChief1100() {
}
void SpeakerChief1100::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene1100 *scene = (Scene1100 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -324,7 +405,7 @@ SpeakerGuard::SpeakerGuard() {
_speakerName = "GUARD";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -333,7 +414,7 @@ SpeakerGuard::SpeakerGuard() {
}
void SpeakerGuard2800::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -364,7 +445,7 @@ SpeakerJocko::SpeakerJocko() {
_speakerName = "Jocko";
_color1 = 45;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -373,7 +454,7 @@ SpeakerJocko::SpeakerJocko() {
}
void SpeakerJocko3200::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3200 *scene = (Scene3200 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -396,7 +477,7 @@ void SpeakerJocko3200::proc15() {
}
void SpeakerJocko3220::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3220 *scene = (Scene3220 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -419,7 +500,7 @@ void SpeakerJocko3220::proc15() {
}
void SpeakerJocko3230::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3230 *scene = (Scene3230 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -449,7 +530,7 @@ SpeakerMiranda::SpeakerMiranda(): VisualSpeaker() {
_speakerName = "MIRANDA";
_color1 = 154;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -458,7 +539,7 @@ SpeakerMiranda::SpeakerMiranda(): VisualSpeaker() {
}
void SpeakerMiranda300::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 3) {
@@ -498,7 +579,7 @@ void SpeakerMiranda300::proc15() {
}
void SpeakerMiranda1625::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
Scene1625 *scene = (Scene1625 *)R2_GLOBALS._sceneManager._scene;
@@ -521,7 +602,7 @@ void SpeakerMiranda1625::proc15() {
}
void SpeakerMiranda3255::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &R2_GLOBALS._player;
@@ -544,7 +625,7 @@ void SpeakerMiranda3255::proc15() {
void SpeakerMiranda3375::proc15() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 3)
@@ -594,7 +675,7 @@ void SpeakerMiranda3375::proc15() {
void SpeakerMiranda3385::proc15() {
Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 3)
@@ -643,7 +724,7 @@ void SpeakerMiranda3385::proc15() {
void SpeakerMiranda3395::proc15() {
Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 3)
@@ -693,7 +774,7 @@ void SpeakerMiranda3395::proc15() {
void SpeakerMiranda3400::proc15() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 3)
@@ -737,7 +818,7 @@ void SpeakerMiranda3400::proc15() {
void SpeakerMiranda3600::proc15() {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 3)
@@ -783,7 +864,7 @@ void SpeakerMiranda3600::proc15() {
void SpeakerMiranda3700::proc15() {
Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor3;
@@ -840,7 +921,7 @@ SpeakerNej::SpeakerNej() {
_speakerName = "NEJ";
_color1 = 171;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -849,7 +930,7 @@ SpeakerNej::SpeakerNej() {
}
void SpeakerNej2700::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene2700 *scene = (Scene2700 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -884,7 +965,7 @@ void SpeakerNej2700::proc15() {
}
void SpeakerNej2750::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -916,7 +997,7 @@ void SpeakerNej2750::proc15() {
}
void SpeakerNej2800::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene2750 *scene = (Scene2750 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -948,7 +1029,7 @@ SpeakerPharisha::SpeakerPharisha(): VisualSpeaker() {
_speakerName = "PHARISHA";
_color1 = 151;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -957,7 +1038,7 @@ SpeakerPharisha::SpeakerPharisha(): VisualSpeaker() {
}
void SpeakerPharisha2435::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene2435 *scene = (Scene2435 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -984,7 +1065,7 @@ SpeakerPrivate3210::SpeakerPrivate3210() {
_speakerName = "Private";
_color1 = 45;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -993,7 +1074,7 @@ SpeakerPrivate3210::SpeakerPrivate3210() {
}
void SpeakerPrivate3210::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3210 *scene = (Scene3210 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -1023,7 +1104,7 @@ SpeakerProtector3600::SpeakerProtector3600() {
_speakerName = "Protector";
_color1 = 170;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1032,7 +1113,7 @@ SpeakerProtector3600::SpeakerProtector3600() {
}
void SpeakerProtector3600::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -1084,7 +1165,7 @@ SpeakerQuinn::SpeakerQuinn(): VisualSpeaker() {
_speakerName = "QUINN";
_color1 = 60;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1093,7 +1174,7 @@ SpeakerQuinn::SpeakerQuinn(): VisualSpeaker() {
}
void SpeakerQuinn300::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 3) {
@@ -1140,7 +1221,7 @@ void SpeakerQuinn300::proc15() {
}
void SpeakerQuinn1100::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (v == 0)
@@ -1188,7 +1269,7 @@ void SpeakerQuinn1100::proc15() {
}
void SpeakerQuinn2435::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 1) {
@@ -1214,7 +1295,7 @@ void SpeakerQuinn2435::proc15() {
}
void SpeakerQuinn2450::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 1) {
@@ -1242,7 +1323,7 @@ void SpeakerQuinn2450::proc15() {
}
void SpeakerQuinn2700::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &R2_GLOBALS._player;
@@ -1273,7 +1354,7 @@ void SpeakerQuinn2700::proc15() {
}
void SpeakerQuinn2750::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &R2_GLOBALS._player;
@@ -1304,7 +1385,7 @@ void SpeakerQuinn2750::proc15() {
}
void SpeakerQuinn2800::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &R2_GLOBALS._player;
@@ -1345,7 +1426,7 @@ void SpeakerQuinn2800::proc15() {
void SpeakerQuinn3255::proc15() {
Scene3255 *scene = (Scene3255 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor4;
@@ -1368,7 +1449,7 @@ void SpeakerQuinn3255::proc15() {
void SpeakerQuinn3375::proc15() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 1)
@@ -1419,7 +1500,7 @@ void SpeakerQuinn3375::proc15() {
void SpeakerQuinn3385::proc15() {
Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 1)
@@ -1474,7 +1555,7 @@ void SpeakerQuinn3385::proc15() {
void SpeakerQuinn3395::proc15() {
Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 1)
@@ -1529,7 +1610,7 @@ void SpeakerQuinn3395::proc15() {
void SpeakerQuinn3400::proc15() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 1)
@@ -1578,7 +1659,7 @@ void SpeakerQuinn3400::proc15() {
void SpeakerQuinn3600::proc15() {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 1)
@@ -1626,7 +1707,7 @@ void SpeakerQuinn3600::proc15() {
void SpeakerQuinn3700::setText(const Common::String &msg) {
Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene;
- switch (_fieldF6) {
+ switch (_speakerMode) {
case 2:
scene->_actor3.setup(30, 1, 1);
R2_GLOBALS._sound2.play(44);
@@ -1644,7 +1725,7 @@ void SpeakerQuinn3700::setText(const Common::String &msg) {
void SpeakerQuinn3700::proc15() {
Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor1;
@@ -1701,7 +1782,7 @@ SpeakerQuinnL::SpeakerQuinnL(): VisualSpeaker() {
_speakerName = "QUINNL";
_color1 = 35;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1718,7 +1799,7 @@ SpeakerRalf3245::SpeakerRalf3245() {
_speakerName = "Ralf";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1727,7 +1808,7 @@ SpeakerRalf3245::SpeakerRalf3245() {
}
void SpeakerRalf3245::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3245 *scene = (Scene3245 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -1770,7 +1851,7 @@ SpeakerRocko::SpeakerRocko() {
_speakerName = "Rocko";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1779,7 +1860,7 @@ SpeakerRocko::SpeakerRocko() {
}
void SpeakerRocko3200::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3200 *scene = (Scene3200 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -1802,7 +1883,7 @@ void SpeakerRocko3200::proc15() {
}
void SpeakerRocko3220::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3220 *scene = (Scene3220 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -1825,7 +1906,7 @@ void SpeakerRocko3220::proc15() {
}
void SpeakerRocko3230::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3230 *scene = (Scene3230 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -1855,7 +1936,7 @@ SpeakerSeeker::SpeakerSeeker(): VisualSpeaker() {
_speakerName = "SEEKER";
_color1 = 35;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -1864,10 +1945,10 @@ SpeakerSeeker::SpeakerSeeker(): VisualSpeaker() {
}
void SpeakerSeeker300::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
- if (R2_GLOBALS._player._characterIndex == 3) {
+ if (R2_GLOBALS._player._characterIndex == 2) {
_object2 = &R2_GLOBALS._player;
} else {
Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
@@ -1900,7 +1981,7 @@ void SpeakerSeeker300::proc15() {
}
void SpeakerSeeker1100::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (v == 0)
@@ -1959,7 +2040,7 @@ void SpeakerSeeker1100::proc15() {
}
void SpeakerSeeker1900::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 2) {
@@ -1989,7 +2070,7 @@ void SpeakerSeeker1900::proc15() {
}
void SpeakerSeeker2435::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 2) {
@@ -2015,7 +2096,7 @@ void SpeakerSeeker2435::proc15() {
}
void SpeakerSeeker2450::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 2) {
@@ -2042,7 +2123,7 @@ void SpeakerSeeker2450::proc15() {
void SpeakerSeeker3375::proc15() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 2)
@@ -2091,7 +2172,7 @@ void SpeakerSeeker3375::proc15() {
void SpeakerSeeker3385::proc15() {
Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 2)
@@ -2140,7 +2221,7 @@ void SpeakerSeeker3385::proc15() {
void SpeakerSeeker3395::proc15() {
Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 2)
@@ -2189,7 +2270,7 @@ void SpeakerSeeker3395::proc15() {
void SpeakerSeeker3400::proc15() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 2)
@@ -2248,7 +2329,7 @@ void SpeakerSeeker3400::proc15() {
void SpeakerSeeker3600::proc15() {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
if (R2_GLOBALS._player._characterIndex == 2)
@@ -2295,7 +2376,7 @@ void SpeakerSeeker3600::proc15() {
void SpeakerSeeker3700::setText(const Common::String &msg) {
Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene;
- if (_fieldF6 == 1) {
+ if (_speakerMode == 1) {
R2_GLOBALS._sound2.play(44);
scene->_actor3.setup(30, 8, 1);
} else {
@@ -2307,7 +2388,7 @@ void SpeakerSeeker3700::setText(const Common::String &msg) {
void SpeakerSeeker3700::proc15() {
Scene3700 *scene = (Scene3700 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor2;
@@ -2359,7 +2440,7 @@ SpeakerSeekerL::SpeakerSeekerL(): VisualSpeaker() {
_speakerName = "SEEKERL";
_color1 = 35;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2376,7 +2457,7 @@ SpeakerSocko3200::SpeakerSocko3200() {
_speakerName = "Socko";
_color1 = 10;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2385,7 +2466,7 @@ SpeakerSocko3200::SpeakerSocko3200() {
}
void SpeakerSocko3200::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3200 *scene = (Scene3200 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -2415,7 +2496,7 @@ SpeakerSoldier::SpeakerSoldier(int colour) {
_speakerName = "SOLDIER";
_color1 = colour;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2424,7 +2505,7 @@ SpeakerSoldier::SpeakerSoldier(int colour) {
}
void SpeakerSoldier300::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
@@ -2455,7 +2536,7 @@ SpeakerTeal::SpeakerTeal(): VisualSpeaker() {
_speakerName = "TEAL";
_color1 = 22;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2468,7 +2549,7 @@ SpeakerTealMode7::SpeakerTealMode7(): SpeakerTeal() {
}
void SpeakerTeal300::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
Scene300 *scene = (Scene300 *)R2_GLOBALS._sceneManager._scene;
@@ -2492,7 +2573,7 @@ void SpeakerTeal300::proc15() {
}
void SpeakerTeal1625::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
Scene1625 *scene = (Scene1625 *)R2_GLOBALS._sceneManager._scene;
@@ -2516,7 +2597,7 @@ void SpeakerTeal1625::proc15() {
}
void SpeakerTeal3240::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3240 *scene = (Scene3240 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -2541,7 +2622,7 @@ void SpeakerTeal3240::proc15() {
void SpeakerTeal3400::proc15() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor4;
@@ -2598,7 +2679,7 @@ void SpeakerTeal3400::proc15() {
void SpeakerTeal3600::proc15() {
Scene3600 *scene = (Scene3600 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor5;
@@ -2659,7 +2740,7 @@ SpeakerTomko3245::SpeakerTomko3245() {
_speakerName = "Tomko";
_color1 = 10;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2668,7 +2749,7 @@ SpeakerTomko3245::SpeakerTomko3245() {
}
void SpeakerTomko3245::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3245 *scene = (Scene3245 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -2711,7 +2792,7 @@ SpeakerWebbster::SpeakerWebbster(int colour) {
_speakerName = "WEBBSTER";
_color1 = colour;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2720,7 +2801,7 @@ SpeakerWebbster::SpeakerWebbster(int colour) {
}
void SpeakerWebbster3240::proc15() {
- int v = _fieldF6;
+ int v = _speakerMode;
Scene3240 *scene = (Scene3240 *)R2_GLOBALS._sceneManager._scene;
if (!_object2) {
@@ -2745,7 +2826,7 @@ void SpeakerWebbster3240::proc15() {
void SpeakerWebbster3375::proc15() {
Scene3375 *scene = (Scene3375 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor3;
@@ -2789,7 +2870,7 @@ void SpeakerWebbster3375::proc15() {
void SpeakerWebbster3385::proc15() {
Scene3385 *scene = (Scene3385 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor3;
@@ -2833,7 +2914,7 @@ void SpeakerWebbster3385::proc15() {
void SpeakerWebbster3395::proc15() {
Scene3395 *scene = (Scene3395 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor3;
@@ -2877,7 +2958,7 @@ void SpeakerWebbster3395::proc15() {
void SpeakerWebbster3400::proc15() {
Scene3400 *scene = (Scene3400 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_actor3;
@@ -2925,7 +3006,7 @@ SpeakerDutyOfficer::SpeakerDutyOfficer(): VisualSpeaker() {
_speakerName = "DUTYOFFICER";
_color1 = 5;
_color2 = 0;
- _fieldF6 = 0;
+ _speakerMode = 0;
_textWidth = 300;
_hideObjects = false;
_object2 = NULL;
@@ -2936,7 +3017,7 @@ SpeakerDutyOfficer::SpeakerDutyOfficer(): VisualSpeaker() {
void SpeakerDutyOfficer::proc15() {
Scene180 *scene = (Scene180 *)R2_GLOBALS._sceneManager._scene;
- int v = _fieldF6;
+ int v = _speakerMode;
if (!_object2) {
_object2 = &scene->_object2;
diff --git a/engines/tsage/ringworld2/ringworld2_speakers.h b/engines/tsage/ringworld2/ringworld2_speakers.h
index fa2946d56c..532e02576c 100644
--- a/engines/tsage/ringworld2/ringworld2_speakers.h
+++ b/engines/tsage/ringworld2/ringworld2_speakers.h
@@ -41,21 +41,27 @@ class VisualSpeaker : public Speaker {
public:
SceneActor _object1;
SceneObject *_object2;
- int _fieldF6, _fieldF8;
+ int _speakerMode;
+ int _fieldF8;
int _displayMode;
int _soundId;
int _delayAmount;
bool _removeObject;
- int _frameNumber;
+ uint32 _frameNumber;
int _numFrames;
+ int _delayAmount2;
+ uint32 _frameNumber2;
private:
void setFrame(int numFrames);
+ void setFrame2(int numFrames);
public:
VisualSpeaker();
virtual Common::String getClassName() { return "VisualSpeaker"; }
virtual void synchronize(Serializer &s);
virtual void remove();
+ virtual void signal();
+ virtual void dispatch();
virtual void setText(const Common::String &msg);
virtual void proc15() {}
virtual void proc16();
diff --git a/engines/tsage/saveload.h b/engines/tsage/saveload.h
index 4126e31822..d43ef792bc 100644
--- a/engines/tsage/saveload.h
+++ b/engines/tsage/saveload.h
@@ -150,6 +150,16 @@ public:
if (i != this->end()) ++i;
this->insert(i, newItem);
}
+
+ bool contains(T item) {
+ typename SynchronizedList<T>::iterator i = this->begin();
+ for (; i != this->end(); ++i) {
+ if (*i == item)
+ return true;
+ }
+
+ return false;
+ }
};
/**
diff --git a/engines/tsage/user_interface.cpp b/engines/tsage/user_interface.cpp
index 4bd9e49875..c0ebb804d2 100644
--- a/engines/tsage/user_interface.cpp
+++ b/engines/tsage/user_interface.cpp
@@ -84,7 +84,10 @@ void UIQuestion::showDescription(CursorType cursor) {
case GType_Ringworld2:
if ((cursor == R2_COM_SCANNER) || (cursor == R2_COM_SCANNER_2)) {
// Show communicator
- warning("TODO: Communicator");
+ Ringworld2::SceneExt *scene = static_cast<Ringworld2::SceneExt *>
+ (R2_GLOBALS._sceneManager._scene);
+ if (!scene->_sceneAreas.contains(R2_GLOBALS._scannerDialog))
+ R2_GLOBALS._scannerDialog->proc12(4, 1, 1, 160, 125);
} else {
// Show object description
SceneItem::display2(3, (int)cursor);
@@ -399,7 +402,7 @@ void UIElements::setup(const Common::Point &pt) {
}
// Setup bottom-right hand buttons
- xp += 62;
+ xp = (g_vm->getGameID() == GType_Ringworld2) ? 255 : 253;
int yp = (g_vm->getGameID() == GType_BlueForce) ? 16 : 17;
_question.setup(1, 4, 7, xp, yp, 255);
_question.setEnabled(false);
@@ -410,7 +413,7 @@ void UIElements::setup(const Common::Point &pt) {
add(&_scrollLeft);
_scrollLeft._isLeft = true;
- xp += 22;
+ xp += (g_vm->getGameID() == GType_Ringworld2) ? 21 : 22;
_scrollRight.setup(1, 4, 4, xp, yp, 255);
add(&_scrollRight);
_scrollRight._isLeft = false;
diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp
index 2bd7c47b62..04e83efbe5 100644
--- a/engines/tucker/tucker.cpp
+++ b/engines/tucker/tucker.cpp
@@ -941,7 +941,7 @@ void TuckerEngine::fadeOutPalette(int colorsCount) {
_system->getPaletteManager()->grabPalette(pal, 0, colorsCount);
for (int color = 0; color < colorsCount; ++color) {
for (int i = 0; i < 3; ++i) {
- const int c = int(pal[color * 3 + i]) + kFadePaletteStep * 3;
+ const int c = int(pal[color * 3 + i]) + kFadePaletteStep * 4;
pal[color * 3 + i] = MIN<int>(c, _currentPalette[color * 3 + i]);
}
}
@@ -954,7 +954,7 @@ void TuckerEngine::fadeInPalette(int colorsCount) {
_system->getPaletteManager()->grabPalette(pal, 0, colorsCount);
for (int color = 0; color < colorsCount; ++color) {
for (int i = 0; i < 3; ++i) {
- const int c = int(pal[color * 3 + i]) - kFadePaletteStep * 3;
+ const int c = int(pal[color * 3 + i]) - kFadePaletteStep * 4;
pal[color * 3 + i] = MAX<int>(c, 0);
}
}
@@ -2991,6 +2991,7 @@ enum TableInstructionCode {
kCode_gfg,
kCode_gv,
kCode_loc,
+ kCode_mof,
kCode_opt,
kCode_opf,
kCode_ofg,
@@ -3041,6 +3042,7 @@ static const struct {
{ "gfg", kCode_gfg },
{ "gv", kCode_gv },
{ "loc", kCode_loc },
+ { "mof", kCode_mof },
{ "opt", kCode_opt },
{ "opf", kCode_opf },
{ "ofg", kCode_ofg },
@@ -3062,8 +3064,9 @@ static const struct {
int TuckerEngine::readTableInstructionCode(int *index) {
bool match = false;
+ int nameLen = 0;
for (int i = 0; _instructions[i].name; ++i) {
- const int nameLen = strlen(_instructions[i].name);
+ nameLen = strlen(_instructions[i].name);
if (_instructions[i].name[1] == '0') {
if (_instructions[i].name[0] == _tableInstructionsPtr[0] && _instructions[i].name[2] == _tableInstructionsPtr[2]) {
const char digit = _tableInstructionsPtr[1];
@@ -3083,6 +3086,7 @@ int TuckerEngine::readTableInstructionCode(int *index) {
}
}
warning("Unhandled instruction '%c%c%c'", _tableInstructionsPtr[0], _tableInstructionsPtr[1], _tableInstructionsPtr[2]);
+ _tableInstructionsPtr += nameLen + 1;
return kCode_invalid;
}
@@ -3232,6 +3236,9 @@ int TuckerEngine::executeTableInstruction() {
case kCode_loc:
_nextLocationNum = readTableInstructionParam(2);
return 1;
+ case kCode_mof:
+ // TODO: Unknown opcode in Spanish version. Identify if this has any function.
+ return 0;
case kCode_opt:
_conversationOptionsCount = readTableInstructionParam(2);
for (i = 0; i < _conversationOptionsCount; ++i) {
diff --git a/engines/wintermute/ad/ad_response.cpp b/engines/wintermute/ad/ad_response.cpp
index 4483bbc667..d59bcf363c 100644
--- a/engines/wintermute/ad/ad_response.cpp
+++ b/engines/wintermute/ad/ad_response.cpp
@@ -166,7 +166,7 @@ BaseFont *AdResponse::getFont() const {
int32 AdResponse::getID() const {
return _iD;
}
-
+
const char *AdResponse::getText() const {
return _text;
}
diff --git a/engines/wintermute/base/base_engine.cpp b/engines/wintermute/base/base_engine.cpp
index d4b17a0a64..79b16e5c74 100644
--- a/engines/wintermute/base/base_engine.cpp
+++ b/engines/wintermute/base/base_engine.cpp
@@ -46,8 +46,8 @@ BaseEngine::BaseEngine() {
_gameId = "";
}
-void BaseEngine::init(Common::Language lang) {
- _fileManager = new BaseFileManager(lang);
+void BaseEngine::init() {
+ _fileManager = new BaseFileManager(_language);
// Don't forget to register your random source
_rnd = new Common::RandomSource("Wintermute");
_classReg = new SystemClassRegistry();
@@ -60,9 +60,11 @@ BaseEngine::~BaseEngine() {
delete _classReg;
}
-void BaseEngine::createInstance(const Common::String &gameid, Common::Language lang) {
- instance()._gameId = gameid;
- instance().init(lang);
+void BaseEngine::createInstance(const Common::String &targetName, const Common::String &gameId, Common::Language lang) {
+ instance()._targetName = targetName;
+ instance()._gameId = gameId;
+ instance()._language = lang;
+ instance().init();
}
void BaseEngine::LOG(bool res, const char *fmt, ...) {
diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h
index d972e6ebbc..1b3b976bda 100644
--- a/engines/wintermute/base/base_engine.h
+++ b/engines/wintermute/base/base_engine.h
@@ -44,17 +44,19 @@ class BaseRenderer;
class SystemClassRegistry;
class Timer;
class BaseEngine : public Common::Singleton<Wintermute::BaseEngine> {
- void init(Common::Language lang);
+ void init();
BaseFileManager *_fileManager;
Common::String _gameId;
+ Common::String _targetName;
BaseGame *_gameRef;
// We need random numbers
Common::RandomSource *_rnd;
SystemClassRegistry *_classReg;
+ Common::Language _language;
public:
BaseEngine();
~BaseEngine();
- static void createInstance(const Common::String &gameid, Common::Language lang);
+ static void createInstance(const Common::String &targetName, const Common::String &gameId, Common::Language lang);
void setGameRef(BaseGame *gameRef) { _gameRef = gameRef; }
Common::RandomSource *getRandomSource() { return _rnd; }
@@ -68,7 +70,9 @@ public:
static const Timer *getTimer();
static const Timer *getLiveTimer();
static void LOG(bool res, const char *fmt, ...);
- const char *getGameId() { return _gameId.c_str(); }
+ const char *getGameTargetName() const { return _targetName.c_str(); }
+ Common::String getGameId() const { return _gameId; }
+ Common::Language getLanguage() const { return _language; }
};
} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp
index 7d59b03684..64bdbd1660 100644
--- a/engines/wintermute/base/base_file_manager.cpp
+++ b/engines/wintermute/base/base_file_manager.cpp
@@ -269,7 +269,7 @@ Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &f
bool BaseFileManager::hasFile(const Common::String &filename) {
if (scumm_strnicmp(filename.c_str(), "savegame:", 9) == 0) {
- BasePersistenceManager pm(BaseEngine::instance().getGameId());
+ BasePersistenceManager pm(BaseEngine::instance().getGameTargetName());
if (filename.size() <= 9) {
return false;
}
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index 4d8e79b5c2..0f0d928285 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -81,7 +81,7 @@ IMPLEMENT_PERSISTENT(BaseGame, true)
//////////////////////////////////////////////////////////////////////
-BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gameId), _timerNormal(), _timerLive() {
+BaseGame::BaseGame(const Common::String &targetName) : BaseObject(this), _targetName(targetName), _timerNormal(), _timerLive() {
_shuttingDown = false;
_state = GAME_RUNNING;
@@ -212,7 +212,7 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam
#else*/
_touchInterface = false;
_constrainedMemory = false;
-
+
_settings = new BaseGameSettings(this);
//#endif
@@ -1276,11 +1276,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
stack->correctParams(2);
const char *key = stack->pop()->getString();
const char *initVal = stack->pop()->getString();
- Common::String privKey = "wme_" + StringUtil::encodeSetting(key);
- Common::String result = initVal;
- if (ConfMan.hasKey(privKey)) {
- result = StringUtil::decodeSetting(ConfMan.get(key));
- }
+ Common::String result = readRegistryString(key, initVal);
stack->pushString(result.c_str());
return STATUS_OK;
}
@@ -3734,7 +3730,7 @@ bool BaseGame::onWindowClose() {
bool BaseGame::displayDebugInfo() {
const uint32 strLength = 100;
char str[strLength];
-
+
if (_debugShowFPS) {
sprintf(str, "FPS: %d", _gameRef->_fps);
_systemFont->drawText((byte *)str, 0, 0, 100, TAL_LEFT);
@@ -3902,4 +3898,26 @@ char *BaseGame::getKeyFromStringTable(const char *str) const {
return _settings->getKeyFromStringTable(str);
}
+Common::String BaseGame::readRegistryString(const Common::String &key, const Common::String &initValue) const {
+ // Game specific hacks:
+ Common::String result = initValue;
+ // James Peris:
+ if (BaseEngine::instance().getGameId() == "jamesperis" && key == "Language") {
+ Common::Language language = BaseEngine::instance().getLanguage();
+ if (language == Common::EN_ANY) {
+ result = "english";
+ } else if (language == Common::ES_ESP) {
+ result = "spanish";
+ } else {
+ error("Invalid language set for James Peris");
+ }
+ } else { // Just fallback to using ConfMan for now
+ Common::String privKey = "wme_" + StringUtil::encodeSetting(key);
+ if (ConfMan.hasKey(privKey)) {
+ result = StringUtil::decodeSetting(ConfMan.get(key));
+ }
+ }
+ return result;
+}
+
} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h
index d51255d013..f635339286 100644
--- a/engines/wintermute/base/base_game.h
+++ b/engines/wintermute/base/base_game.h
@@ -137,7 +137,7 @@ public:
bool initialize2();
bool initialize3();
BaseTransitionMgr *_transMgr;
-
+
// String Table
void expandStringByStringTable(char **str) const;
char *getKeyFromStringTable(const char *str) const;
@@ -150,7 +150,7 @@ public:
BaseScriptable *_mathClass;
BaseSurfaceStorage *_surfaceStorage;
BaseFontStorage *_fontStorage;
- BaseGame(const Common::String &gameId);
+ BaseGame(const Common::String &targetName);
virtual ~BaseGame();
bool _debugDebugMode;
@@ -173,8 +173,8 @@ public:
// compatibility bits
bool _compatKillMethodThreads;
- const char* getGameId() const { return _gameId.c_str(); }
- void setGameId(const Common::String& gameId) { _gameId = gameId; }
+ const char* getGameTargetName() const { return _targetName.c_str(); }
+ void setGameTargetName(const Common::String& targetName) { _targetName = targetName; }
uint32 _surfaceGCCycleTime;
bool _smartCache; // RO
bool _subtitles; // RO
@@ -275,7 +275,7 @@ private:
bool _mouseRightDown;
bool _mouseMidlleDown;
-
+
BaseGameSettings *_settings;
int32 _soundBufferSizeSec;
@@ -295,7 +295,7 @@ private:
uint32 _lastTime;
uint32 _fpsTime;
uint32 _framesRendered;
- Common::String _gameId;
+ Common::String _targetName;
void setEngineLogCallback(ENGINE_LOG_CALLBACK callback = nullptr, void *data = nullptr);
ENGINE_LOG_CALLBACK _engineLogCallback;
@@ -343,6 +343,8 @@ private:
bool isDoubleClick(int32 buttonIndex);
uint32 _usedMem;
+// TODO: This should be expanded into a proper class eventually:
+ Common::String readRegistryString(const Common::String &key, const Common::String &initValue) const;
protected:
diff --git a/engines/wintermute/base/base_game_music.cpp b/engines/wintermute/base/base_game_music.cpp
index ac23801e4c..eff5d47210 100644
--- a/engines/wintermute/base/base_game_music.cpp
+++ b/engines/wintermute/base/base_game_music.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -65,10 +65,10 @@ bool BaseGameMusic::playMusic(int channel, const char *filename, bool looping, u
BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
return STATUS_FAILED;
}
-
+
delete _music[channel];
_music[channel] = nullptr;
-
+
_music[channel] = new BaseSound(_gameRef);
if (_music[channel] && DID_SUCCEED(_music[channel]->setSound(filename, Audio::Mixer::kMusicSoundType, true))) {
if (_musicStartTime[channel]) {
@@ -93,7 +93,7 @@ bool BaseGameMusic::stopMusic(int channel) {
BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
return STATUS_FAILED;
}
-
+
if (_music[channel]) {
_music[channel]->stop();
delete _music[channel];
@@ -111,7 +111,7 @@ bool BaseGameMusic::pauseMusic(int channel) {
BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
return STATUS_FAILED;
}
-
+
if (_music[channel]) {
return _music[channel]->pause();
} else {
@@ -126,7 +126,7 @@ bool BaseGameMusic::resumeMusic(int channel) {
BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
return STATUS_FAILED;
}
-
+
if (_music[channel]) {
return _music[channel]->resume();
} else {
@@ -141,7 +141,7 @@ bool BaseGameMusic::setMusicStartTime(int channel, uint32 time) {
BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
return STATUS_FAILED;
}
-
+
_musicStartTime[channel] = time;
if (_music[channel] && _music[channel]->isPlaying()) {
return _music[channel]->setPositionTime(time);
@@ -153,14 +153,14 @@ bool BaseGameMusic::setMusicStartTime(int channel, uint32 time) {
//////////////////////////////////////////////////////////////////////////
bool BaseGameMusic::updateMusicCrossfade() {
/* byte globMusicVol = _soundMgr->getVolumePercent(SOUND_MUSIC); */
-
+
if (!_musicCrossfadeRunning) {
return STATUS_OK;
}
if (_gameRef->_state == GAME_FROZEN) {
return STATUS_OK;
}
-
+
if (_musicCrossfadeChannel1 < 0 || _musicCrossfadeChannel1 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel1]) {
_musicCrossfadeRunning = false;
return STATUS_OK;
@@ -169,34 +169,34 @@ bool BaseGameMusic::updateMusicCrossfade() {
_musicCrossfadeRunning = false;
return STATUS_OK;
}
-
+
if (!_music[_musicCrossfadeChannel1]->isPlaying()) {
_music[_musicCrossfadeChannel1]->play();
}
if (!_music[_musicCrossfadeChannel2]->isPlaying()) {
_music[_musicCrossfadeChannel2]->play();
}
-
+
uint32 currentTime = _gameRef->getLiveTimer()->getTime() - _musicCrossfadeStartTime;
-
+
if (currentTime >= _musicCrossfadeLength) {
_musicCrossfadeRunning = false;
//_music[_musicCrossfadeChannel2]->setVolume(GlobMusicVol);
_music[_musicCrossfadeChannel2]->setVolumePercent(100);
-
+
_music[_musicCrossfadeChannel1]->stop();
//_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol);
_music[_musicCrossfadeChannel1]->setVolumePercent(100);
-
-
+
+
if (_musicCrossfadeSwap) {
// swap channels
BaseSound *dummy = _music[_musicCrossfadeChannel1];
int dummyInt = _musicStartTime[_musicCrossfadeChannel1];
-
+
_music[_musicCrossfadeChannel1] = _music[_musicCrossfadeChannel2];
_musicStartTime[_musicCrossfadeChannel1] = _musicStartTime[_musicCrossfadeChannel2];
-
+
_music[_musicCrossfadeChannel2] = dummy;
_musicStartTime[_musicCrossfadeChannel2] = dummyInt;
}
@@ -205,10 +205,10 @@ bool BaseGameMusic::updateMusicCrossfade() {
//_music[_musicCrossfadeChannel2]->setVolume((float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol);
_music[_musicCrossfadeChannel1]->setVolumePercent((int)(100.0f - (float)currentTime / (float)_musicCrossfadeLength * 100.0f));
_music[_musicCrossfadeChannel2]->setVolumePercent((int)((float)currentTime / (float)_musicCrossfadeLength * 100.0f));
-
+
//_gameRef->QuickMessageForm("%d %d", _music[_musicCrossfadeChannel1]->GetVolume(), _music[_musicCrossfadeChannel2]->GetVolume());
}
-
+
return STATUS_OK;
}
@@ -242,15 +242,15 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
stack->correctParams(4);
channel = stack->pop()->getInt();
}
-
+
const char *filename = stack->pop()->getString();
ScValue *valLooping = stack->pop();
bool looping = valLooping->isNULL() ? true : valLooping->getBool();
-
+
ScValue *valLoopStart = stack->pop();
uint32 loopStart = (uint32)(valLoopStart->isNULL() ? 0 : valLoopStart->getInt());
-
-
+
+
if (DID_FAIL(playMusic(channel, filename, looping, loopStart))) {
stack->pushBool(false);
} else {
@@ -258,20 +258,20 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
}
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// StopMusic / StopMusicChannel
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "StopMusic") == 0 || strcmp(name, "StopMusicChannel") == 0) {
int channel = 0;
-
+
if (strcmp(name, "StopMusic") == 0) {
stack->correctParams(0);
} else {
stack->correctParams(1);
channel = stack->pop()->getInt();
}
-
+
if (DID_FAIL(stopMusic(channel))) {
stack->pushBool(false);
} else {
@@ -279,20 +279,20 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
}
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// PauseMusic / PauseMusicChannel
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "PauseMusic") == 0 || strcmp(name, "PauseMusicChannel") == 0) {
int channel = 0;
-
+
if (strcmp(name, "PauseMusic") == 0) {
stack->correctParams(0);
} else {
stack->correctParams(1);
channel = stack->pop()->getInt();
}
-
+
if (DID_FAIL(pauseMusic(channel))) {
stack->pushBool(false);
} else {
@@ -300,7 +300,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
}
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// ResumeMusic / ResumeMusicChannel
//////////////////////////////////////////////////////////////////////////
@@ -312,7 +312,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
stack->correctParams(1);
channel = stack->pop()->getInt();
}
-
+
if (DID_FAIL(resumeMusic(channel))) {
stack->pushBool(false);
} else {
@@ -320,7 +320,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
}
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// GetMusic / GetMusicChannel
//////////////////////////////////////////////////////////////////////////
@@ -343,7 +343,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
}
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// SetMusicPosition / SetMusicChannelPosition
//////////////////////////////////////////////////////////////////////////
@@ -355,18 +355,18 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
stack->correctParams(2);
channel = stack->pop()->getInt();
}
-
+
uint32 time = stack->pop()->getInt();
-
+
if (DID_FAIL(setMusicStartTime(channel, time))) {
stack->pushBool(false);
} else {
stack->pushBool(true);
}
-
+
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// GetMusicPosition / GetMusicChannelPosition
//////////////////////////////////////////////////////////////////////////
@@ -378,7 +378,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
stack->correctParams(1);
channel = stack->pop()->getInt();
}
-
+
if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
stack->pushInt(0);
} else {
@@ -386,7 +386,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
}
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// IsMusicPlaying / IsMusicChannelPlaying
//////////////////////////////////////////////////////////////////////////
@@ -398,7 +398,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
stack->correctParams(1);
channel = stack->pop()->getInt();
}
-
+
if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
stack->pushBool(false);
} else {
@@ -406,7 +406,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
}
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// SetMusicVolume / SetMusicChannelVolume
//////////////////////////////////////////////////////////////////////////
@@ -418,7 +418,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
stack->correctParams(2);
channel = stack->pop()->getInt();
}
-
+
int volume = stack->pop()->getInt();
if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
stack->pushBool(false);
@@ -431,7 +431,7 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
}
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// GetMusicVolume / GetMusicChannelVolume
//////////////////////////////////////////////////////////////////////////
@@ -443,16 +443,16 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
stack->correctParams(1);
channel = stack->pop()->getInt();
}
-
+
if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
stack->pushInt(0);
} else {
stack->pushInt(_music[channel]->getVolumePercent());
}
-
+
return STATUS_OK;
}
-
+
//////////////////////////////////////////////////////////////////////////
// MusicCrossfade
//////////////////////////////////////////////////////////////////////////
@@ -462,34 +462,34 @@ bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *this
int channel2 = stack->pop()->getInt(0);
uint32 fadeLength = (uint32)stack->pop()->getInt(0);
bool swap = stack->pop()->getBool(true);
-
+
if (_musicCrossfadeRunning) {
script->runtimeError("Game.MusicCrossfade: Music crossfade is already in progress.");
stack->pushBool(false);
return STATUS_OK;
}
-
+
_musicCrossfadeStartTime = _gameRef->getLiveTimer()->getTime();
_musicCrossfadeChannel1 = channel1;
_musicCrossfadeChannel2 = channel2;
_musicCrossfadeLength = fadeLength;
_musicCrossfadeSwap = swap;
-
+
_musicCrossfadeRunning = true;
-
+
stack->pushBool(true);
return STATUS_OK;
- }
+ }
//////////////////////////////////////////////////////////////////////////
// GetSoundLength
//////////////////////////////////////////////////////////////////////////
else if (strcmp(name, "GetSoundLength") == 0) {
stack->correctParams(1);
-
+
int length = 0;
const char *filename = stack->pop()->getString();
-
+
BaseSound *sound = new BaseSound(_gameRef);
if (sound && DID_SUCCEED(sound->setSound(filename, Audio::Mixer::kMusicSoundType, true))) {
length = sound->getLength();
diff --git a/engines/wintermute/base/base_game_music.h b/engines/wintermute/base/base_game_music.h
index 0ac904b8c1..150ea6200c 100644
--- a/engines/wintermute/base/base_game_music.h
+++ b/engines/wintermute/base/base_game_music.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -53,7 +53,7 @@ public:
bool stopMusic(int channel);
bool playMusic(int channel, const char *filename, bool looping = true, uint32 loopStart = 0);
bool updateMusicCrossfade();
-
+
bool persistChannels(BasePersistenceManager *persistMgr);
bool persistCrossfadeSettings(BasePersistenceManager *persistMgr);
private:
diff --git a/engines/wintermute/base/base_game_settings.cpp b/engines/wintermute/base/base_game_settings.cpp
index 55fbe39fd2..9b5eb314bb 100644
--- a/engines/wintermute/base/base_game_settings.cpp
+++ b/engines/wintermute/base/base_game_settings.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -47,7 +47,7 @@ BaseGameSettings::BaseGameSettings(BaseGame *gameRef) {
_allowAccessTab = true;
_allowAboutTab = true;
_allowDesktopRes = false;
-
+
_compressedSavegames = true;
_richSavedGames = false;
_savedGameExt = "dsv";
@@ -101,21 +101,21 @@ bool BaseGameSettings::loadSettings(const char *filename) {
TOKEN_TABLE(SAVED_GAME_EXT)
TOKEN_TABLE(GUID)
TOKEN_TABLE_END
-
-
+
+
byte *origBuffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
if (origBuffer == nullptr) {
BaseEngine::LOG(0, "BaseGame::LoadSettings failed for file '%s'", filename);
return STATUS_FAILED;
}
-
+
bool ret = STATUS_OK;
-
+
byte *buffer = origBuffer;
byte *params;
int cmd;
BaseParser parser;
-
+
if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_SETTINGS) {
BaseEngine::LOG(0, "'SETTINGS' keyword expected in game settings file.");
return STATUS_FAILED;
@@ -130,61 +130,61 @@ bool BaseGameSettings::loadSettings(const char *filename) {
strcpy(_gameFile, (char *)params);
}
break;
-
+
case TOKEN_STRING_TABLE:
if (DID_FAIL(_stringTable->loadFile((char *)params))) {
cmd = PARSERR_GENERIC;
}
break;
-
+
case TOKEN_RESOLUTION:
parser.scanStr((char *)params, "%d,%d", &_resWidth, &_resHeight);
break;
-
+
case TOKEN_REQUIRE_3D_ACCELERATION:
parser.scanStr((char *)params, "%b", &_requireAcceleration);
break;
-
+
case TOKEN_REQUIRE_SOUND:
parser.scanStr((char *)params, "%b", &_requireSound);
break;
-
+
case TOKEN_HWTL_MODE:
parser.scanStr((char *)params, "%d", &_TLMode);
break;
-
+
case TOKEN_ALLOW_WINDOWED_MODE:
parser.scanStr((char *)params, "%b", &_allowWindowed);
break;
-
+
case TOKEN_ALLOW_DESKTOP_RES:
parser.scanStr((char *)params, "%b", &_allowDesktopRes);
break;
-
+
case TOKEN_ALLOW_ADVANCED:
parser.scanStr((char *)params, "%b", &_allowAdvanced);
break;
-
+
case TOKEN_ALLOW_ACCESSIBILITY_TAB:
parser.scanStr((char *)params, "%b", &_allowAccessTab);
break;
-
+
case TOKEN_ALLOW_ABOUT_TAB:
parser.scanStr((char *)params, "%b", &_allowAboutTab);
break;
-
+
case TOKEN_REGISTRY_PATH:
//BaseEngine::instance().getRegistry()->setBasePath((char *)params);
break;
-
+
case TOKEN_RICH_SAVED_GAMES:
parser.scanStr((char *)params, "%b", &_richSavedGames);
break;
-
+
case TOKEN_SAVED_GAME_EXT:
_savedGameExt = (char *)params;
break;
-
+
case TOKEN_GUID:
break;
}
@@ -197,12 +197,12 @@ bool BaseGameSettings::loadSettings(const char *filename) {
BaseEngine::LOG(0, "Error loading game settings '%s'", filename);
ret = STATUS_FAILED;
}
-
+
_allowWindowed = true; // TODO: These two settings should probably be cleaned out altogether.
_compressedSavegames = true;
-
+
delete[] origBuffer;
-
+
return ret;
}
diff --git a/engines/wintermute/base/base_game_settings.h b/engines/wintermute/base/base_game_settings.h
index 1dfb0b50cc..92c00ab0c2 100644
--- a/engines/wintermute/base/base_game_settings.h
+++ b/engines/wintermute/base/base_game_settings.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/wintermute/base/base_keyboard_state.h b/engines/wintermute/base/base_keyboard_state.h
index b62ece02b7..e321dfee16 100644
--- a/engines/wintermute/base/base_keyboard_state.h
+++ b/engines/wintermute/base/base_keyboard_state.h
@@ -61,7 +61,7 @@ private:
bool _currentPrintable;
uint32 _currentKeyData;
uint32 _currentCharCode;
-
+
bool _currentShift;
bool _currentAlt;
bool _currentControl;
diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp
index 5dbacb157b..23290e1574 100644
--- a/engines/wintermute/base/base_persistence_manager.cpp
+++ b/engines/wintermute/base/base_persistence_manager.cpp
@@ -94,7 +94,7 @@ BasePersistenceManager::BasePersistenceManager(const char *savePrefix, bool dele
if (savePrefix) {
_savePrefix = savePrefix;
} else if (_gameRef) {
- _savePrefix = _gameRef->getGameId();
+ _savePrefix = _gameRef->getGameTargetName();
} else {
_savePrefix = "wmesav";
}
@@ -282,7 +282,7 @@ bool BasePersistenceManager::initSave(const char *desc) {
} else {
_saveStream->writeUint32LE(0);
}
-
+
thumbnailOK = true;
}
}
diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp
index c20881e425..b3f05ce977 100644
--- a/engines/wintermute/base/gfx/base_renderer.cpp
+++ b/engines/wintermute/base/gfx/base_renderer.cpp
@@ -113,15 +113,21 @@ void BaseRenderer::setIndicatorVal(int value) {
}
void BaseRenderer::setLoadingScreen(const char *filename, int x, int y) {
- // TODO: Handle NULL
- _loadImageName = filename;
+ if (filename == nullptr) {
+ _saveImageName = "";
+ } else {
+ _loadImageName = filename;
+ }
_loadImageX = x;
_loadImageY = y;
}
void BaseRenderer::setSaveImage(const char *filename, int x, int y) {
- // TODO: Handle NULL
- _saveImageName = filename;
+ if (filename == nullptr) {
+ _saveImageName = "";
+ } else {
+ _saveImageName = filename;
+ }
_saveImageX = x;
_saveImageY = y;
}
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
index e1424cea87..eca2998da5 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -546,7 +546,7 @@ void BaseRenderOSystem::drawTickets() {
// Revert the colorMod-state.
_colorMod = oldColorMod;
-
+
it = _renderQueue.begin();
// Clean out the old tickets
decrement = 0;
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
index 0572ef2f6e..87bb2fdb53 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -163,7 +163,7 @@ bool BaseSurfaceOSystem::finishLoad() {
needsColorKey = true;
}
}
-
+
if (needsColorKey) {
TransparentSurface trans(*_surface);
trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, replaceAlpha);
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
index 36c5d7b740..98c5be62a8 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.h b/engines/wintermute/base/gfx/osystem/render_ticket.h
index 968b42b5e1..64df3590a1 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.h
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/wintermute/base/save_thumb_helper.cpp b/engines/wintermute/base/save_thumb_helper.cpp
index bab29c5cf8..535648eddd 100644
--- a/engines/wintermute/base/save_thumb_helper.cpp
+++ b/engines/wintermute/base/save_thumb_helper.cpp
@@ -56,23 +56,23 @@ BaseImage *SaveThumbHelper::storeThumb(bool doFlip, int width, int height) {
// works normally for direct3d
_gameRef->displayContent(false);
_gameRef->_renderer->flip();
-
+
_gameRef->displayContent(false);
_gameRef->_renderer->flip();
}
-
+
BaseImage *screenshot = _gameRef->_renderer->takeScreenshot();
if (!screenshot) {
return nullptr;
}
-
+
// normal thumbnail
if (_gameRef->getSaveThumbWidth() > 0 && _gameRef->getSaveThumbHeight() > 0) {
thumbnail = new BaseImage();
thumbnail->copyFrom(screenshot, width, height);
}
-
-
+
+
delete screenshot;
screenshot = nullptr;
}
@@ -99,7 +99,7 @@ bool SaveThumbHelper::storeThumbnail(bool doFlip) {
bool SaveThumbHelper::storeScummVMThumbNail(bool doFlip) {
delete _scummVMThumb;
_scummVMThumb = nullptr;
-
+
_scummVMThumb = storeThumb(doFlip, kThumbnailWidth, kThumbnailHeight2);
if (!_scummVMThumb) {
return STATUS_FAILED;
diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp
index 1b945c2e1c..0cffa94b50 100644
--- a/engines/wintermute/base/scriptables/script.cpp
+++ b/engines/wintermute/base/scriptables/script.cpp
@@ -461,6 +461,7 @@ void ScScript::cleanup() {
_parentScript = nullptr; // ref only
delete _scriptStream;
+ _scriptStream = nullptr;
}
diff --git a/engines/wintermute/base/timer.cpp b/engines/wintermute/base/timer.cpp
index 5dfc117f48..96097c10d5 100644
--- a/engines/wintermute/base/timer.cpp
+++ b/engines/wintermute/base/timer.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/wintermute/base/timer.h b/engines/wintermute/base/timer.h
index ec5477ba2e..4099c6c825 100644
--- a/engines/wintermute/base/timer.h
+++ b/engines/wintermute/base/timer.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -51,7 +51,7 @@ public:
void persist(BasePersistenceManager *persistMgr);
};
-
+
} // End of namespace Wintermute
#endif
diff --git a/engines/wintermute/debugger.cpp b/engines/wintermute/debugger.cpp
index 92b8e6251f..6e865befb9 100644
--- a/engines/wintermute/debugger.cpp
+++ b/engines/wintermute/debugger.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/engines/wintermute/debugger.h b/engines/wintermute/debugger.h
index 588b81af97..6fbbb084f0 100644
--- a/engines/wintermute/debugger.h
+++ b/engines/wintermute/debugger.h
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -32,7 +32,7 @@ class Console : public GUI::Debugger {
public:
Console(WintermuteEngine *vm);
virtual ~Console();
-
+
bool Cmd_ShowFps(int argc, const char **argv);
bool Cmd_DumpFile(int argc, const char **argv);
private:
diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h
index 09426c9307..3d9afe7c97 100644
--- a/engines/wintermute/detection_tables.h
+++ b/engines/wintermute/detection_tables.h
@@ -42,15 +42,17 @@ static const PlainGameDescriptor wintermuteGames[] = {
{"dreamscape", "Dreamscape"},
{"ghostsheet", "Ghost in the Sheet"},
{"hamlet", "Hamlet or the last game without MMORPS features, shaders and product placement"},
- {"jamesperis", "James Peris: No License Nor Control"},
+ {"jamesperis", "James Peris: No License Nor Control"},
{"julia", "J.U.L.I.A."},
{"mirage", "Mirage"},
{"pigeons", "Pigeons in the Park"},
{"reversion1", "Reversion: The Escape"},
{"reversion2", "Reversion: The Meeting"},
{"rosemary", "Rosemary"},
+ {"shinestar", "The Shine of a Star"},
{"thebox", "The Box"},
- {"tradestory", "The Trader of Stories"},
+ {"tib", "Fairy Tales About Toshechka and Boshechka"},
+ {"tradestory", "The Trader of Stories"},
{"twc", "the white chamber"},
{"wintermute", "Wintermute engine game"},
{0, 0}
@@ -292,12 +294,43 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
- // James Peris: No License Nor Control
+ // James Peris: No License Nor Control (English)
+ {
+ "jamesperis",
+ "",
+ AD_ENTRY1s("data.dcp", "a420961e170cb7d168a0d2bae2fe5218", 225294032),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // James Peris: No License Nor Control (Spanish)
+ {
+ "jamesperis",
+ "",
+ AD_ENTRY1s("data.dcp", "a420961e170cb7d168a0d2bae2fe5218", 225294032),
+ Common::ES_ESP,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
+ // James Peris: No License Nor Control (Demo) (English)
{
"jamesperis",
"Demo",
AD_ENTRY1s("data.dcp", "edb9f9c7a08993c1e28f4e477b5f9830", 116113507),
- Common::UNK_LANG, // No solution in place to select language
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE |
+ ADGF_DEMO,
+ GUIO0()
+ },
+ // James Peris: No License Nor Control (Demo) (Spanish)
+ {
+ "jamesperis",
+ "Demo",
+ AD_ENTRY1s("data.dcp", "edb9f9c7a08993c1e28f4e477b5f9830", 116113507),
+ Common::ES_ESP,
Common::kPlatformWindows,
ADGF_UNSTABLE |
ADGF_DEMO,
@@ -581,6 +614,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // The Shine of a Star
+ {
+ "shinestar",
+ "",
+ AD_ENTRY1s("data.dcp", "f05abe9e2427a5e4f73648fa09c4ba8e", 94113060),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// The Box
{
"thebox",
@@ -591,6 +634,16 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO0()
},
+ // Fairy Tales About Toshechka and Boshechka
+ {
+ "tib",
+ "",
+ AD_ENTRY1s("data.dcp", "87d296ef3f46570ed18f000d3885db77", 340264526),
+ Common::RU_RUS,
+ Common::kPlatformWindows,
+ ADGF_UNSTABLE,
+ GUIO0()
+ },
// The Trader of Stories
{
"tradestory",
diff --git a/engines/wintermute/platform_osystem.cpp b/engines/wintermute/platform_osystem.cpp
index 362c0da624..8b1a6e38e9 100644
--- a/engines/wintermute/platform_osystem.cpp
+++ b/engines/wintermute/platform_osystem.cpp
@@ -125,9 +125,12 @@ void BasePlatform::handleEvent(Common::Event *event) {
// _gameRef->AutoSaveOnExit();
// _gameRef->_quitting = true;
// }
- if (_gameRef) {
- _gameRef->onWindowClose();
- }
+
+// The engine CAN query for closing, but we disable it for now, as the EVENT_QUIT-event
+// can't be stopped.
+// if (_gameRef) {
+// _gameRef->onWindowClose();
+// }
break;
default:
// TODO: Do we care about any other events?
diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp
index 8f9db8392f..ac24c6f15e 100644
--- a/engines/wintermute/video/video_theora_player.cpp
+++ b/engines/wintermute/video/video_theora_player.cpp
@@ -163,14 +163,14 @@ bool VideoTheoraPlayer::resetStream() {
if (!_file) {
return STATUS_FAILED;
}
-
+
#if defined (USE_THEORADEC)
_theoraDecoder = new Video::TheoraDecoder();
#else
return STATUS_FAILED;
#endif
_theoraDecoder->loadStream(_file);
-
+
if (!_theoraDecoder->isVideoLoaded()) {
return STATUS_FAILED;
}
diff --git a/engines/wintermute/video/video_theora_player.h b/engines/wintermute/video/video_theora_player.h
index 364509a080..40b9ba104a 100644
--- a/engines/wintermute/video/video_theora_player.h
+++ b/engines/wintermute/video/video_theora_player.h
@@ -101,7 +101,7 @@ public:
// video properties
int32 _posX;
int32 _posY;
-
+
bool _dontDropFrames;
private:
int32 _state;
diff --git a/engines/wintermute/wintermute.cpp b/engines/wintermute/wintermute.cpp
index 89a6f1b3e0..a878944661 100644
--- a/engines/wintermute/wintermute.cpp
+++ b/engines/wintermute/wintermute.cpp
@@ -26,7 +26,6 @@
#include "common/debug.h"
#include "common/debug-channels.h"
#include "common/error.h"
-#include "common/EventRecorder.h"
#include "common/file.h"
#include "common/fs.h"
#include "common/tokenizer.h"
@@ -134,7 +133,7 @@ Common::Error WintermuteEngine::run() {
}
int WintermuteEngine::init() {
- BaseEngine::createInstance(_targetName, _gameDescription->language);
+ BaseEngine::createInstance(_targetName, _gameDescription->gameid, _gameDescription->language);
_game = new AdGame(_targetName);
if (!_game) {
return 1;
@@ -148,7 +147,7 @@ int WintermuteEngine::init() {
_game->initialize1();
// set gameId, for savegame-naming:
- _game->setGameId(_targetName);
+ _game->setGameTargetName(_targetName);
if (DID_FAIL(_game->loadSettings("startup.settings"))) {
_game->LOG(0, "Error loading game settings.");
@@ -251,6 +250,9 @@ int WintermuteEngine::messageLoop() {
}
prevTime = time;
}
+ if (shouldQuit()) {
+ break;
+ }
if (_game && _game->_quitting) {
break;
}
diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp
index c818101645..6825767dfd 100644
--- a/graphics/cursorman.cpp
+++ b/graphics/cursorman.cpp
@@ -48,6 +48,9 @@ bool CursorManager::isVisible() {
bool CursorManager::showMouse(bool visible) {
if (_cursorStack.empty())
return false;
+ if (_locked) {
+ return false;
+ }
_cursorStack.top()->_visible = visible;
@@ -225,6 +228,10 @@ void CursorManager::replaceCursorPalette(const byte *colors, uint start, uint nu
}
}
+void CursorManager::lock(bool locked) {
+ _locked = locked;
+}
+
CursorManager::Cursor::Cursor(const void *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
#ifdef USE_RGB_COLOR
if (!format)
diff --git a/graphics/cursorman.h b/graphics/cursorman.h
index 66e8d1ba56..b4d8ad94ce 100644
--- a/graphics/cursorman.h
+++ b/graphics/cursorman.h
@@ -160,12 +160,15 @@ public:
*/
void replaceCursorPalette(const byte *colors, uint start, uint num);
+ void lock(bool locked);
private:
friend class Common::Singleton<SingletonBaseType>;
// Even though this is basically the default constructor we implement it
// ourselves, so it is private and thus there is no way to create this class
// except from the Singleton code.
- CursorManager() {}
+ CursorManager() {
+ _locked = false;
+ }
~CursorManager();
struct Cursor {
@@ -198,6 +201,7 @@ private:
};
Common::Stack<Cursor *> _cursorStack;
Common::Stack<Palette *> _cursorPaletteStack;
+ bool _locked;
};
} // End of namespace Graphics
diff --git a/graphics/scaler.h b/graphics/scaler.h
index 1e5b796631..54d022d202 100644
--- a/graphics/scaler.h
+++ b/graphics/scaler.h
@@ -89,4 +89,10 @@ extern bool createThumbnailFromScreen(Graphics::Surface *surf);
*/
extern bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, const uint8 *palette);
+/**
+ * Downscale screenshot to thumbnale size.
+ *
+ */
+extern bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in);
+
#endif
diff --git a/graphics/scaler/thumbnail_intern.cpp b/graphics/scaler/thumbnail_intern.cpp
index 88f3cc2077..8a98263eee 100644
--- a/graphics/scaler/thumbnail_intern.cpp
+++ b/graphics/scaler/thumbnail_intern.cpp
@@ -134,7 +134,7 @@ static bool grabScreen565(Graphics::Surface *surf) {
return true;
}
-static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
+bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
uint16 width = in.w;
uint16 inHeight = in.h;
@@ -206,7 +206,7 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) {
return true;
}
-bool createThumbnailFromScreen(Graphics::Surface* surf) {
+bool createThumbnailFromScreen(Graphics::Surface *surf) {
assert(surf);
Graphics::Surface screen;
@@ -236,3 +236,31 @@ bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h,
return createThumbnail(*surf, screen);
}
+
+// this is somewhat awkward, but createScreenShot should logically be in graphics,
+// but moving other functions in this file into that namespace breaks several engines
+namespace Graphics {
+bool createScreenShot(Graphics::Surface &surf) {
+ Graphics::PixelFormat screenFormat = g_system->getScreenFormat();
+ //convert surface to 2 bytes pixel format to avoid problems with palette saving and loading
+ if ((screenFormat.bytesPerPixel == 1) || (screenFormat.bytesPerPixel == 2)) {
+ return grabScreen565(&surf);
+ } else {
+ Graphics::Surface *screen = g_system->lockScreen();
+ if (!screen) {
+ return false;
+ }
+ surf.create(screen->w, screen->h, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
+ for (uint y = 0; y < screen->h; ++y) {
+ for (uint x = 0; x < screen->w; ++x) {
+ byte r = 0, g = 0, b = 0, a = 0;
+ uint32 col = READ_UINT32(screen->getBasePtr(x, y));
+ screenFormat.colorToARGB(col, a, r, g, b);
+ ((uint32 *)surf.pixels)[y * surf.w + x] = Graphics::ARGBToColor<Graphics::ColorMasks<8888> >(a, r, g, b);
+ }
+ }
+ g_system->unlockScreen();
+ return true;
+ }
+}
+} // End of namespace Graphics
diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp
index ddb377306d..e3f368dffa 100644
--- a/graphics/thumbnail.cpp
+++ b/graphics/thumbnail.cpp
@@ -23,6 +23,7 @@
#include "graphics/scaler.h"
#include "graphics/colormasks.h"
#include "common/endian.h"
+#include "common/algorithm.h"
#include "common/system.h"
#include "common/stream.h"
#include "common/textconsole.h"
@@ -42,7 +43,16 @@ struct ThumbnailHeader {
#define ThumbnailHeaderSize (4+4+1+2+2+(1+4+4))
-bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) {
+enum HeaderState {
+ /// There is no header present
+ kHeaderNone,
+ /// The header present only has reliable values for version and size
+ kHeaderUnsupported,
+ /// The header is present and the version is supported
+ kHeaderPresent
+};
+
+HeaderState loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) {
header.type = in.readUint32BE();
// We also accept the bad 'BMHT' header here, for the sake of compatibility
// with some older savegames which were written incorrectly due to a bug in
@@ -50,16 +60,28 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou
if (header.type != MKTAG('T','H','M','B') && header.type != MKTAG('B','M','H','T')) {
if (outputWarnings)
warning("couldn't find thumbnail header type");
- return false;
+ return kHeaderNone;
}
header.size = in.readUint32BE();
header.version = in.readByte();
+ // Do a check whether any read errors had occured. If so we cannot use the
+ // values obtained for size and version because they might be bad.
+ if (in.err() || in.eos()) {
+ // TODO: We fake that there is no header. This is actually not quite
+ // correct since we found the start of the header and then things
+ // started to break. Right no we leave detection of this to the client.
+ // Since this case is caused by broken files, the client code should
+ // catch it anyway... If there is a nicer solution here, we should
+ // implement it.
+ return kHeaderNone;
+ }
+
if (header.version > THMB_VERSION) {
if (outputWarnings)
warning("trying to load a newer thumbnail version: %d instead of %d", header.version, THMB_VERSION);
- return false;
+ return kHeaderUnsupported;
}
header.width = in.readUint16BE();
@@ -81,7 +103,15 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou
header.format = createPixelFormat<565>();
}
- return true;
+ if (in.err() || in.eos()) {
+ // When we reached this point we know that at least the size and
+ // version field was loaded successfully, thus we tell this header
+ // is not supported and silently hope that the client code is
+ // prepared to handle read errors.
+ return kHeaderUnsupported;
+ } else {
+ return kHeaderPresent;
+ }
}
} // end of anonymous namespace
@@ -89,7 +119,12 @@ bool checkThumbnailHeader(Common::SeekableReadStream &in) {
uint32 position = in.pos();
ThumbnailHeader header;
- bool hasHeader = loadHeader(in, header, false);
+ // TODO: It is not clear whether this is the best semantics. Now
+ // checkThumbnailHeader will return true even when the thumbnail header
+ // found is actually not usable. However, most engines seem to use this
+ // to detect the presence of any header and if there is none it wont even
+ // try to skip it. Thus, this looks like the best solution for now...
+ bool hasHeader = (loadHeader(in, header, false) != kHeaderNone);
in.seek(position, SEEK_SET);
@@ -100,7 +135,9 @@ bool skipThumbnail(Common::SeekableReadStream &in) {
uint32 position = in.pos();
ThumbnailHeader header;
- if (!loadHeader(in, header, false)) {
+ // We can skip unsupported and supported headers. So we only seek back
+ // to the old position in case there is no header at all.
+ if (loadHeader(in, header, false) == kHeaderNone) {
in.seek(position, SEEK_SET);
return false;
}
@@ -110,10 +147,23 @@ bool skipThumbnail(Common::SeekableReadStream &in) {
}
Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) {
+ const uint32 position = in.pos();
ThumbnailHeader header;
-
- if (!loadHeader(in, header, true))
+ HeaderState headerState = loadHeader(in, header, true);
+
+ // Try to handle unsupported/broken headers gracefully. If there is no
+ // header at all, we seek back and return at this point. If there is an
+ // unsupported/broken header, we skip the actual data and return. The
+ // downside is that we might reset the end of stream flag with this and
+ // the client code would not be able to notice a read past the end of the
+ // stream at this point then.
+ if (headerState == kHeaderNone) {
+ in.seek(position, SEEK_SET);
+ return 0;
+ } else if (headerState == kHeaderUnsupported) {
+ in.seek(header.size - (in.pos() - position), SEEK_CUR);
return 0;
+ }
if (header.format.bytesPerPixel != 2 && header.format.bytesPerPixel != 4) {
warning("trying to load thumbnail with unsupported bit depth %d", header.format.bytesPerPixel);
@@ -143,7 +193,6 @@ Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) {
assert(0);
}
}
-
return to;
}
@@ -216,4 +265,55 @@ bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) {
return true;
}
+
+/**
+ * Returns an array indicating which pixels of a source image horizontally or vertically get
+ * included in a scaled image
+ */
+int *scaleLine(int size, int srcSize) {
+ int scale = 100 * size / srcSize;
+ assert(scale > 0);
+ int *v = new int[size];
+ Common::fill(v, &v[size], 0);
+
+ int distCtr = 0;
+ int *destP = v;
+ for (int distIndex = 0; distIndex < srcSize; ++distIndex) {
+ distCtr += scale;
+ while (distCtr >= 100) {
+ assert(destP < &v[size]);
+ *destP++ = distIndex;
+ distCtr -= 100;
+ }
+ }
+
+ return v;
+}
+
+Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize) {
+ Graphics::Surface *s = new Graphics::Surface();
+ s->create(xSize, ySize, srcImage.format);
+
+ int *horizUsage = scaleLine(xSize, srcImage.w);
+ int *vertUsage = scaleLine(ySize, srcImage.h);
+
+ // Loop to create scaled version
+ for (int yp = 0; yp < ySize; ++yp) {
+ const byte *srcP = (const byte *)srcImage.getBasePtr(0, vertUsage[yp]);
+ byte *destP = (byte *)s->getBasePtr(0, yp);
+
+ for (int xp = 0; xp < xSize; ++xp) {
+ const byte *tempSrcP = srcP + (horizUsage[xp] * srcImage.format.bytesPerPixel);
+ for (int byteCtr = 0; byteCtr < srcImage.format.bytesPerPixel; ++byteCtr) {
+ *destP++ = *tempSrcP++;
+ }
+ }
+ }
+
+ // Delete arrays and return surface
+ delete[] horizUsage;
+ delete[] vertUsage;
+ return s;
+}
+
} // End of namespace Graphics
diff --git a/graphics/thumbnail.h b/graphics/thumbnail.h
index 45a0fdbf07..c857809c91 100644
--- a/graphics/thumbnail.h
+++ b/graphics/thumbnail.h
@@ -64,6 +64,24 @@ bool saveThumbnail(Common::WriteStream &out);
*/
bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb);
+/**
+ * Grabs framebuffer into surface
+ *
+ * @param surf a surface
+ * @return false if a error occurred
+ */
+bool createScreenShot(Graphics::Surface &surf);
+
+/**
+ * Scales a passed surface, creating a new surface with the result
+ * @param srcImage Source image to scale
+ * @param xSize New surface width
+ * @param ySize New surface height
+ * @remarks Caller is responsible for freeing the returned surface
+ */
+Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize);
+
+
} // End of namespace Graphics
#endif
diff --git a/graphics/yuv_to_rgb.h b/graphics/yuv_to_rgb.h
index f785422c5a..a1e61ec705 100644
--- a/graphics/yuv_to_rgb.h
+++ b/graphics/yuv_to_rgb.h
@@ -22,10 +22,17 @@
/**
* @file
- * YUV to RGB conversion used in engines:
- * - mohawk
- * - scumm (he)
- * - sword25
+ * YUV to RGB conversion.
+ *
+ * Used in graphics:
+ * - JPEGDecoder
+ *
+ * Used in video:
+ * - BinkDecoder
+ * - Indeo3Decoder
+ * - PSXStreamDecoder
+ * - TheoraDecoder
+ * - SVQ1Decoder
*/
#ifndef GRAPHICS_YUV_TO_RGB_H
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
new file mode 100644
index 0000000000..fd0093d266
--- /dev/null
+++ b/gui/EventRecorder.cpp
@@ -0,0 +1,678 @@
+/* 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/EventRecorder.h"
+
+#ifdef ENABLE_EVENTRECORDER
+
+namespace Common {
+DECLARE_SINGLETON(GUI::EventRecorder);
+}
+
+#include "common/debug-channels.h"
+#include "backends/timer/sdl/sdl-timer.h"
+#include "backends/mixer/sdl/sdl-mixer.h"
+#include "common/config-manager.h"
+#include "common/md5.h"
+#include "gui/gui-manager.h"
+#include "gui/widget.h"
+#include "gui/onscreendialog.h"
+#include "common/random.h"
+#include "common/savefile.h"
+#include "common/textconsole.h"
+#include "graphics/thumbnail.h"
+#include "graphics/surface.h"
+#include "graphics/scaler.h"
+
+namespace GUI {
+
+
+const int kMaxRecordsNames = 0x64;
+const int kDefaultScreenshotPeriod = 60000;
+const int kDefaultBPP = 2;
+
+uint32 readTime(Common::ReadStream *inFile) {
+ uint32 d = inFile->readByte();
+ if (d == 0xff) {
+ d = inFile->readUint32LE();
+ }
+
+ return d;
+}
+
+void writeTime(Common::WriteStream *outFile, uint32 d) {
+ //Simple RLE compression
+ if (d >= 0xff) {
+ outFile->writeByte(0xff);
+ outFile->writeUint32LE(d);
+ } else {
+ outFile->writeByte(d);
+ }
+}
+
+EventRecorder::EventRecorder() {
+ _timerManager = NULL;
+ _recordMode = kPassthrough;
+ _fakeMixerManager = NULL;
+ _initialized = false;
+ _needRedraw = false;
+ _fastPlayback = false;
+
+ _fakeTimer = 0;
+ _savedState = false;
+ _needcontinueGame = false;
+ _temporarySlot = 0;
+ _realSaveManager = 0;
+ _realMixerManager = 0;
+ _controlPanel = 0;
+ _lastMillis = 0;
+ _lastScreenshotTime = 0;
+ _screenshotPeriod = 0;
+ _playbackFile = 0;
+
+ DebugMan.addDebugChannel(kDebugLevelEventRec, "EventRec", "Event recorder debug level");
+}
+
+EventRecorder::~EventRecorder() {
+ if (_timerManager != NULL) {
+ delete _timerManager;
+ }
+}
+
+void EventRecorder::deinit() {
+ if (!_initialized) {
+ return;
+ }
+ setFileHeader();
+ _needRedraw = false;
+ _initialized = false;
+ _recordMode = kPassthrough;
+ delete _fakeMixerManager;
+ _fakeMixerManager = NULL;
+ _controlPanel->close();
+ delete _controlPanel;
+ debugC(1, kDebugLevelEventRec, "playback:action=stopplayback");
+ g_system->getEventManager()->getEventDispatcher()->unregisterSource(this);
+ _recordMode = kPassthrough;
+ _playbackFile->close();
+ delete _playbackFile;
+ switchMixer();
+ switchTimerManagers();
+ DebugMan.disableDebugChannel("EventRec");
+}
+
+void EventRecorder::processMillis(uint32 &millis, bool skipRecord) {
+ if (!_initialized) {
+ return;
+ }
+ if (skipRecord) {
+ millis = _fakeTimer;
+ return;
+ }
+ if (_recordMode == kRecorderPlaybackPause) {
+ millis = _fakeTimer;
+ }
+ uint32 millisDelay;
+ Common::RecorderEvent timerEvent;
+ switch (_recordMode) {
+ case kRecorderRecord:
+ updateSubsystems();
+ millisDelay = millis - _lastMillis;
+ _lastMillis = millis;
+ _fakeTimer += millisDelay;
+ _controlPanel->setReplayedTime(_fakeTimer);
+ timerEvent.recordedtype = Common::kRecorderEventTypeTimer;
+ timerEvent.time = _fakeTimer;
+ _playbackFile->writeEvent(timerEvent);
+ takeScreenshot();
+ _timerManager->handler();
+ break;
+ case kRecorderPlayback:
+ updateSubsystems();
+ if (_nextEvent.recordedtype == Common::kRecorderEventTypeTimer) {
+ _fakeTimer = _nextEvent.time;
+ _nextEvent = _playbackFile->getNextEvent();
+ _timerManager->handler();
+ } else {
+ if (_nextEvent.type == Common::EVENT_RTL) {
+ error("playback:action=stopplayback");
+ } else {
+ uint32 seconds = _fakeTimer / 1000;
+ Common::String screenTime = Common::String::format("%.2d:%.2d:%.2d", seconds / 3600 % 24, seconds / 60 % 60, seconds % 60);
+ error("playback:action=error reason=\"synchronization error\" time = %s", screenTime.c_str());
+ }
+ }
+ millis = _fakeTimer;
+ _controlPanel->setReplayedTime(_fakeTimer);
+ break;
+ case kRecorderPlaybackPause:
+ millis = _fakeTimer;
+ break;
+ default:
+ break;
+ }
+}
+
+bool EventRecorder::processDelayMillis() {
+ return _fastPlayback;
+}
+
+void EventRecorder::checkForKeyCode(const Common::Event &event) {
+ if ((event.type == Common::EVENT_KEYDOWN) && (event.kbd.flags & Common::KBD_CTRL) && (event.kbd.keycode == Common::KEYCODE_p) && (!event.synthetic)) {
+ togglePause();
+ }
+}
+
+bool EventRecorder::pollEvent(Common::Event &ev) {
+ if ((_recordMode != kRecorderPlayback) || !_initialized)
+ return false;
+
+ if ((_nextEvent.recordedtype == Common::kRecorderEventTypeTimer) || (_nextEvent.type == Common::EVENT_INVALID)) {
+ return false;
+ }
+
+ switch (_nextEvent.type) {
+ case Common::EVENT_MOUSEMOVE:
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONDOWN:
+ case Common::EVENT_RBUTTONUP:
+ case Common::EVENT_WHEELUP:
+ case Common::EVENT_WHEELDOWN:
+ g_system->warpMouse(_nextEvent.mouse.x, _nextEvent.mouse.y);
+ break;
+ default:
+ break;
+ }
+ ev = _nextEvent;
+ _nextEvent = _playbackFile->getNextEvent();
+ return true;
+}
+
+void EventRecorder::switchFastMode() {
+ if (_recordMode == kRecorderPlaybackPause) {
+ _fastPlayback = !_fastPlayback;
+ }
+}
+
+void EventRecorder::togglePause() {
+ RecordMode oldState;
+ switch (_recordMode) {
+ case kRecorderPlayback:
+ case kRecorderRecord:
+ oldState = _recordMode;
+ _recordMode = kRecorderPlaybackPause;
+ _controlPanel->runModal();
+ _recordMode = oldState;
+ _initialized = true;
+ break;
+ case kRecorderPlaybackPause:
+ _controlPanel->close();
+ break;
+ default:
+ break;
+ }
+}
+
+void EventRecorder::RegisterEventSource() {
+ g_system->getEventManager()->getEventDispatcher()->registerMapper(this, false);
+}
+
+uint32 EventRecorder::getRandomSeed(const Common::String &name) {
+ uint32 result = g_system->getMillis();
+ if (_recordMode == kRecorderRecord) {
+ _playbackFile->getHeader().randomSourceRecords[name] = result;
+ } else if (_recordMode == kRecorderPlayback) {
+ result = _playbackFile->getHeader().randomSourceRecords[name];
+ }
+ return result;
+}
+
+Common::String EventRecorder::generateRecordFileName(const Common::String &target) {
+ Common::String pattern(target+".r??");
+ Common::StringArray files = g_system->getSavefileManager()->listSavefiles(pattern);
+ for (int i = 0; i < kMaxRecordsNames; ++i) {
+ Common::String recordName = Common::String::format("%s.r%02d", target.c_str(), i);
+ if (find(files.begin(), files.end(), recordName) != files.end()) {
+ continue;
+ }
+ return recordName;
+ }
+ return "";
+}
+
+
+void EventRecorder::init(Common::String recordFileName, RecordMode mode) {
+ _fakeMixerManager = new NullSdlMixerManager();
+ _fakeMixerManager->init();
+ _fakeMixerManager->suspendAudio();
+ _fakeTimer = 0;
+ _lastMillis = g_system->getMillis();
+ _playbackFile = new Common::PlaybackFile();
+ _lastScreenshotTime = 0;
+ _recordMode = mode;
+ _needcontinueGame = false;
+ if (ConfMan.hasKey("disable_display")) {
+ DebugMan.enableDebugChannel("EventRec");
+ gDebugLevel = 1;
+ }
+ if (_recordMode == kRecorderPlayback) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Load file\" filename=%s", recordFileName.c_str());
+ }
+ g_system->getEventManager()->getEventDispatcher()->registerSource(this, false);
+ _screenshotPeriod = ConfMan.getInt("screenshot_period");
+ if (_screenshotPeriod == 0) {
+ _screenshotPeriod = kDefaultScreenshotPeriod;
+ }
+ if (!openRecordFile(recordFileName)) {
+ deinit();
+ error("playback:action=error reason=\"Record file loading error\"");
+ return;
+ }
+ if (_recordMode != kPassthrough) {
+ _controlPanel = new GUI::OnScreenDialog(_recordMode == kRecorderRecord);
+ }
+ if (_recordMode == kRecorderPlayback) {
+ applyPlaybackSettings();
+ _nextEvent = _playbackFile->getNextEvent();
+ }
+ if (_recordMode == kRecorderRecord) {
+ getConfig();
+ }
+
+ switchMixer();
+ switchTimerManagers();
+ _needRedraw = true;
+ _initialized = true;
+}
+
+
+/**
+ * Opens or creates file depend of recording mode.
+ *
+ *@param id of recording or playing back game
+ *@return true in case of success, false in case of error
+ *
+ */
+bool EventRecorder::openRecordFile(const Common::String &fileName) {
+ bool result;
+ switch (_recordMode) {
+ case kRecorderRecord:
+ return _playbackFile->openWrite(fileName);
+ case kRecorderPlayback:
+ _recordMode = kPassthrough;
+ result = _playbackFile->openRead(fileName);
+ _recordMode = kRecorderPlayback;
+ return result;
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool EventRecorder::checkGameHash(const ADGameDescription *gameDesc) {
+ if (_playbackFile->getHeader().hashRecords.size() != 0) {
+ warning("Engine doesn't contain description table");
+ return false;
+ }
+ for (const ADGameFileDescription *fileDesc = gameDesc->filesDescriptions; fileDesc->fileName; fileDesc++) {
+ if (_playbackFile->getHeader().hashRecords.find(fileDesc->fileName) == _playbackFile->getHeader().hashRecords.end()) {
+ warning("MD5 hash for file %s not found in record file", fileDesc->fileName);
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check game hash\" filename=%s filehash=%s storedhash=\"\" result=different", fileDesc->fileName, fileDesc->md5);
+ return false;
+ }
+ if (_playbackFile->getHeader().hashRecords[fileDesc->fileName] != fileDesc->md5) {
+ warning("Incorrect version of game file %s. Stored MD5 is %s. MD5 of loaded game is %s", fileDesc->fileName, _playbackFile->getHeader().hashRecords[fileDesc->fileName].c_str(), fileDesc->md5);
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check game hash\" filename=%s filehash=%s storedhash=%s result=different", fileDesc->fileName, fileDesc->md5, _playbackFile->getHeader().hashRecords[fileDesc->fileName].c_str());
+ return false;
+ }
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Check game hash\" filename=%s filehash=%s storedhash=%s result=equal", fileDesc->fileName, fileDesc->md5, _playbackFile->getHeader().hashRecords[fileDesc->fileName].c_str());
+ }
+ return true;
+}
+
+void EventRecorder::registerMixerManager(SdlMixerManager *mixerManager) {
+ _realMixerManager = mixerManager;
+}
+
+void EventRecorder::switchMixer() {
+ if (_recordMode == kPassthrough) {
+ _realMixerManager->resumeAudio();
+ } else {
+ _realMixerManager->suspendAudio();
+ _fakeMixerManager->resumeAudio();
+ }
+}
+
+SdlMixerManager *EventRecorder::getMixerManager() {
+ if (_recordMode == kPassthrough) {
+ return _realMixerManager;
+ } else {
+ return _fakeMixerManager;
+ }
+}
+
+void EventRecorder::getConfigFromDomain(Common::ConfigManager::Domain *domain) {
+ for (Common::ConfigManager::Domain::iterator entry = domain->begin(); entry!= domain->end(); ++entry) {
+ _playbackFile->getHeader().settingsRecords[entry->_key] = entry->_value;
+ }
+}
+
+void EventRecorder::getConfig() {
+ getConfigFromDomain(ConfMan.getDomain(ConfMan.kApplicationDomain));
+ getConfigFromDomain(ConfMan.getActiveDomain());
+ _playbackFile->getHeader().settingsRecords["save_slot"] = ConfMan.get("save_slot");
+}
+
+
+void EventRecorder::applyPlaybackSettings() {
+ for (Common::StringMap::iterator i = _playbackFile->getHeader().settingsRecords.begin(); i != _playbackFile->getHeader().settingsRecords.end(); ++i) {
+ Common::String currentValue = ConfMan.get(i->_key);
+ if (currentValue != i->_value) {
+ ConfMan.set(i->_key, i->_value, ConfMan.kTransientDomain);
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Apply settings\" key=%s storedvalue=%s currentvalue=%s result=different", i->_key.c_str(), i->_value.c_str(), currentValue.c_str());
+ } else {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Apply settings\" key=%s storedvalue=%s currentvalue=%s result=equal", i->_key.c_str(), i->_value.c_str(), currentValue.c_str());
+ }
+ }
+ removeDifferentEntriesInDomain(ConfMan.getDomain(ConfMan.kApplicationDomain));
+ removeDifferentEntriesInDomain(ConfMan.getActiveDomain());
+}
+
+void EventRecorder::removeDifferentEntriesInDomain(Common::ConfigManager::Domain *domain) {
+ for (Common::ConfigManager::Domain::iterator entry = domain->begin(); entry!= domain->end(); ++entry) {
+ if (_playbackFile->getHeader().settingsRecords.find(entry->_key) == _playbackFile->getHeader().settingsRecords.end()) {
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Apply settings\" checksettings:key=%s storedvalue=%s currentvalue="" result=different", entry->_key.c_str(), entry->_value.c_str());
+ domain->erase(entry->_key);
+ }
+ }
+}
+
+DefaultTimerManager *EventRecorder::getTimerManager() {
+ return _timerManager;
+}
+
+void EventRecorder::registerTimerManager(DefaultTimerManager *timerManager) {
+ _timerManager = timerManager;
+}
+
+void EventRecorder::switchTimerManagers() {
+ delete _timerManager;
+ if (_recordMode == kPassthrough) {
+ _timerManager = new SdlTimerManager();
+ } else {
+ _timerManager = new DefaultTimerManager();
+ }
+}
+
+void EventRecorder::updateSubsystems() {
+ if (_recordMode == kPassthrough) {
+ return;
+ }
+ RecordMode oldRecordMode = _recordMode;
+ _recordMode = kPassthrough;
+ _fakeMixerManager->update();
+ _recordMode = oldRecordMode;
+}
+
+Common::List<Common::Event> EventRecorder::mapEvent(const Common::Event &ev, Common::EventSource *source) {
+ if ((!_initialized) && (_recordMode != kRecorderPlaybackPause)) {
+ return DefaultEventMapper::mapEvent(ev, source);
+ }
+
+ checkForKeyCode(ev);
+ Common::Event evt = ev;
+ evt.mouse.x = evt.mouse.x * (g_system->getOverlayWidth() / g_system->getWidth());
+ evt.mouse.y = evt.mouse.y * (g_system->getOverlayHeight() / g_system->getHeight());
+ switch (_recordMode) {
+ case kRecorderPlayback:
+ if (ev.synthetic != true) {
+ return Common::List<Common::Event>();
+ }
+ return Common::DefaultEventMapper::mapEvent(ev, source);
+ break;
+ case kRecorderRecord:
+ g_gui.processEvent(evt, _controlPanel);
+ if (((evt.type == Common::EVENT_LBUTTONDOWN) || (evt.type == Common::EVENT_LBUTTONUP) || (evt.type == Common::EVENT_MOUSEMOVE)) && _controlPanel->isMouseOver()) {
+ return Common::List<Common::Event>();
+ } else {
+ Common::RecorderEvent e;
+ memcpy(&e, &ev, sizeof(ev));
+ e.recordedtype = Common::kRecorderEventTypeNormal;
+ e.time = _fakeTimer;
+ _playbackFile->writeEvent(e);
+ return DefaultEventMapper::mapEvent(ev, source);
+ }
+ break;
+ case kRecorderPlaybackPause: {
+ Common::Event dialogEvent;
+ if (_controlPanel->isEditDlgVisible()) {
+ dialogEvent = ev;
+ } else {
+ dialogEvent = evt;
+ }
+ g_gui.processEvent(dialogEvent, _controlPanel->getActiveDlg());
+ if (((dialogEvent.type == Common::EVENT_LBUTTONDOWN) || (dialogEvent.type == Common::EVENT_LBUTTONUP) || (dialogEvent.type == Common::EVENT_MOUSEMOVE)) && _controlPanel->isMouseOver()) {
+ return Common::List<Common::Event>();
+ }
+ return Common::DefaultEventMapper::mapEvent(dialogEvent, source);
+ }
+ break;
+ default:
+ return Common::DefaultEventMapper::mapEvent(ev, source);
+ }
+}
+
+void EventRecorder::setGameMd5(const ADGameDescription *gameDesc) {
+ for (const ADGameFileDescription *fileDesc = gameDesc->filesDescriptions; fileDesc->fileName; fileDesc++) {
+ if (fileDesc->md5 != NULL) {
+ _playbackFile->getHeader().hashRecords[fileDesc->fileName] = fileDesc->md5;
+ }
+ }
+}
+
+void EventRecorder::processGameDescription(const ADGameDescription *desc) {
+ if (_recordMode == kRecorderRecord) {
+ setGameMd5(desc);
+ }
+ if ((_recordMode == kRecorderPlayback) && !checkGameHash(desc)) {
+ deinit();
+ error("playback:action=error reason=\"\"");
+ }
+}
+
+void EventRecorder::deleteRecord(const Common::String& fileName) {
+ g_system->getSavefileManager()->removeSavefile(fileName);
+}
+
+void EventRecorder::takeScreenshot() {
+ if ((_fakeTimer - _lastScreenshotTime) > _screenshotPeriod) {
+ Graphics::Surface screen;
+ uint8 md5[16];
+ if (grabScreenAndComputeMD5(screen, md5)) {
+ _lastScreenshotTime = _fakeTimer;
+ _playbackFile->saveScreenShot(screen, md5);
+ screen.free();
+ }
+ }
+}
+
+bool EventRecorder::grabScreenAndComputeMD5(Graphics::Surface &screen, uint8 md5[16]) {
+ if (!createScreenShot(screen)) {
+ warning("Can't save screenshot");
+ return false;
+ }
+ Common::MemoryReadStream bitmapStream((const byte*)screen.pixels, screen.w * screen.h * screen.format.bytesPerPixel);
+ computeStreamMD5(bitmapStream, md5);
+ return true;
+}
+
+Common::SeekableReadStream *EventRecorder::processSaveStream(const Common::String &fileName) {
+ Common::InSaveFile *saveFile;
+ switch (_recordMode) {
+ case kRecorderPlayback:
+ debugC(1, kDebugLevelEventRec, "playback:action=\"Process save file\" filename=%s len=%d", fileName.c_str(), _playbackFile->getHeader().saveFiles[fileName].size);
+ return new Common::MemoryReadStream(_playbackFile->getHeader().saveFiles[fileName].buffer, _playbackFile->getHeader().saveFiles[fileName].size);
+ case kRecorderRecord:
+ saveFile = _realSaveManager->openForLoading(fileName);
+ if (saveFile != NULL) {
+ _playbackFile->addSaveFile(fileName, saveFile);
+ saveFile->seek(0);
+ }
+ return saveFile;
+ default:
+ return NULL;
+ break;
+ }
+}
+
+Common::SaveFileManager *EventRecorder::getSaveManager(Common::SaveFileManager *realSaveManager) {
+ _realSaveManager = realSaveManager;
+ if (_recordMode != kPassthrough) {
+ return &_fakeSaveManager;
+ } else {
+ return realSaveManager;
+ }
+}
+
+void EventRecorder::preDrawOverlayGui() {
+ if ((_initialized) || (_needRedraw)) {
+ RecordMode oldMode = _recordMode;
+ _recordMode = kPassthrough;
+ g_system->showOverlay();
+ g_gui.theme()->clearAll();
+ g_gui.theme()->openDialog(true, GUI::ThemeEngine::kShadingNone);
+ _controlPanel->drawDialog();
+ g_gui.theme()->finishBuffering();
+ g_gui.theme()->updateScreen();
+ _recordMode = oldMode;
+ }
+}
+
+void EventRecorder::postDrawOverlayGui() {
+ if ((_initialized) || (_needRedraw)) {
+ RecordMode oldMode = _recordMode;
+ _recordMode = kPassthrough;
+ g_system->hideOverlay();
+ _recordMode = oldMode;
+ }
+}
+
+Common::StringArray EventRecorder::listSaveFiles(const Common::String &pattern) {
+ if (_recordMode == kRecorderPlayback) {
+ Common::StringArray result;
+ for (Common::HashMap<Common::String, Common::PlaybackFile::SaveFileBuffer>::iterator i = _playbackFile->getHeader().saveFiles.begin(); i != _playbackFile->getHeader().saveFiles.end(); ++i) {
+ if (i->_key.matchString(pattern, false, true)) {
+ result.push_back(i->_key);
+ }
+ }
+ return result;
+ } else {
+ return _realSaveManager->listSavefiles(pattern);
+ }
+}
+
+void EventRecorder::setFileHeader() {
+ if (_recordMode != kRecorderRecord) {
+ return;
+ }
+ TimeDate t;
+ const EnginePlugin *plugin = 0;
+ GameDescriptor desc = EngineMan.findGame(ConfMan.getActiveDomainName(), &plugin);
+ 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());
+ }
+ _playbackFile->getHeader().author = _author;
+ _playbackFile->getHeader().notes = _desc;
+ _playbackFile->getHeader().name = _name;
+}
+
+SDL_Surface *EventRecorder::getSurface(int width, int height) {
+ // Create a RGB565 surface of the requested dimensions.
+ return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16, 0xF800, 0x07E0, 0x001F, 0x0000);
+}
+
+bool EventRecorder::switchMode() {
+ const Common::String gameId = ConfMan.get("gameid");
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+ bool metaInfoSupport = (*plugin)->hasFeature(MetaEngine::kSavesSupportMetaInfo);
+ bool featuresSupport = metaInfoSupport &&
+ g_engine->canSaveGameStateCurrently() &&
+ (*plugin)->hasFeature(MetaEngine::kSupportsListSaves) &&
+ (*plugin)->hasFeature(MetaEngine::kSupportsDeleteSave);
+ if (!featuresSupport) {
+ return false;
+ }
+
+ int emptySlot = 1;
+ SaveStateList saveList = (*plugin)->listSaves(gameId.c_str());
+ for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) {
+ int saveSlot = x->getSaveSlot();
+ if (saveSlot == 0) {
+ continue;
+ }
+ if (emptySlot != saveSlot) {
+ break;
+ }
+ emptySlot++;
+ }
+ Common::String saveName;
+ if (emptySlot >= 0) {
+ saveName = Common::String::format("Save %d", emptySlot + 1);
+ Common::Error status = g_engine->saveGameState(emptySlot, saveName);
+ if (status.getCode() == Common::kNoError) {
+ Common::Event eventRTL;
+ eventRTL.type = Common::EVENT_RTL;
+ g_system->getEventManager()->pushEvent(eventRTL);
+ }
+ }
+ ConfMan.set("record_mode", "", Common::ConfigManager::kTransientDomain);
+ ConfMan.setInt("save_slot", emptySlot, Common::ConfigManager::kTransientDomain);
+ _needcontinueGame = true;
+ return true;
+}
+
+bool EventRecorder::checkForContinueGame() {
+ bool result = _needcontinueGame;
+ _needcontinueGame = false;
+ return result;
+}
+
+void EventRecorder::deleteTemporarySave() {
+ if (_temporarySlot == -1) return;
+ const Common::String gameId = ConfMan.get("gameid");
+ const EnginePlugin *plugin = 0;
+ EngineMan.findGame(gameId, &plugin);
+ (*plugin)->removeSaveState(gameId.c_str(), _temporarySlot);
+ _temporarySlot = -1;
+}
+
+} // End of namespace GUI
+
+#endif // ENABLE_EVENTRECORDER
+
diff --git a/gui/EventRecorder.h b/gui/EventRecorder.h
new file mode 100644
index 0000000000..68ffe16fbc
--- /dev/null
+++ b/gui/EventRecorder.h
@@ -0,0 +1,238 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GUI_EVENTRECORDER_H
+#define GUI_EVENTRECORDER_H
+
+#include "common/system.h"
+
+#include "common/events.h"
+#include "common/savefile.h"
+#include "common/singleton.h"
+
+#include "engines/advancedDetector.h"
+
+#ifdef ENABLE_EVENTRECORDER
+
+#include "common/mutex.h"
+#include "common/array.h"
+#include "common/memstream.h"
+#include "backends/keymapper/keymapper.h"
+#include "backends/mixer/sdl/sdl-mixer.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+#include "backends/timer/sdl/sdl-timer.h"
+#include "common/config-manager.h"
+#include "common/recorderfile.h"
+#include "backends/saves/recorder/recorder-saves.h"
+#include "backends/mixer/nullmixer/nullsdl-mixer.h"
+#include "backends/saves/default/default-saves.h"
+
+
+#define g_eventRec (GUI::EventRecorder::instance())
+
+namespace GUI {
+ class OnScreenDialog;
+}
+
+namespace GUI {
+class RandomSource;
+class SeekableReadStream;
+class WriteStream;
+
+
+/**
+ * Our generic event recorder.
+ *
+ * TODO: Add more documentation.
+ */
+class EventRecorder : private Common::EventSource, public Common::Singleton<EventRecorder>, private Common::DefaultEventMapper {
+ friend class Common::Singleton<SingletonBaseType>;
+ EventRecorder();
+ ~EventRecorder();
+public:
+ /** Specify operation mode of Event Recorder */
+ enum RecordMode {
+ kPassthrough = 0, /**< kPassthrough, do nothing */
+ kRecorderRecord = 1, /**< kRecorderRecord, do the recording */
+ kRecorderPlayback = 2, /**< kRecorderPlayback, playback existing recording */
+ kRecorderPlaybackPause = 3 /**< kRecordetPlaybackPause, interal state when user pauses the playback */
+ };
+
+ void init(Common::String recordFileName, RecordMode mode);
+ void deinit();
+ bool processDelayMillis();
+ uint32 getRandomSeed(const Common::String &name);
+ void processMillis(uint32 &millis, bool skipRecord);
+ bool processAudio(uint32 &samples, bool paused);
+ void processGameDescription(const ADGameDescription *desc);
+ Common::SeekableReadStream *processSaveStream(const Common::String & fileName);
+
+ /** Hooks for intercepting into GUI processing, so required events could be shoot
+ * or filtered out */
+ void preDrawOverlayGui();
+ void postDrawOverlayGui();
+
+ /** Set recording author
+ *
+ * @see getAuthor
+ */
+ void setAuthor(const Common::String &author) {
+ _author = author;
+ }
+
+ /** Set recording notes
+ *
+ * @see getNotes
+ */
+ void setNotes(const Common::String &desc){
+ _desc = desc;
+ }
+
+ /** Set descriptive name of the recording
+ *
+ * @see getName
+ */
+ void setName(const Common::String &name) {
+ _name = name;
+ }
+
+ /** Get recording author
+ *
+ * @see getAuthor
+ */
+ const Common::String getAuthor() {
+ return _author;
+ }
+
+ /** Get recording notes
+ *
+ * @see setNotes
+ */
+ const Common::String getNotes() {
+ return _desc;
+ }
+
+ /** Get recording name
+ *
+ * @see setName
+ */
+ const Common::String getName() {
+ return _name;
+ }
+ void setRedraw(bool redraw) {
+ _needRedraw = redraw;
+ }
+
+ void registerMixerManager(SdlMixerManager *mixerManager);
+ void registerTimerManager(DefaultTimerManager *timerManager);
+
+ SdlMixerManager *getMixerManager();
+ DefaultTimerManager *getTimerManager();
+
+ void deleteRecord(const Common::String& fileName);
+ bool checkForContinueGame();
+
+ void suspendRecording() {
+ _savedState = _initialized;
+ _initialized = false;
+ }
+
+ void resumeRecording() {
+ _initialized = _savedState;
+ }
+
+ Common::StringArray listSaveFiles(const Common::String &pattern);
+ Common::String generateRecordFileName(const Common::String &target);
+
+ Common::SaveFileManager *getSaveManager(Common::SaveFileManager *realSaveManager);
+ SDL_Surface *getSurface(int width, int height);
+ void RegisterEventSource();
+
+ /** Retrieve game screenshot and compute its checksum for comparison */
+ bool grabScreenAndComputeMD5(Graphics::Surface &screen, uint8 md5[16]);
+
+ void updateSubsystems();
+ bool switchMode();
+ void switchFastMode();
+
+private:
+ virtual Common::List<Common::Event> mapEvent(const Common::Event &ev, Common::EventSource *source);
+ bool notifyPoll();
+ bool pollEvent(Common::Event &ev);
+ bool _initialized;
+ volatile uint32 _fakeTimer;
+ bool _savedState;
+ bool _needcontinueGame;
+ int _temporarySlot;
+ Common::String _author;
+ Common::String _desc;
+ Common::String _name;
+
+ Common::SaveFileManager *_realSaveManager;
+ SdlMixerManager *_realMixerManager;
+ DefaultTimerManager *_timerManager;
+ RecorderSaveFileManager _fakeSaveManager;
+ NullSdlMixerManager *_fakeMixerManager;
+ GUI::OnScreenDialog *_controlPanel;
+ Common::RecorderEvent _nextEvent;
+
+ void setFileHeader();
+ void setGameMd5(const ADGameDescription *gameDesc);
+ void getConfig();
+ void getConfigFromDomain(Common::ConfigManager::Domain *domain);
+ void removeDifferentEntriesInDomain(Common::ConfigManager::Domain *domain);
+ void applyPlaybackSettings();
+
+ void switchMixer();
+ void switchTimerManagers();
+
+ void togglePause();
+
+ void takeScreenshot();
+
+ bool openRecordFile(const Common::String &fileName);
+
+ bool checkGameHash(const ADGameDescription *desc);
+
+ void checkForKeyCode(const Common::Event &event);
+ bool allowMapping() const { return false; }
+
+ volatile uint32 _lastMillis;
+ uint32 _lastScreenshotTime;
+ uint32 _screenshotPeriod;
+ Common::PlaybackFile *_playbackFile;
+
+ void saveScreenShot();
+ void checkRecordedMD5();
+ void deleteTemporarySave();
+ volatile RecordMode _recordMode;
+ Common::String _recordFileName;
+ bool _fastPlayback;
+ bool _needRedraw;
+};
+
+} // End of namespace GUI
+
+#endif // ENABLE_EVENTRECORDER
+
+#endif
diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp
index e2fa2580f5..3ce043cb39 100644
--- a/gui/ThemeEngine.cpp
+++ b/gui/ThemeEngine.cpp
@@ -50,6 +50,14 @@ const char * const ThemeEngine::kImageEraser = "eraser.bmp";
const char * const ThemeEngine::kImageDelbtn = "delbtn.bmp";
const char * const ThemeEngine::kImageList = "list.bmp";
const char * const ThemeEngine::kImageGrid = "grid.bmp";
+const char * const ThemeEngine::kImageStopbtn = "stopbtn.bmp";
+const char * const ThemeEngine::kImageEditbtn = "editbtn.bmp";
+const char * const ThemeEngine::kImageSwitchModebtn = "switchbtn.bmp";
+const char * const ThemeEngine::kImageFastReplaybtn = "fastreplay.bmp";
+const char * const ThemeEngine::kImageStopSmallbtn = "stopbtn_small.bmp";
+const char * const ThemeEngine::kImageEditSmallbtn = "editbtn_small.bmp";
+const char * const ThemeEngine::kImageSwitchModeSmallbtn = "switchbtn_small.bmp";
+const char * const ThemeEngine::kImageFastReplaySmallbtn = "fastreplay_small.bmp";
struct TextDrawData {
const Graphics::Font *_fontPtr;
@@ -465,11 +473,7 @@ void ThemeEngine::enable() {
if (_enabled)
return;
- if (_useCursor) {
- CursorMan.pushCursorPalette(_cursorPal, 0, _cursorPalSize);
- CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, true);
- CursorMan.showMouse(true);
- }
+ showCursor();
_system->showOverlay();
clearAll();
@@ -482,10 +486,8 @@ void ThemeEngine::disable() {
_system->hideOverlay();
- if (_useCursor) {
- CursorMan.popCursorPalette();
- CursorMan.popCursor();
- }
+ hideCursor();
+
_enabled = false;
}
@@ -1787,5 +1789,20 @@ Common::String ThemeEngine::getThemeId(const Common::String &filename) {
}
}
+void ThemeEngine::showCursor() {
+ if (_useCursor) {
+ CursorMan.pushCursorPalette(_cursorPal, 0, _cursorPalSize);
+ CursorMan.pushCursor(_cursor, _cursorWidth, _cursorHeight, _cursorHotspotX, _cursorHotspotY, 255, true);
+ CursorMan.showMouse(true);
+ }
+}
+
+void ThemeEngine::hideCursor() {
+ if (_useCursor) {
+ CursorMan.popCursorPalette();
+ CursorMan.popCursor();
+ }
+}
+
} // End of namespace GUI.
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 6e5fd291b7..160ceb3259 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -234,6 +234,14 @@ public:
static const char *const kImageDelbtn; ///< Delete characters in the predictive dialog
static const char *const kImageList; ///< List image used in save/load chooser selection
static const char *const kImageGrid; ///< Grid image used in save/load chooser selection
+ static const char *const kImageStopbtn; ///< Stop recording button in recorder onscreen dialog
+ static const char *const kImageEditbtn; ///< Edit recording metadata in recorder onscreen dialog
+ static const char *const kImageSwitchModebtn; ///< Switch mode button in recorder onscreen dialog
+ static const char *const kImageFastReplaybtn; ///< Fast playback mode button in recorder onscreen dialog
+ static const char *const kImageStopSmallbtn; ///< Stop recording button in recorder onscreen dialog (for 320xY)
+ static const char *const kImageEditSmallbtn; ///< Edit recording metadata in recorder onscreen dialog (for 320xY)
+ static const char *const kImageSwitchModeSmallbtn; ///< Switch mode button in recorder onscreen dialog (for 320xY)
+ static const char *const kImageFastReplaySmallbtn; ///< Fast playback mode button in recorder onscreen dialog (for 320xY)
/**
* Graphics mode enumeration.
@@ -275,8 +283,13 @@ public:
void refresh();
void enable();
+
+ void showCursor();
+ void hideCursor();
+
void disable();
+
/**
* Query the set up pixel format.
*/
diff --git a/gui/about.cpp b/gui/about.cpp
index 088971f273..20145886c6 100644
--- a/gui/about.cpp
+++ b/gui/about.cpp
@@ -46,7 +46,7 @@ enum {
// 0 - 2 -- set a custom color:
// 0 normal text
// 1 highlighted text
-// 2 disabled text
+// 2 disabled text
// TODO: Maybe add a tab/indent feature; that is, make it possible to specify
// an amount by which that line shall be indented (the indent of course would have
// to be considered while performing any word wrapping, too).
@@ -139,7 +139,7 @@ void AboutDialog::addLine(const char *str) {
} else {
Common::String format(str, 2);
str += 2;
-
+
static Common::String asciiStr;
if (format[0] == 'A') {
bool useAscii = false;
diff --git a/gui/chooser.cpp b/gui/chooser.cpp
index 6ae08161df..c195e94c9b 100644
--- a/gui/chooser.cpp
+++ b/gui/chooser.cpp
@@ -67,6 +67,7 @@ void ChooserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
break;
case kCloseCmd:
setResult(-1);
+ // Fall through
default:
Dialog::handleCommand(sender, cmd, data);
}
diff --git a/gui/credits.h b/gui/credits.h
index 81d46b2b73..70f79ac9a5 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -294,9 +294,6 @@ static const char *credits[] = {
"C0""Andre Heider",
"C0""Angus Lees",
"",
-"C1""BADA",
-"C0""Chris Warren-Smith",
-"",
"C1""Dreamcast",
"C0""Marcus Comstedt",
"",
@@ -352,6 +349,9 @@ static const char *credits[] = {
"C0""Jurgen Braam",
"C0""Lars Persson",
"",
+"C1""Tizen / BADA",
+"C0""Chris Warren-Smith",
+"",
"C1""WebOS",
"C0""Klaus Reimer",
"",
diff --git a/gui/dialog.h b/gui/dialog.h
index 1773c6633e..d269a2f645 100644
--- a/gui/dialog.h
+++ b/gui/dialog.h
@@ -37,6 +37,8 @@ struct Event;
namespace GUI {
+class EventRecorder;
+
class Widget;
// Some "common" commands sent to handleCommand()
@@ -47,6 +49,7 @@ enum {
class Dialog : public GuiObject {
friend class GuiManager;
+ friend class EventRecorder;
friend class Tooltip;
protected:
Widget *_mouseWidget;
diff --git a/gui/editrecorddialog.cpp b/gui/editrecorddialog.cpp
new file mode 100644
index 0000000000..cfcc747121
--- /dev/null
+++ b/gui/editrecorddialog.cpp
@@ -0,0 +1,87 @@
+/* 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 "editrecorddialog.h"
+#include "gui/widgets/edittext.h"
+#include "common/translation.h"
+
+
+namespace GUI {
+
+const Common::String EditRecordDialog::getAuthor() {
+ return _authorEdit->getEditString();
+}
+
+void EditRecordDialog::setAuthor(const Common::String &author) {
+ _authorEdit->setEditString(author);
+}
+
+const Common::String EditRecordDialog::getNotes() {
+ return _notesEdit->getEditString();
+}
+
+void EditRecordDialog::setNotes(const Common::String &desc) {
+ _notesEdit->setEditString(desc);
+}
+
+const Common::String EditRecordDialog::getName() {
+ return _nameEdit->getEditString();
+}
+
+void EditRecordDialog::setName(const Common::String &name) {
+ _nameEdit->setEditString(name);
+}
+
+EditRecordDialog::~EditRecordDialog() {
+}
+
+EditRecordDialog::EditRecordDialog(const Common::String author, const Common::String name, const Common::String notes) : Dialog("EditRecordDialog") {
+ new StaticTextWidget(this,"EditRecordDialog.AuthorLabel",_("Author:"));
+ new StaticTextWidget(this,"EditRecordDialog.NameLabel",_("Name:"));
+ new StaticTextWidget(this,"EditRecordDialog.NotesLabel",_("Notes:"));
+ _authorEdit = new EditTextWidget(this, "EditRecordDialog.AuthorEdit","");
+ _notesEdit = new EditTextWidget(this, "EditRecordDialog.NotesEdit","");
+ _nameEdit = new EditTextWidget(this, "EditRecordDialog.NameEdit","");
+ _authorEdit->setEditString(author);
+ _notesEdit->setEditString(notes);
+ _nameEdit->setEditString(name);
+ new GUI::ButtonWidget(this, "EditRecordDialog.Cancel", _("Cancel"), 0, kCloseCmd);
+ new GUI::ButtonWidget(this, "EditRecordDialog.OK", _("Ok"), 0, kOKCmd);
+}
+
+void EditRecordDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
+ switch(cmd) {
+ case kCloseCmd:
+ setResult(kCloseCmd);
+ close();
+ break;
+ case kOKCmd:
+ setResult(kOKCmd);
+ close();
+ break;
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ break;
+ }
+}
+
+}
diff --git a/gui/editrecorddialog.h b/gui/editrecorddialog.h
new file mode 100644
index 0000000000..c8da4521ca
--- /dev/null
+++ b/gui/editrecorddialog.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GUI_EDITRECORDDIALOG_H
+#define GUI_EDITRECORDDIALOG_H
+
+#include "gui/dialog.h"
+
+namespace GUI {
+
+class EditTextWidget;
+class StaticTextWidget;
+
+class EditRecordDialog : public Dialog {
+private:
+ EditTextWidget *_notesEdit;
+ EditTextWidget *_nameEdit;
+ EditTextWidget *_authorEdit;
+ EditRecordDialog() : Dialog("EditRecordDialog") {};
+public:
+ EditRecordDialog(const Common::String author, const Common::String name, const Common::String notes);
+ ~EditRecordDialog();
+
+ const Common::String getAuthor();
+ const Common::String getNotes();
+ const Common::String getName();
+
+ void setAuthor(const Common::String &author);
+ void setNotes(const Common::String &desc);
+ void setName(const Common::String &name);
+
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+};
+
+}// End of namespace GUI
+
+#endif
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index a0ef4216aa..1505c8c707 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -27,6 +27,7 @@
#include "common/rect.h"
#include "common/textconsole.h"
#include "common/translation.h"
+#include "gui/EventRecorder.h"
#include "backends/keymapper/keymapper.h"
@@ -253,12 +254,15 @@ Dialog *GuiManager::getTopDialog() const {
void GuiManager::runLoop() {
Dialog * const activeDialog = getTopDialog();
bool didSaveState = false;
- int button;
- uint32 time;
if (activeDialog == 0)
return;
+#ifdef ENABLE_EVENTRECORDER
+ // Suspend recording while GUI is shown
+ g_eventRec.suspendRecording();
+#endif
+
if (!_stateIsSaved) {
saveState();
_theme->enable();
@@ -296,10 +300,10 @@ void GuiManager::runLoop() {
// _theme->updateScreen();
// _system->updateScreen();
- if (lastRedraw + waitTime < _system->getMillis()) {
+ if (lastRedraw + waitTime < _system->getMillis(true)) {
_theme->updateScreen();
_system->updateScreen();
- lastRedraw = _system->getMillis();
+ lastRedraw = _system->getMillis(true);
}
Common::Event event;
@@ -314,72 +318,21 @@ void GuiManager::runLoop() {
if (activeDialog != getTopDialog() && event.type != Common::EVENT_SCREEN_CHANGED)
continue;
- Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
-
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- activeDialog->handleKeyDown(event.kbd);
- break;
- case Common::EVENT_KEYUP:
- activeDialog->handleKeyUp(event.kbd);
- break;
- case Common::EVENT_MOUSEMOVE:
- activeDialog->handleMouseMoved(mouse.x, mouse.y, 0);
-
- if (mouse.x != _lastMousePosition.x || mouse.y != _lastMousePosition.y) {
- _lastMousePosition.x = mouse.x;
- _lastMousePosition.y = mouse.y;
- _lastMousePosition.time = _system->getMillis();
- }
+ processEvent(event, activeDialog);
+ if (event.type == Common::EVENT_MOUSEMOVE) {
tooltipCheck = true;
- break;
- // We don't distinguish between mousebuttons (for now at least)
- case Common::EVENT_LBUTTONDOWN:
- case Common::EVENT_RBUTTONDOWN:
- button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2);
- time = _system->getMillis();
- if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay)
- && ABS(_lastClick.x - event.mouse.x) < 3
- && ABS(_lastClick.y - event.mouse.y) < 3) {
- _lastClick.count++;
- } else {
- _lastClick.x = event.mouse.x;
- _lastClick.y = event.mouse.y;
- _lastClick.count = 1;
- }
- _lastClick.time = time;
- activeDialog->handleMouseDown(mouse.x, mouse.y, button, _lastClick.count);
- break;
- case Common::EVENT_LBUTTONUP:
- case Common::EVENT_RBUTTONUP:
- button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2);
- activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count);
- break;
- case Common::EVENT_WHEELUP:
- activeDialog->handleMouseWheel(mouse.x, mouse.y, -1);
- break;
- case Common::EVENT_WHEELDOWN:
- activeDialog->handleMouseWheel(mouse.x, mouse.y, 1);
- break;
- case Common::EVENT_SCREEN_CHANGED:
- screenChange();
- break;
- default:
-#ifdef ENABLE_KEYMAPPER
- activeDialog->handleOtherEvent(event);
-#endif
- break;
}
- if (lastRedraw + waitTime < _system->getMillis()) {
+
+ if (lastRedraw + waitTime < _system->getMillis(true)) {
_theme->updateScreen();
_system->updateScreen();
- lastRedraw = _system->getMillis();
+ lastRedraw = _system->getMillis(true);
}
}
- if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis()) {
+ if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis(true)) {
Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y);
if (wdg && wdg->hasTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) {
Tooltip *tooltip = new Tooltip();
@@ -409,6 +362,11 @@ void GuiManager::runLoop() {
restoreState();
_useStdCursor = false;
}
+
+#ifdef ENABLE_EVENTRECORDER
+ // Resume recording once GUI is shown
+ g_eventRec.resumeRecording();
+#endif
}
#pragma mark -
@@ -492,7 +450,7 @@ void GuiManager::setupCursor() {
// very much. We could plug in a different cursor here if we like to.
void GuiManager::animateCursor() {
- int time = _system->getMillis();
+ int time = _system->getMillis(true);
if (time > _cursorAnimateTimer + kCursorAnimateDelay) {
for (int i = 0; i < 15; i++) {
if ((i < 6) || (i > 8)) {
@@ -537,4 +495,64 @@ void GuiManager::screenChange() {
_system->updateScreen();
}
+void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDialog) {
+ int button;
+ uint32 time;
+ Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y);
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ activeDialog->handleKeyDown(event.kbd);
+ break;
+ case Common::EVENT_KEYUP:
+ activeDialog->handleKeyUp(event.kbd);
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ activeDialog->handleMouseMoved(mouse.x, mouse.y, 0);
+
+ if (mouse.x != _lastMousePosition.x || mouse.y != _lastMousePosition.y) {
+ _lastMousePosition.x = mouse.x;
+ _lastMousePosition.y = mouse.y;
+ _lastMousePosition.time = _system->getMillis(true);
+ }
+
+ break;
+ // We don't distinguish between mousebuttons (for now at least)
+ case Common::EVENT_LBUTTONDOWN:
+ case Common::EVENT_RBUTTONDOWN:
+ button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2);
+ time = _system->getMillis(true);
+ if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay)
+ && ABS(_lastClick.x - event.mouse.x) < 3
+ && ABS(_lastClick.y - event.mouse.y) < 3) {
+ _lastClick.count++;
+ } else {
+ _lastClick.x = event.mouse.x;
+ _lastClick.y = event.mouse.y;
+ _lastClick.count = 1;
+ }
+ _lastClick.time = time;
+ activeDialog->handleMouseDown(mouse.x, mouse.y, button, _lastClick.count);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2);
+ activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count);
+ break;
+ case Common::EVENT_WHEELUP:
+ activeDialog->handleMouseWheel(mouse.x, mouse.y, -1);
+ break;
+ case Common::EVENT_WHEELDOWN:
+ activeDialog->handleMouseWheel(mouse.x, mouse.y, 1);
+ break;
+ case Common::EVENT_SCREEN_CHANGED:
+ screenChange();
+ break;
+ default:
+ #ifdef ENABLE_KEYMAPPER
+ activeDialog->handleOtherEvent(event);
+ #endif
+ break;
+ }
+}
+
} // End of namespace GUI
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index 49542fd001..b52d91ba08 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -35,6 +35,10 @@ namespace Graphics {
class Font;
}
+namespace Common {
+ struct Event;
+}
+
namespace GUI {
class Dialog;
@@ -67,6 +71,8 @@ public:
// until no dialogs are active anymore.
void runLoop();
+ void processEvent(const Common::Event &event, Dialog *const activeDialog);
+
bool isActive() const { return ! _dialogStack.empty(); }
bool loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled, bool force = false);
diff --git a/gui/launcher.cpp b/gui/launcher.cpp
index 4e35b54db8..77d4cce794 100644
--- a/gui/launcher.cpp
+++ b/gui/launcher.cpp
@@ -37,6 +37,11 @@
#include "gui/message.h"
#include "gui/gui-manager.h"
#include "gui/options.h"
+#ifdef ENABLE_EVENTRECORDER
+#include "gui/onscreendialog.h"
+#include "gui/recorderdialog.h"
+#include "gui/EventRecorder.h"
+#endif
#include "gui/saveload.h"
#include "gui/widgets/edittext.h"
#include "gui/widgets/list.h"
@@ -596,7 +601,6 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
LauncherDialog::LauncherDialog()
: Dialog(0, 0, 320, 200) {
_backgroundType = GUI::ThemeEngine::kDialogBackgroundMain;
-
const int screenW = g_system->getOverlayWidth();
const int screenH = g_system->getOverlayHeight();
@@ -779,10 +783,9 @@ void LauncherDialog::updateListing() {
}
void LauncherDialog::addGame() {
- int modifiers = g_system->getEventManager()->getModifierState();
#ifndef DISABLE_MASS_ADD
- const bool massAdd = (modifiers & Common::KBD_SHIFT) != 0;
+ const bool massAdd = checkModifier(Common::KBD_SHIFT);
if (massAdd) {
MessageDialog alert(_("Do you really want to run the mass game detector? "
@@ -975,6 +978,49 @@ void LauncherDialog::editGame(int item) {
}
}
+void LauncherDialog::loadGameButtonPressed(int item) {
+#ifdef ENABLE_EVENTRECORDER
+ const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
+ if (shiftPressed) {
+ recordGame(item);
+ } else {
+ loadGame(item);
+ }
+ updateButtons();
+#else
+ loadGame(item);
+#endif
+}
+
+#ifdef ENABLE_EVENTRECORDER
+void LauncherDialog::recordGame(int item) {
+ RecorderDialog recorderDialog;
+ MessageDialog alert(_("Do you want to load savegame?"),
+ _("Yes"), _("No"));
+ switch(recorderDialog.runModal(_domains[item])) {
+ case RecorderDialog::kRecordDialogClose:
+ break;
+ case RecorderDialog::kRecordDialogPlayback:
+ ConfMan.setActiveDomain(_domains[item]);
+ close();
+ ConfMan.set("record_mode", "playback", ConfigManager::kTransientDomain);
+ ConfMan.set("record_file_name", recorderDialog.getFileName(), ConfigManager::kTransientDomain);
+ break;
+ case RecorderDialog::kRecordDialogRecord:
+ ConfMan.setActiveDomain(_domains[item]);
+ if (alert.runModal() == GUI::kMessageOK) {
+ loadGame(item);
+ }
+ close();
+ g_eventRec.setAuthor(recorderDialog._author);
+ g_eventRec.setName(recorderDialog._name);
+ g_eventRec.setNotes(recorderDialog._notes);
+ ConfMan.set("record_mode", "record", ConfigManager::kTransientDomain);
+ break;
+ }
+}
+#endif
+
void LauncherDialog::loadGame(int item) {
String gameId = ConfMan.get("gameid", _domains[item]);
if (gameId.empty())
@@ -1039,7 +1085,7 @@ void LauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
editGame(item);
break;
case kLoadGameCmd:
- loadGame(item);
+ loadGameButtonPressed(item);
break;
case kOptionsCmd: {
GlobalOptionsDialog options;
@@ -1109,20 +1155,28 @@ void LauncherDialog::updateButtons() {
_loadButton->setEnabled(en);
_loadButton->draw();
}
+ switchButtonsText(_addButton, "~A~dd Game...", "Mass Add...");
+#ifdef ENABLE_EVENTRECORDER
+ switchButtonsText(_loadButton, "~L~oad...", "Record...");
+#endif
+}
- // Update the label of the "Add" button depending on whether shift is pressed or not
- int modifiers = g_system->getEventManager()->getModifierState();
- const bool massAdd = (modifiers & Common::KBD_SHIFT) != 0;
+// Update the label of the button depending on whether shift is pressed or not
+void LauncherDialog::switchButtonsText(ButtonWidget *button, const char *normalText, const char *shiftedText) {
+ const bool shiftPressed = checkModifier(Common::KBD_SHIFT);
const bool lowRes = g_system->getOverlayWidth() <= 320;
- const char *newAddButtonLabel = massAdd
- ? (lowRes ? _c("Mass Add...", "lowres") : _("Mass Add..."))
- : (lowRes ? _c("~A~dd Game...", "lowres") : _("~A~dd Game..."));
+ const char *newAddButtonLabel = shiftPressed
+ ? (lowRes ? _c(shiftedText, "lowres") : _(shiftedText))
+ : (lowRes ? _c(normalText, "lowres") : _(normalText));
- if (_addButton->getLabel() != newAddButtonLabel)
- _addButton->setLabel(newAddButtonLabel);
+ if (button->getLabel() != newAddButtonLabel)
+ button->setLabel(newAddButtonLabel);
}
+
+
+
void LauncherDialog::reflowLayout() {
#ifndef DISABLE_FANCY_THEMES
if (g_gui.xmlEval()->getVar("Globals.ShowLauncherLogo") == 1 && g_gui.theme()->supportsImages()) {
@@ -1186,4 +1240,9 @@ void LauncherDialog::reflowLayout() {
Dialog::reflowLayout();
}
+bool LauncherDialog::checkModifier(int checkedModifier) {
+ int modifiers = g_system->getEventManager()->getModifierState();
+ return (modifiers & checkedModifier) != 0;
+}
+
} // End of namespace GUI
diff --git a/gui/launcher.h b/gui/launcher.h
index fc0484350a..2ab47be98d 100644
--- a/gui/launcher.h
+++ b/gui/launcher.h
@@ -56,7 +56,7 @@ protected:
ListWidget *_list;
ButtonWidget *_addButton;
Widget *_startButton;
- Widget *_loadButton;
+ ButtonWidget *_loadButton;
Widget *_editButton;
Widget *_removeButton;
#ifndef DISABLE_FANCY_THEMES
@@ -80,6 +80,7 @@ protected:
void updateListing();
void updateButtons();
+ void switchButtonsText(ButtonWidget *button, const char *normalText, const char *shiftedText);
void open();
void close();
@@ -100,6 +101,16 @@ protected:
void editGame(int item);
/**
+ * Facade for "Load..."/"Record..." buttons.
+ */
+ void loadGameButtonPressed(int item);
+
+ /**
+ * Handle "Record..." button.
+ */
+ void recordGame(int item);
+
+ /**
* Handle "Load..." button.
*/
void loadGame(int item);
@@ -111,6 +122,8 @@ protected:
* @target name of target to select
*/
void selectTarget(const String &target);
+private:
+ bool checkModifier(int modifier);
};
} // End of namespace GUI
diff --git a/gui/module.mk b/gui/module.mk
index bda3c88cd5..338e43c6a4 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -7,6 +7,7 @@ MODULE_OBJS := \
debugger.o \
dialog.o \
error.o \
+ EventRecorder.o \
gui-manager.o \
launcher.o \
massadd.o \
@@ -38,6 +39,13 @@ MODULE_OBJS += \
browser.o
endif
+ifdef ENABLE_EVENTRECORDER
+MODULE_OBJS += \
+ editrecorddialog.o \
+ onscreendialog.o \
+ recorderdialog.o
+endif
+
ifdef USE_FLUIDSYNTH
MODULE_OBJS += \
fluidsynth-dialog.o
diff --git a/gui/onscreendialog.cpp b/gui/onscreendialog.cpp
new file mode 100644
index 0000000000..03a6f26ec0
--- /dev/null
+++ b/gui/onscreendialog.cpp
@@ -0,0 +1,233 @@
+/* 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 "gui/gui-manager.h"
+
+#include "gui/EventRecorder.h"
+
+#include "common/events.h"
+#include "common/rect.h"
+#include "common/translation.h"
+
+#include "graphics/cursorman.h"
+
+#include "gui/editrecorddialog.h"
+#include "gui/ThemeEval.h"
+
+#include "gui/onscreendialog.h"
+
+namespace GUI {
+
+bool OnScreenDialog::isVisible() const {
+ return true;
+}
+
+enum {
+ kStopCmd = 'STOP',
+ kEditCmd = 'EDIT',
+ kSwitchModeCmd = 'MODE',
+ kFastModeCmd = 'FAST'
+};
+
+void OnScreenDialog::reflowLayout() {
+ GuiObject::reflowLayout();
+}
+
+void OnScreenDialog::releaseFocus() {
+}
+
+OnScreenDialog::OnScreenDialog(bool isRecord) : Dialog("OnScreenDialog") {
+ _x = _y = 0;
+
+#ifndef DISABLE_FANCY_THEMES
+ if (g_gui.xmlEval()->getVar("Globals.OnScreenDialog.ShowPics") == 1 && g_gui.theme()->supportsImages()) {
+ GUI::PicButtonWidget *btn;
+ btn = new PicButtonWidget(this, "OnScreenDialog.StopButton", 0, kStopCmd, 0);
+ btn->useThemeTransparency(true);
+
+ if (g_system->getOverlayWidth() > 320)
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageStopbtn));
+ else
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageStopSmallbtn));
+
+ if (isRecord) {
+ btn = new PicButtonWidget(this, "OnScreenDialog.EditButton", 0, kEditCmd, 0);
+ btn->useThemeTransparency(true);
+
+ if (g_system->getOverlayWidth() > 320)
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageEditbtn));
+ else
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageEditSmallbtn));
+ } else {
+ btn = new PicButtonWidget(this, "OnScreenDialog.SwitchModeButton", 0, kSwitchModeCmd, 0);
+ btn->useThemeTransparency(true);
+ if (g_system->getOverlayWidth() > 320)
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSwitchModebtn));
+ else
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSwitchModeSmallbtn));
+
+ btn = new PicButtonWidget(this, "OnScreenDialog.FastReplayButton", 0, kFastModeCmd, 0);
+ btn->useThemeTransparency(true);
+ if (g_system->getOverlayWidth() > 320)
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageFastReplaybtn));
+ else
+ btn->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageFastReplaySmallbtn));
+ }
+ } else
+#endif
+ {
+ if (g_system->getOverlayWidth() > 320)
+ new ButtonWidget(this, "OnScreenDialog.StopButton", "[ ]", _("Stop"), kStopCmd);
+ else
+ new ButtonWidget(this, "OnScreenDialog.StopButton", "[]", _("Stop"), kStopCmd);
+
+ if (isRecord) {
+ new ButtonWidget(this, "OnScreenDialog.EditButton", "E", _("Edit record description"), kEditCmd);
+ } else {
+ new ButtonWidget(this, "OnScreenDialog.SwitchModeButton", "G", _("Switch to Game"), kSwitchModeCmd);
+
+ new ButtonWidget(this, "OnScreenDialog.FastReplayButton", ">>", _("Fast replay"), kFastModeCmd);
+ }
+ }
+
+
+ _text = new GUI::StaticTextWidget(this, "OnScreenDialog.TimeLabel", "00:00:00");
+ _enableDrag = false;
+ _mouseOver = false;
+ _editDlgShown = false;
+
+ _lastTime = 0;
+ _dlg = 0;
+}
+
+void OnScreenDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ Common::Event eventRTL;
+ switch (cmd) {
+ case kStopCmd:
+ eventRTL.type = Common::EVENT_RTL;
+ g_system->getEventManager()->pushEvent(eventRTL);
+ close();
+ break;
+ case kEditCmd:
+ _dlg = new EditRecordDialog(g_eventRec.getAuthor(), g_eventRec.getName(), g_eventRec.getNotes());
+ CursorMan.lock(false);
+ g_eventRec.setRedraw(false);
+ g_system->showOverlay();
+ _editDlgShown = true;
+ _dlg->runModal();
+ _editDlgShown = false;
+ g_system->hideOverlay();
+ g_eventRec.setRedraw(true);
+ CursorMan.lock(true);
+ g_eventRec.setAuthor(((EditRecordDialog *)_dlg)->getAuthor());
+ g_eventRec.setName(((EditRecordDialog *)_dlg)->getName());
+ g_eventRec.setNotes(((EditRecordDialog *)_dlg)->getNotes());
+ delete _dlg;
+ break;
+ case kSwitchModeCmd:
+ if (g_eventRec.switchMode()) {
+ close();
+ }
+ break;
+ case kFastModeCmd:
+ g_eventRec.switchFastMode();
+ break;
+ }
+}
+
+void OnScreenDialog::setReplayedTime(uint32 newTime) {
+ if (newTime - _lastTime > 1000) {
+ uint32 seconds = newTime / 1000;
+ _text->setLabel(Common::String::format("%.2d:%.2d:%.2d", seconds / 3600 % 24, seconds / 60 % 60, seconds % 60));
+ _lastTime = newTime;
+ }
+}
+
+OnScreenDialog::~OnScreenDialog() {
+}
+
+void OnScreenDialog::handleMouseMoved(int x, int y, int button) {
+ if (_enableDrag) {
+ _x = _x + x - _dragPoint.x;
+ _y = _y + y - _dragPoint.y;
+ }
+ Dialog::handleMouseMoved(x, y, button);
+ if (isMouseOver(x, y)) {
+ if (_mouseOver == false) {
+ g_gui.theme()->showCursor();
+ CursorMan.lock(true);
+ }
+ _mouseOver = true;
+ } else {
+ if (_mouseOver == true) {
+ CursorMan.lock(false);
+ g_gui.theme()->hideCursor();
+ }
+ _mouseOver = false;
+ }
+}
+
+void OnScreenDialog::handleMouseDown(int x, int y, int button, int clickCount) {
+ if (isMouseOver(x, y)) {
+ _dragPoint.x = x;
+ _dragPoint.y = y;
+ _enableDrag = true;
+ }
+ Dialog::handleMouseDown(x, y, button, clickCount);
+}
+
+void OnScreenDialog::handleMouseUp(int x, int y, int button, int clickCount) {
+ if (isMouseOver(x, y)) {
+
+ }
+ _enableDrag = false;
+ Dialog::handleMouseUp(x, y, button, clickCount);
+}
+
+bool OnScreenDialog::isMouseOver(int x, int y) {
+ return (x >= 0 && x < _w && y >= 0 && y < _h);
+}
+
+bool OnScreenDialog::isMouseOver() {
+ return _mouseOver;
+}
+
+void OnScreenDialog::close() {
+ CursorMan.lock(false);
+ Dialog::close();
+}
+
+Dialog *OnScreenDialog::getActiveDlg() {
+ if (_editDlgShown) {
+ return _dlg;
+ } else {
+ return this;
+ }
+}
+
+bool OnScreenDialog::isEditDlgVisible() {
+ return _editDlgShown;
+}
+
+}
diff --git a/gui/onscreendialog.h b/gui/onscreendialog.h
new file mode 100644
index 0000000000..2fae14cbc6
--- /dev/null
+++ b/gui/onscreendialog.h
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GUI_ONSCREENDIALOG_H
+#define GUI_ONSCREENDIALOG_H
+
+#include "gui/dialog.h"
+#include "gui/widget.h"
+
+namespace GUI {
+
+class OnScreenDialog : public Dialog {
+private:
+ uint32 _lastTime;
+ bool _enableDrag;
+ bool _mouseOver;
+ bool _editDlgShown;
+ Common::Point _dragPoint;
+ GUI::StaticTextWidget *_text;
+ Dialog *_dlg;
+
+ bool isMouseOver(int x, int y);
+
+public:
+ OnScreenDialog(bool recordingMode);
+ ~OnScreenDialog();
+ virtual void close();
+ virtual bool isVisible() const;
+ virtual void reflowLayout();
+
+ void setReplayedTime(uint32 newTime);
+
+ virtual void handleMouseMoved(int x, int y, int button);
+ virtual void handleMouseDown(int x, int y, int button, int clickCount);
+ virtual void handleMouseUp(int x, int y, int button, int clickCount);
+ void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
+
+ bool isMouseOver();
+ bool isEditDlgVisible();
+ Dialog *getActiveDlg();
+protected:
+ virtual void releaseFocus();
+};
+
+} // End of namespace GUI
+
+#endif
diff --git a/gui/recorderdialog.cpp b/gui/recorderdialog.cpp
new file mode 100644
index 0000000000..1a11dbac65
--- /dev/null
+++ b/gui/recorderdialog.cpp
@@ -0,0 +1,298 @@
+/* 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/algorithm.h"
+#include "common/bufferedstream.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "graphics/colormasks.h"
+#include "graphics/palette.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
+#include "common/translation.h"
+#include "gui/widgets/list.h"
+#include "gui/editrecorddialog.h"
+#include "gui/EventRecorder.h"
+#include "gui/message.h"
+#include "gui/saveload.h"
+#include "common/system.h"
+#include "gui/ThemeEval.h"
+#include "gui/gui-manager.h"
+#include "recorderdialog.h"
+
+#define MAX_RECORDS_NAMES 0xFF
+
+namespace GUI {
+
+enum {
+ kRecordCmd = 'RCRD',
+ kPlaybackCmd = 'PBCK',
+ kDeleteCmd = 'DEL ',
+ kNextScreenshotCmd = 'NEXT',
+ kPrevScreenshotCmd = 'PREV',
+ kEditRecordCmd = 'EDIT'
+};
+
+RecorderDialog::RecorderDialog() : Dialog("RecorderDialog"), _list(0), _currentScreenshot(0) {
+ _firstScreenshotUpdate = false;
+ _screenShotsCount = 0;
+ _currentScreenshotText = 0;
+ _authorText = 0;
+ _notesText = 0;
+
+ _backgroundType = ThemeEngine::kDialogBackgroundSpecial;
+
+ new StaticTextWidget(this, "SaveLoadChooser.Title", _("Recorder or Playback Gameplay"));
+
+ _list = new GUI::ListWidget(this, "RecorderDialog.List");
+ _list->setNumberingMode(GUI::kListNumberingOff);
+
+ _deleteButton = new GUI::ButtonWidget(this, "RecorderDialog.Delete", _("Delete"), 0, kDeleteCmd);
+ new GUI::ButtonWidget(this, "RecorderDialog.Cancel", _("Cancel"), 0, kCloseCmd);
+ new GUI::ButtonWidget(this, "RecorderDialog.Record", _("Record"), 0, kRecordCmd);
+ _playbackButton = new GUI::ButtonWidget(this, "RecorderDialog.Playback", _("Playback"), 0, kPlaybackCmd);
+
+ _editButton = new GUI::ButtonWidget(this, "RecorderDialog.Edit", _("Edit"), 0, kEditRecordCmd);
+
+ _editButton->setEnabled(false);
+ _deleteButton->setEnabled(false);
+ _playbackButton->setEnabled(false);
+
+ _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10);
+ _container = new GUI::ContainerWidget(this, 0, 0, 10, 10);
+ if (g_gui.xmlEval()->getVar("Globals.RecorderDialog.ExtInfo.Visible") == 1) {
+ new GUI::ButtonWidget(this,"RecorderDialog.NextScreenShotButton", "<", 0, kPrevScreenshotCmd);
+ new GUI::ButtonWidget(this, "RecorderDialog.PreviousScreenShotButton", ">", 0, kNextScreenshotCmd);
+ _currentScreenshotText = new StaticTextWidget(this, "RecorderDialog.currentScreenshot", "0/0");
+ _authorText = new StaticTextWidget(this, "RecorderDialog.Author", _("Author: "));
+ _notesText = new StaticTextWidget(this, "RecorderDialog.Notes", _("Notes: "));
+ }
+ if (_gfxWidget)
+ _gfxWidget->setGfx(0);
+}
+
+
+void RecorderDialog::reflowLayout() {
+ if (g_gui.xmlEval()->getVar("Globals.RecorderDialog.ExtInfo.Visible") == 1) {
+ int16 x, y;
+ uint16 w, h;
+
+ if (!g_gui.xmlEval()->getWidgetData("RecorderDialog.Thumbnail", x, y, w, h)) {
+ error("Error when loading position data for Recorder Thumbnails");
+ }
+
+ int thumbW = kThumbnailWidth;
+ int thumbH = kThumbnailHeight2;
+ int thumbX = x + (w >> 1) - (thumbW >> 1);
+ int thumbY = y + kLineHeight;
+
+ _container->resize(x, y, w, h);
+ _gfxWidget->resize(thumbX, thumbY, thumbW, thumbH);
+
+ _container->setVisible(true);
+ _gfxWidget->setVisible(true);
+ updateSelection(false);
+ } else {
+ _container->setVisible(false);
+ _gfxWidget->setVisible(false);
+ }
+ Dialog::reflowLayout();
+}
+
+
+
+void RecorderDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+ switch(cmd) {
+ case kEditRecordCmd: {
+ if (_list->getSelected() >= 0) {
+ EditRecordDialog editDlg(_fileHeaders[_list->getSelected()].author, _fileHeaders[_list->getSelected()].name, _fileHeaders[_list->getSelected()].notes);
+ if (editDlg.runModal() != kOKCmd) {
+ return;
+ }
+ _playbackFile.openRead(_fileHeaders[_list->getSelected()].fileName);
+ _playbackFile.getHeader().author = editDlg.getAuthor();
+ _playbackFile.getHeader().name = editDlg.getName();
+ _playbackFile.getHeader().notes = editDlg.getNotes();
+ _playbackFile.updateHeader();
+ _fileHeaders[_list->getSelected()] = _playbackFile.getHeader();
+ int oldselection = _list->getSelected();
+ updateList();
+ _list->setSelected(oldselection);
+ updateSelection(true);
+ _playbackFile.close();
+ }
+ }
+ break;
+ case kNextScreenshotCmd:
+ ++_currentScreenshot;
+ updateScreenshot();
+ break;
+ case kPrevScreenshotCmd:
+ --_currentScreenshot;
+ updateScreenshot();
+ break;
+ case kDeleteCmd:
+ if (_list->getSelected() >= 0) {
+ MessageDialog alert(_("Do you really want to delete this record?"),
+ _("Delete"), _("Cancel"));
+ if (alert.runModal() == GUI::kMessageOK) {
+ _playbackFile.close();
+ g_eventRec.deleteRecord(_fileHeaders[_list->getSelected()].fileName);
+ _list->setSelected(-1);
+ updateList();
+ }
+ }
+ break;
+ case GUI::kListSelectionChangedCmd:
+ updateSelection(true);
+ break;
+ case kRecordCmd: {
+ TimeDate t;
+ Common::String gameId = ConfMan.get("gameid", _target);
+ const EnginePlugin *plugin = 0;
+ GameDescriptor desc = EngineMan.findGame(gameId, &plugin);
+ 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(), "");
+ if (editDlg.runModal() != kOKCmd) {
+ return;
+ }
+ _author = editDlg.getAuthor();
+ _name = editDlg.getName();
+ _notes = editDlg.getNotes();
+ _filename = g_eventRec.generateRecordFileName(_target);
+ setResult(kRecordDialogRecord);
+ close();
+ }
+ break;
+ case kPlaybackCmd:
+ if (_list->getSelected() >= 0) {
+ _filename = _fileHeaders[_list->getSelected()].fileName;
+ setResult(kRecordDialogPlayback);
+ close();
+ }
+ break;
+ case kCloseCmd:
+ setResult(kRecordDialogClose);
+ // Fall through
+ default:
+ Dialog::handleCommand(sender, cmd, data);
+ }
+}
+
+void RecorderDialog::updateList() {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::String pattern(_target+".r??");
+ Common::StringArray files = saveFileMan->listSavefiles(pattern);
+ Common::PlaybackFile file;
+ Common::StringArray namesList;
+ _fileHeaders.clear();
+ for (Common::StringArray::iterator i = files.begin(); i != files.end(); ++i) {
+ if (file.openRead(*i)) {
+ namesList.push_back(file.getHeader().name);
+ _fileHeaders.push_back(file.getHeader());
+ }
+ file.close();
+ }
+ _list->setList(namesList);
+ _list->draw();
+}
+
+int RecorderDialog::runModal(Common::String &target) {
+ _target = target;
+ updateList();
+ return Dialog::runModal();
+}
+
+RecorderDialog::~RecorderDialog() {
+}
+
+void RecorderDialog::updateSelection(bool redraw) {
+ if (_list->getSelected() >= 0) {
+ _editButton->setEnabled(true);
+ _deleteButton->setEnabled(true);
+ _playbackButton->setEnabled(true);
+ }
+
+ if (g_gui.xmlEval()->getVar("Globals.RecorderDialog.ExtInfo.Visible") != 1)
+ return;
+
+ _gfxWidget->setGfx(-1, -1, 0, 0, 0);
+ _screenShotsCount = 0;
+ _currentScreenshot = 0;
+ updateScreenShotsText();
+ if (_list->getSelected() >= 0) {
+ _authorText->setLabel(_("Author: ") + _fileHeaders[_list->getSelected()].author);
+ _notesText->setLabel(_("Notes: ") + _fileHeaders[_list->getSelected()].notes);
+
+ _firstScreenshotUpdate = true;
+ updateScreenshot();
+ if ((_screenShotsCount) > 0) {
+ _currentScreenshot = 1;
+ }
+ updateScreenshot();
+ } else {
+ _authorText->setLabel(_("Author: "));
+ _notesText->setLabel(_("Notes: "));
+ _screenShotsCount = -1;
+ _currentScreenshot = 0;
+ _gfxWidget->setGfx(-1, -1, 0, 0, 0);
+ _gfxWidget->draw();
+ updateScreenShotsText();
+ }
+}
+
+void RecorderDialog::updateScreenshot() {
+ if (_list->getSelected() == -1) {
+ return;
+ }
+ if (_currentScreenshot < 1) {
+ _currentScreenshot = _screenShotsCount;
+ }
+ if (_currentScreenshot > _screenShotsCount) {
+ _currentScreenshot = 1;
+ }
+ if (_firstScreenshotUpdate) {
+ _playbackFile.openRead(_fileHeaders[_list->getSelected()].fileName);
+ _screenShotsCount = _playbackFile.getScreensCount();
+ _firstScreenshotUpdate = false;
+ }
+ Graphics::Surface *srcsf = _playbackFile.getScreenShot(_currentScreenshot);
+ if (srcsf != NULL) {
+ Graphics::Surface *destsf = Graphics::scale(*srcsf, _gfxWidget->getWidth(), _gfxWidget->getHeight());
+ _gfxWidget->setGfx(destsf);
+ updateScreenShotsText();
+ delete destsf;
+ delete srcsf;
+ } else {
+ _gfxWidget->setGfx(-1, -1, 0, 0, 0);
+ }
+ _gfxWidget->draw();
+}
+
+void RecorderDialog::updateScreenShotsText() {
+ if (_screenShotsCount == -1) {
+ _currentScreenshotText->setLabel(Common::String::format("%d / ?", _currentScreenshot));
+ } else {
+ _currentScreenshotText->setLabel(Common::String::format("%d / %d", _currentScreenshot, _screenShotsCount));
+ }
+}
+
+} // End of namespace GUI
diff --git a/gui/recorderdialog.h b/gui/recorderdialog.h
new file mode 100644
index 0000000000..eb690a4f38
--- /dev/null
+++ b/gui/recorderdialog.h
@@ -0,0 +1,81 @@
+/* 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_RECORDER_DIALOG_H
+#define GUI_RECORDER_DIALOG_H
+#include "common/stream.h"
+#include "common/recorderfile.h"
+#include "gui/dialog.h"
+namespace GUI {
+
+class ListWidget;
+class GraphicsWidget;
+class ButtonWidget;
+class CommandSender;
+class ContainerWidget;
+class StaticTextWidget;
+
+class RecorderDialog : public GUI::Dialog {
+private:
+ bool _firstScreenshotUpdate;
+ Common::PlaybackFile _playbackFile;
+ Common::String _target;
+ Common::String _filename;
+ int _currentScreenshot;
+ int _screenShotsCount;
+ Common::Array<Common::PlaybackFile::PlaybackFileHeader> _fileHeaders;
+ GUI::ListWidget *_list;
+ GUI::ContainerWidget *_container;
+ GUI::GraphicsWidget *_gfxWidget;
+ GUI::StaticTextWidget *_currentScreenshotText;
+ GUI::StaticTextWidget *_authorText;
+ GUI::StaticTextWidget *_notesText;
+ GUI::ButtonWidget *_editButton;
+ GUI::ButtonWidget *_deleteButton;
+ GUI::ButtonWidget *_playbackButton;
+
+ void updateList();
+ void updateScreenShotsText();
+ void updateSelection(bool redraw);
+ void updateScreenshot();
+public:
+ Common::String _author;
+ Common::String _name;
+ Common::String _notes;
+ enum DialogResult {
+ kRecordDialogClose,
+ kRecordDialogRecord,
+ kRecordDialogPlayback
+ };
+ RecorderDialog();
+ ~RecorderDialog();
+
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ virtual void reflowLayout();
+
+ int runModal(Common::String &target);
+ const Common::String getFileName() {return _filename;}
+};
+
+} // End of namespace GUI
+
+
+#endif
diff --git a/gui/saveload-dialog.cpp b/gui/saveload-dialog.cpp
index c7dd62b6c6..585117fba4 100644
--- a/gui/saveload-dialog.cpp
+++ b/gui/saveload-dialog.cpp
@@ -286,6 +286,7 @@ void SaveLoadChooserSimple::handleCommand(CommandSender *sender, uint32 cmd, uin
break;
case kCloseCmd:
setResult(-1);
+ // Fall through
default:
SaveLoadChooserDialog::handleCommand(sender, cmd, data);
}
@@ -595,6 +596,7 @@ void SaveLoadChooserGrid::handleCommand(CommandSender *sender, uint32 cmd, uint3
case kCloseCmd:
setResult(-1);
+ // Fall through
default:
SaveLoadChooserDialog::handleCommand(sender, cmd, data);
}
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 6d8e6baac7..1b6ae3ec27 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -610,50 +610,54 @@
"/> "
"</drawdata> "
"</render_info> "
-"<layout_info resolution='y<400'> "
+"<layout_info resolution='y>399'> "
"<globals> "
-"<def var='Line.Height' value='12' /> "
-"<def var='Font.Height' value='10' /> "
-"<def var='About.OuterBorder' value='10'/> "
-"<def var='Layout.Spacing' value='8'/> "
+"<def var='Line.Height' value='16' /> "
+"<def var='Font.Height' value='16' /> "
+"<def var='About.OuterBorder' value='80'/> "
+"<def var='Layout.Spacing' value='8' /> "
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
"<def var='ShowChooserPics' value='0'/> "
-"<def var='ShowChooserPageDisplay' value='0'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
-"<def var='KeyMapper.Spacing' value='5'/> "
-"<def var='KeyMapper.LabelWidth' value='80'/> "
-"<def var='KeyMapper.ButtonWidth' value='60'/> "
-"<def var='Tooltip.MaxWidth' value='70'/> "
-"<def var='Tooltip.XDelta' value='8'/> "
-"<def var='Tooltip.YDelta' value='8'/> "
-"<def var='Predictive.Button.Width' value='45' /> "
-"<def var='Predictive.Button.Height' value='15' /> "
-"<widget name='Button' "
-"size='72,16' "
-"/> "
-"<widget name='Slider' "
-"size='85,12' "
-"/> "
+"<def var='ShowChooserPageDisplay' value='1'/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
+"<def var='RecorderDialog.ExtInfo.Visible' value='1'/> "
+"<def var='OnScreenDialog.ShowPics' value='0'/> "
+"<def var='KeyMapper.Spacing' value='10'/> "
+"<def var='KeyMapper.LabelWidth' value='100'/> "
+"<def var='KeyMapper.ButtonWidth' value='80'/> "
+"<def var='Tooltip.MaxWidth' value='200'/> "
+"<def var='Tooltip.XDelta' value='16'/> "
+"<def var='Tooltip.YDelta' value='16'/> "
+"<def var='Predictive.Button.Width' value='60' /> "
"<widget name='OptionsLabel' "
"size='110,Globals.Line.Height' "
"textalign='right' "
"/> "
"<widget name='SmallLabel' "
-"size='18,Globals.Line.Height' "
+"size='24,Globals.Line.Height' "
+"/> "
+"<widget name='ShortOptionsLabel' "
+"size='60,Globals.Line.Height' "
+"/> "
+"<widget name='Button' "
+"size='108,24' "
+"/> "
+"<widget name='Slider' "
+"size='128,18' "
"/> "
"<widget name='PopUp' "
-"size='-1,15' "
+"size='-1,19' "
"/> "
"<widget name='Checkbox' "
-"size='-1,Globals.Line.Height' "
+"size='-1,14' "
"/> "
"<widget name='Radiobutton' "
"size='-1,Globals.Line.Height' "
"/> "
"<widget name='ListWidget' "
-"padding='5,0,0,0' "
+"padding='5,0,8,0' "
"/> "
"<widget name='PopUpWidget' "
"padding='7,5,0,0' "
@@ -665,29 +669,35 @@
"padding='7,5,5,5' "
"/> "
"<widget name='Scrollbar' "
-"size='9,0' "
+"size='15,0' "
"/> "
"<widget name='TabWidget.Tab' "
-"size='45,16' "
-"padding='0,0,2,0' "
+"size='75,27' "
+"padding='0,0,8,0' "
"/> "
"<widget name='TabWidget.Body' "
-"padding='0,0,0,-8' "
+"padding='0,0,0,0' "
"/> "
"<widget name='TabWidget.NavButton' "
-"size='32,18' "
-"padding='0,0,1,0' "
+"size='15,18' "
+"padding='0,3,4,0' "
+"/> "
+"<widget name='EditRecordLabel' "
+"size='60,25' "
+"/> "
+"<widget name='EditRecord' "
+"size='240,25' "
"/> "
"</globals> "
"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='6,6,2,2'> "
+"<layout type='vertical' center='true' padding='16,16,8,8'> "
"<widget name='Version' "
"height='Globals.Line.Height' "
"textalign='center' "
"/> "
-"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
+"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
"<widget name='SearchDesc' "
-"width='50' "
+"width='60' "
"height='Globals.Line.Height' "
"textalign='right' "
"/> "
@@ -702,38 +712,39 @@
"<space /> "
"</layout> "
"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='LoadGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='AddGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='EditGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='RemoveGameButton' "
-"height='12' "
+"height='20' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<space size='4'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='QuitButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='AboutButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='OptionsButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='StartButton' "
-"height='12' "
+"height='20' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,0,4'> "
+"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
"/> "
@@ -741,7 +752,7 @@
"height='Globals.Line.Height' "
"/> "
"<widget name='List'/> "
-"<layout type='vertical' padding='0,0,8,0'> "
+"<layout type='vertical' padding='0,0,16,0'> "
"<widget name='Hidden' "
"type='Checkbox' "
"/> "
@@ -760,10 +771,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
+"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,16'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -776,7 +787,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -784,7 +795,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -802,7 +813,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -810,7 +821,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -818,7 +829,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -826,7 +837,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
@@ -840,7 +851,7 @@
"type='Radiobutton' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -854,8 +865,9 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -866,7 +878,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -877,7 +889,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -888,8 +900,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"</layout> "
+"<layout type='vertical' padding='24,0,24,0' center='true'> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
"/> "
@@ -897,8 +909,8 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='6'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auPrefGmPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -906,7 +918,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='mcFontButton' "
"type='Button' "
"/> "
@@ -921,7 +933,7 @@
"<widget name='mcMixedCheckbox' "
"type='Checkbox' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
"/> "
@@ -934,14 +946,14 @@
"/> "
"</layout> "
"<widget name='mcFluidSynthSettings' "
-"width='150' "
+"width='200' "
"height='Globals.Button.Height' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auPrefMt32PopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -959,7 +971,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='SaveButton' "
"type='Button' "
"/> "
@@ -971,7 +983,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -983,7 +995,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ExtraButton' "
"type='Button' "
"/> "
@@ -1007,7 +1019,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -1015,31 +1027,25 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='RendererPopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='RendererPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='AutosavePeriodPopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='AutosavePeriodPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='GuiLanguagePopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='GuiLanguagePopup' "
"type='PopUp' "
@@ -1074,10 +1080,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
+"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,4'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -1089,7 +1095,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1097,7 +1103,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1105,7 +1111,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1113,7 +1119,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1121,7 +1127,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1129,43 +1135,34 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Id' "
-"width='35' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='Domain' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Name' "
-"width='35' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='Desc' "
"type='PopUp' "
"/> "
"</layout> "
-"<space size='8'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='LangPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='LangPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PlatformPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='PlatformPopup' "
"type='PopUp' "
@@ -1174,8 +1171,8 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Savepath' "
"type='Button' "
"/> "
@@ -1187,7 +1184,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Extrapath' "
"type='Button' "
"/> "
@@ -1199,7 +1196,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Gamepath' "
"type='Button' "
"/> "
@@ -1210,7 +1207,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='vertical' padding='16,16,16,16'> "
"<widget name='customOption1Checkbox' "
"type='Checkbox' "
"/> "
@@ -1235,55 +1232,57 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' center='true'> "
"<widget name='Title' "
-"width='160' "
-"height='4' "
+"width='210' "
+"height='Globals.Line.Height' "
"/> "
"<widget name='Version' "
-"width='160' "
-"height='4' "
+"width='210' "
+"height='Globals.Line.Height' "
"/> "
-"<space size='1'/> "
+"<widget name='Resume' "
+"width='150' "
+"height='Globals.Button.Height' "
+"/> "
+"<space size='10'/> "
"<widget name='Load' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Save' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
-"<space size='1'/> "
+"<space size='10'/> "
"<widget name='Options' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Help' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='About' "
-"width='120' "
-"height='12' "
-"/> "
-"<space size='1'/> "
-"<widget name='Resume' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
+"<space size='10'/> "
"<widget name='RTL' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Quit' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalConfig' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='vertical' padding='0,0,0,0' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -1294,7 +1293,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -1305,7 +1304,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -1316,34 +1315,33 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"</layout> "
+"<layout type='vertical' padding='24,24,24,24' center='true'> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
+"width='80' "
"/> "
"</layout> "
-"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
+"</layout> "
+"<space size='8' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subToggleSpeechOnly' "
"type='Radiobutton' "
-"width='90' "
+"width='100' "
"/> "
"<widget name='subToggleSubOnly' "
"type='Radiobutton' "
-"width='90' "
+"width='100' "
"/> "
"<widget name='subToggleSubBoth' "
"type='Radiobutton' "
-"width='90' "
+"width='100' "
"/> "
"</layout> "
-"</layout> "
-"<space size='2' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -1354,8 +1352,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='16'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
+"<space size='60'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='Keys' "
"type='Button' "
"/> "
@@ -1372,7 +1370,7 @@
"<dialog name='FluidSynthSettings' overlays='GlobalOptions' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,16'> "
"<space/> "
"<widget name='ResetSettings' "
"type='Button' "
@@ -1387,7 +1385,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Chorus' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1450,7 +1448,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Reverb' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1505,7 +1503,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Misc' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='InterpolationText' "
"type='OptionsLabel' "
@@ -1517,10 +1515,25 @@
"</layout> "
"</dialog> "
"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
-"<widget name='Title' height='Globals.Line.Height'/> "
+"<layout type='vertical' padding='8,8,8,32' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='Title' "
+"height='Globals.Line.Height' "
+"/> "
+"<space/> "
+"<widget name='PageDisplay' "
+"width='200' "
+"height='Globals.Line.Height' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
"<widget name='List' /> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Thumbnail' "
+"width='180' "
+"height='200' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='ListSwitch' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
@@ -1533,7 +1546,7 @@
"<widget name='Delete' "
"type='Button' "
"/> "
-"<space size='16'/> "
+"<space size='32'/> "
"<widget name='Cancel' "
"type='Button' "
"/> "
@@ -1546,7 +1559,7 @@
"<dialog name='SavenameDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='DescriptionText' "
-"width='180' "
+"width='320' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description' "
@@ -1556,22 +1569,139 @@
"<widget name='Cancel' "
"type='Button' "
"/> "
+"<space size='96'/> "
"<widget name='Ok' "
"type='Button' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='ScummHelp' overlays='screen'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<dialog name='RecorderDialog' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,32' center='true'> "
"<widget name='Title' "
+"height='Globals.Line.Height' "
+"/> "
+"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
+"<widget name='List' /> "
+"<layout type='vertical' padding='0,0,0,0'> "
+"<widget name='Thumbnail' "
"width='180' "
+"height='170' "
+"/> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='NextScreenShotButton' "
+"width='25' "
+"height='25' "
+"/> "
+"<widget name='currentScreenshot' "
+"width='125' "
+"height='25' "
+"textalign='center' "
+"/> "
+"<widget name='PreviousScreenShotButton' "
+"width='25' "
+"height='25' "
+"/> "
+"</layout> "
+"<widget name='Author' height='Globals.Line.Height' /> "
+"<widget name='Notes' height='Globals.Line.Height' /> "
+"</layout> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<widget name='Delete' "
+"type='Button' "
+"/> "
+"<space size='16'/> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<space size='16'/> "
+"<widget name='Edit' "
+"type='Button' "
+"/> "
+"<widget name='Record' "
+"type='Button' "
+"/> "
+"<widget name='Playback' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='OnScreenDialog' overlays='screen_center'> "
+"<layout type='horizontal' spacing='5' padding='5,3,5,3' center='true'> "
+"<widget name='StopButton' "
+"width='32' "
+"height='32' "
+"/> "
+"<widget name='EditButton' "
+"width='32' "
+"height='32' "
+"/> "
+"<widget name='SwitchModeButton' "
+"width='32' "
+"height='32' "
+"/> "
+"<widget name='FastReplayButton' "
+"width='32' "
+"height='32' "
+"/> "
+"<widget name='TimeLabel' "
+"width='50' "
+"height='30' "
+"/> "
+"</layout> "
+"</dialog> "
+"<dialog name='EditRecordDialog' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Title' "
+"width='320' "
+"height='Globals.Line.Height' "
+"/> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='AuthorLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='AuthorEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='NameLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='NameEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='NotesLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='NotesEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='OK' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='ScummHelp' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Title' "
+"width='320' "
"height='Globals.Line.Height' "
"/> "
"<widget name='HelpText' "
-"height='140' "
+"height='200' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,16,0'> "
"<widget name='Prev' "
"type='Button' "
"/> "
@@ -1588,7 +1718,7 @@
"<dialog name='LoomTownsDifficultyDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Description1' "
-"width='280' "
+"width='320' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description2' "
@@ -1606,20 +1736,20 @@
"</layout> "
"</dialog> "
"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='4,4,16,4' center='true'> "
+"<layout type='vertical' padding='8,8,32,8' center='true'> "
"<widget name='DirProgressText' "
-"width='280' "
+"width='480' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameProgressText' "
-"width='280' "
+"width='480' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameList' "
-"width='280' "
-"height='100' "
+"width='480' "
+"height='250' "
"/> "
-"<layout type='horizontal' padding='4,4,4,4'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<widget name='Ok' "
"type='Button' "
"/> "
@@ -1630,20 +1760,20 @@
"</layout> "
"</dialog> "
"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PopupDesc' "
"type='OptionsLabel' "
"/> "
"<widget name='Popup' "
"type='PopUp' "
-"width='150' "
+"width='400' "
"height='Globals.Line.Height' "
"/> "
"</layout> "
"<widget name='KeymapArea' "
-"width='300' "
-"height='120' "
+"width='600' "
+"height='280' "
"/> "
"<widget name='Close' "
"type='Button' "
@@ -1651,142 +1781,144 @@
"</layout> "
"</dialog> "
"<dialog name='Predictive' overlays='screen_center'> "
-"<layout type='vertical' padding='1,1,1,1' center='true'> "
+"<layout type='vertical' padding='5,5,5,5' center='true'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
-"width='150' "
+"width='210' "
"textalign='center' "
"/> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"<layout type='horizontal' padding='5,5,5,5'> "
"<widget name='Word' "
-"width='120' "
+"width='190' "
"height='Globals.Button.Height' "
"/> "
"<widget name='Delete' "
"width='20' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
+"<space size='5' /> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button1' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button2' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button3' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button4' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button5' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button6' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button7' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button8' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button9' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='3,3,3,0'> "
+"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Pre' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Button0' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Next' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
-"<space size='3' /> "
-"<layout type='horizontal' padding='3,3,0,3'> "
+"<space size='5' /> "
+"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Add' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
+"<space size='22'/> "
"<widget name='Cancel' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='OK' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Predictive.Button.Height' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
"</layout_info> "
-"<layout_info resolution='y>399'> "
+"<layout_info resolution='y<400'> "
"<globals> "
-"<def var='Line.Height' value='16' /> "
-"<def var='Font.Height' value='16' /> "
-"<def var='About.OuterBorder' value='80'/> "
-"<def var='Layout.Spacing' value='8' /> "
+"<def var='Line.Height' value='12' /> "
+"<def var='Font.Height' value='10' /> "
+"<def var='About.OuterBorder' value='10'/> "
+"<def var='Layout.Spacing' value='8'/> "
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
"<def var='ShowChooserPics' value='0'/> "
-"<def var='ShowChooserPageDisplay' value='1'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
-"<def var='KeyMapper.Spacing' value='10'/> "
-"<def var='KeyMapper.LabelWidth' value='100'/> "
-"<def var='KeyMapper.ButtonWidth' value='80'/> "
-"<def var='Tooltip.MaxWidth' value='200'/> "
-"<def var='Tooltip.XDelta' value='16'/> "
-"<def var='Tooltip.YDelta' value='16'/> "
-"<def var='Predictive.Button.Width' value='60' /> "
+"<def var='ShowChooserPageDisplay' value='0'/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
+"<def var='RecorderDialog.ExtInfo.Visible' value='0'/> "
+"<def var='OnScreenDialog.ShowPics' value='0'/> "
+"<def var='KeyMapper.Spacing' value='5'/> "
+"<def var='KeyMapper.LabelWidth' value='80'/> "
+"<def var='KeyMapper.ButtonWidth' value='60'/> "
+"<def var='Tooltip.MaxWidth' value='70'/> "
+"<def var='Tooltip.XDelta' value='8'/> "
+"<def var='Tooltip.YDelta' value='8'/> "
+"<def var='Predictive.Button.Width' value='45' /> "
+"<def var='Predictive.Button.Height' value='15' /> "
+"<widget name='Button' "
+"size='72,16' "
+"/> "
+"<widget name='Slider' "
+"size='85,12' "
+"/> "
"<widget name='OptionsLabel' "
"size='110,Globals.Line.Height' "
"textalign='right' "
"/> "
"<widget name='SmallLabel' "
-"size='24,Globals.Line.Height' "
-"/> "
-"<widget name='ShortOptionsLabel' "
-"size='60,Globals.Line.Height' "
-"/> "
-"<widget name='Button' "
-"size='108,24' "
-"/> "
-"<widget name='Slider' "
-"size='128,18' "
+"size='18,Globals.Line.Height' "
"/> "
"<widget name='PopUp' "
-"size='-1,19' "
+"size='-1,15' "
"/> "
"<widget name='Checkbox' "
-"size='-1,14' "
+"size='-1,Globals.Line.Height' "
"/> "
"<widget name='Radiobutton' "
"size='-1,Globals.Line.Height' "
"/> "
"<widget name='ListWidget' "
-"padding='5,0,8,0' "
+"padding='5,0,0,0' "
"/> "
"<widget name='PopUpWidget' "
"padding='7,5,0,0' "
@@ -1798,29 +1930,35 @@
"padding='7,5,5,5' "
"/> "
"<widget name='Scrollbar' "
-"size='15,0' "
+"size='9,0' "
"/> "
"<widget name='TabWidget.Tab' "
-"size='75,27' "
-"padding='0,0,8,0' "
+"size='45,16' "
+"padding='0,0,2,0' "
"/> "
"<widget name='TabWidget.Body' "
-"padding='0,0,0,0' "
+"padding='0,0,0,-8' "
"/> "
"<widget name='TabWidget.NavButton' "
-"size='15,18' "
-"padding='0,3,4,0' "
+"size='32,18' "
+"padding='0,0,1,0' "
+"/> "
+"<widget name='EditRecordLabel' "
+"size='60,Globals.Line.Height' "
+"/> "
+"<widget name='EditRecord' "
+"size='120,15' "
"/> "
"</globals> "
"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='16,16,8,8'> "
+"<layout type='vertical' center='true' padding='6,6,2,2'> "
"<widget name='Version' "
"height='Globals.Line.Height' "
"textalign='center' "
"/> "
-"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
"<widget name='SearchDesc' "
-"width='60' "
+"width='50' "
"height='Globals.Line.Height' "
"textalign='right' "
"/> "
@@ -1835,39 +1973,38 @@
"<space /> "
"</layout> "
"<widget name='GameList'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='LoadGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='AddGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='EditGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='RemoveGameButton' "
-"height='20' "
+"height='12' "
"/> "
"</layout> "
-"<space size='4'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='QuitButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='AboutButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='OptionsButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='StartButton' "
-"height='20' "
+"height='12' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,0,4'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
"/> "
@@ -1875,7 +2012,7 @@
"height='Globals.Line.Height' "
"/> "
"<widget name='List'/> "
-"<layout type='vertical' padding='0,0,16,0'> "
+"<layout type='vertical' padding='0,0,8,0'> "
"<widget name='Hidden' "
"type='Checkbox' "
"/> "
@@ -1894,10 +2031,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -1910,7 +2047,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1918,7 +2055,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1936,7 +2073,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1944,7 +2081,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1952,7 +2089,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1960,7 +2097,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
@@ -1974,7 +2111,7 @@
"type='Radiobutton' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -1988,9 +2125,8 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
-"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -2001,7 +2137,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -2012,7 +2148,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -2023,8 +2159,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,0,24,0' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
"/> "
@@ -2032,8 +2168,8 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='6'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auPrefGmPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -2041,7 +2177,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='mcFontButton' "
"type='Button' "
"/> "
@@ -2056,7 +2192,7 @@
"<widget name='mcMixedCheckbox' "
"type='Checkbox' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
"/> "
@@ -2069,14 +2205,14 @@
"/> "
"</layout> "
"<widget name='mcFluidSynthSettings' "
-"width='200' "
+"width='150' "
"height='Globals.Button.Height' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auPrefMt32PopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -2094,7 +2230,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='SaveButton' "
"type='Button' "
"/> "
@@ -2106,7 +2242,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -2118,7 +2254,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ExtraButton' "
"type='Button' "
"/> "
@@ -2142,7 +2278,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -2150,25 +2286,31 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='RendererPopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='RendererPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='AutosavePeriodPopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='AutosavePeriodPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='GuiLanguagePopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='GuiLanguagePopup' "
"type='PopUp' "
@@ -2203,10 +2345,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,4'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -2218,7 +2360,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2226,7 +2368,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2234,7 +2376,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2242,7 +2384,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MT32' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2250,7 +2392,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2258,34 +2400,43 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='Id' "
-"type='OptionsLabel' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='Domain' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='Name' "
-"type='OptionsLabel' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='Desc' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<space size='8'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='LangPopupDesc' "
-"type='OptionsLabel' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='LangPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='PlatformPopupDesc' "
-"type='OptionsLabel' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='PlatformPopup' "
"type='PopUp' "
@@ -2294,8 +2445,8 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Savepath' "
"type='Button' "
"/> "
@@ -2307,7 +2458,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Extrapath' "
"type='Button' "
"/> "
@@ -2319,7 +2470,7 @@
"width='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Gamepath' "
"type='Button' "
"/> "
@@ -2330,7 +2481,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Engine' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='customOption1Checkbox' "
"type='Checkbox' "
"/> "
@@ -2355,57 +2506,55 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='16,16,16,16' center='true'> "
+"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
"<widget name='Title' "
-"width='210' "
-"height='Globals.Line.Height' "
+"width='160' "
+"height='4' "
"/> "
"<widget name='Version' "
-"width='210' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='Resume' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='160' "
+"height='4' "
"/> "
-"<space size='10'/> "
+"<space size='1'/> "
"<widget name='Load' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Save' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
-"<space size='10'/> "
+"<space size='1'/> "
"<widget name='Options' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Help' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='About' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
+"/> "
+"<space size='1'/> "
+"<widget name='Resume' "
+"width='120' "
+"height='12' "
"/> "
-"<space size='10'/> "
"<widget name='RTL' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Quit' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"</layout> "
"</dialog> "
"<dialog name='GlobalConfig' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<layout type='vertical' padding='0,0,0,0' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -2416,7 +2565,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -2427,7 +2576,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -2438,33 +2587,34 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,24,24,24' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
+"width='80' "
"/> "
"</layout> "
-"</layout> "
-"<space size='8' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subToggleSpeechOnly' "
"type='Radiobutton' "
-"width='100' "
+"width='90' "
"/> "
"<widget name='subToggleSubOnly' "
"type='Radiobutton' "
-"width='100' "
+"width='90' "
"/> "
"<widget name='subToggleSubBoth' "
"type='Radiobutton' "
-"width='100' "
+"width='90' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"</layout> "
+"<space size='2' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -2475,8 +2625,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='60'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<space size='16'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
"<widget name='Keys' "
"type='Button' "
"/> "
@@ -2493,7 +2643,7 @@
"<dialog name='FluidSynthSettings' overlays='GlobalOptions' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='ResetSettings' "
"type='Button' "
@@ -2508,7 +2658,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Chorus' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2571,7 +2721,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Reverb' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -2626,7 +2776,7 @@
"</layout> "
"</dialog> "
"<dialog name='FluidSynthSettings_Misc' overlays='Dialog.FluidSynthSettings.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='InterpolationText' "
"type='OptionsLabel' "
@@ -2638,25 +2788,10 @@
"</layout> "
"</dialog> "
"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,32' center='true'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
-"<widget name='Title' "
-"height='Globals.Line.Height' "
-"/> "
-"<space/> "
-"<widget name='PageDisplay' "
-"width='200' "
-"height='Globals.Line.Height' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Title' height='Globals.Line.Height'/> "
"<widget name='List' /> "
-"<widget name='Thumbnail' "
-"width='180' "
-"height='200' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,16,0'> "
"<widget name='ListSwitch' "
"height='Globals.Line.Height' "
"width='Globals.Line.Height' "
@@ -2669,7 +2804,7 @@
"<widget name='Delete' "
"type='Button' "
"/> "
-"<space size='32'/> "
+"<space size='16'/> "
"<widget name='Cancel' "
"type='Button' "
"/> "
@@ -2682,7 +2817,7 @@
"<dialog name='SavenameDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='DescriptionText' "
-"width='320' "
+"width='180' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description' "
@@ -2692,23 +2827,114 @@
"<widget name='Cancel' "
"type='Button' "
"/> "
-"<space size='96'/> "
"<widget name='Ok' "
"type='Button' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='ScummHelp' overlays='screen_center'> "
+"<dialog name='RecorderDialog' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,4' center='true'> "
+"<widget name='Title' "
+"height='Globals.Line.Height' "
+"/> "
+"<widget name='List' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='2'> "
+"<widget name='Edit' "
+"type='Button' "
+"/> "
+"<space /> "
+"<widget name='Record' "
+"type='Button' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='2'> "
+"<widget name='Delete' "
+"type='Button' "
+"/> "
+"<space /> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='Playback' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='OnScreenDialog' overlays='screen_center'> "
+"<layout type='horizontal' spacing='5' padding='3,2,3,2' center='true'> "
+"<widget name='StopButton' "
+"width='16' "
+"height='16' "
+"/> "
+"<widget name='EditButton' "
+"width='16' "
+"height='16' "
+"/> "
+"<widget name='SwitchModeButton' "
+"width='16' "
+"height='16' "
+"/> "
+"<widget name='FastReplayButton' "
+"width='16' "
+"height='16' "
+"/> "
+"<widget name='TimeLabel' "
+"width='50' "
+"height='16' "
+"/> "
+"</layout> "
+"</dialog> "
+"<dialog name='EditRecordDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Title' "
-"width='320' "
+"height='Globals.Line.Height' "
+"/> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='AuthorLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='AuthorEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='NameLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='NameEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,10'> "
+"<widget name='NotesLabel' "
+"type='EditRecordLabel' "
+"/> "
+"<widget name='NotesEdit' "
+"type='EditRecord' "
+"/> "
+"</layout> "
+"<layout type='horizontal' spacing='5' padding='0,0,0,0'> "
+"<widget name='Cancel' "
+"type='Button' "
+"/> "
+"<widget name='OK' "
+"type='Button' "
+"/> "
+"</layout> "
+"</layout> "
+"</dialog> "
+"<dialog name='ScummHelp' overlays='screen'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<widget name='Title' "
+"width='180' "
"height='Globals.Line.Height' "
"/> "
"<widget name='HelpText' "
-"height='200' "
+"height='140' "
"/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='Prev' "
"type='Button' "
"/> "
@@ -2725,7 +2951,7 @@
"<dialog name='LoomTownsDifficultyDialog' overlays='screen_center'> "
"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Description1' "
-"width='320' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='Description2' "
@@ -2743,20 +2969,20 @@
"</layout> "
"</dialog> "
"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' center='true'> "
+"<layout type='vertical' padding='4,4,16,4' center='true'> "
"<widget name='DirProgressText' "
-"width='480' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameProgressText' "
-"width='480' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameList' "
-"width='480' "
-"height='250' "
+"width='280' "
+"height='100' "
"/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='4,4,4,4'> "
"<widget name='Ok' "
"type='Button' "
"/> "
@@ -2767,20 +2993,20 @@
"</layout> "
"</dialog> "
"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PopupDesc' "
"type='OptionsLabel' "
"/> "
"<widget name='Popup' "
"type='PopUp' "
-"width='400' "
+"width='150' "
"height='Globals.Line.Height' "
"/> "
"</layout> "
"<widget name='KeymapArea' "
-"width='600' "
-"height='280' "
+"width='300' "
+"height='120' "
"/> "
"<widget name='Close' "
"type='Button' "
@@ -2788,93 +3014,91 @@
"</layout> "
"</dialog> "
"<dialog name='Predictive' overlays='screen_center'> "
-"<layout type='vertical' padding='5,5,5,5' center='true'> "
+"<layout type='vertical' padding='1,1,1,1' center='true'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
-"width='210' "
+"width='150' "
"textalign='center' "
"/> "
-"<layout type='horizontal' padding='5,5,5,5'> "
+"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Word' "
-"width='190' "
+"width='120' "
"height='Globals.Button.Height' "
"/> "
"<widget name='Delete' "
"width='20' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
-"<space size='5' /> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button1' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button2' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button3' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button4' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button5' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button6' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
"<layout type='horizontal' padding='3,3,3,3'> "
"<widget name='Button7' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button8' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button9' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"<layout type='horizontal' padding='3,3,3,0'> "
"<widget name='Pre' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Button0' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='Next' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
-"<space size='5' /> "
-"<layout type='horizontal' padding='3,3,3,3'> "
+"<space size='3' /> "
+"<layout type='horizontal' padding='3,3,0,3'> "
"<widget name='Add' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
-"<space size='22'/> "
"<widget name='Cancel' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"<widget name='OK' "
"width='Globals.Predictive.Button.Width' "
-"height='Globals.Button.Height' "
+"height='Globals.Predictive.Button.Height' "
"/> "
"</layout> "
"</layout> "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 297ff20344..4154c6c33a 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 180e8fba74..5fd2d6f835 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -36,6 +36,9 @@
<def var = 'ShowChooserPageDisplay' value = '1'/>
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
+ <def var = 'RecorderDialog.ExtInfo.Visible' value = '1'/>
+
+ <def var = 'OnScreenDialog.ShowPics' value = '0'/>
<def var = 'KeyMapper.Spacing' value = '10'/>
<def var = 'KeyMapper.LabelWidth' value = '100'/>
@@ -101,6 +104,12 @@
size = '15, 18'
padding = '0, 3, 4, 0'
/>
+ <widget name = 'EditRecordLabel'
+ size = '60, 25'
+ />
+ <widget name = 'EditRecord'
+ size = '240, 25'
+ />
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
@@ -1019,6 +1028,125 @@
</layout>
</dialog>
+ <dialog name = 'RecorderDialog' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'>
+ <widget name = 'List' />
+ <layout type = 'vertical' padding = '0, 0, 0, 0'>
+ <widget name = 'Thumbnail'
+ width = '180'
+ height = '170'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'NextScreenShotButton'
+ width = '25'
+ height = '25'
+ />
+ <widget name = 'currentScreenshot'
+ width = '125'
+ height = '25'
+ textalign = 'center'
+ />
+ <widget name = 'PreviousScreenShotButton'
+ width = '25'
+ height = '25'
+ />
+ </layout>
+ <widget name = 'Author' height = 'Globals.Line.Height' />
+ <widget name = 'Notes' height = 'Globals.Line.Height' />
+ </layout>
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Edit'
+ type = 'Button'
+ />
+ <widget name = 'Record'
+ type = 'Button'
+ />
+ <widget name = 'Playback'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'OnScreenDialog' overlays = 'screen_center'>
+ <layout type = 'horizontal' spacing = '5' padding = '5, 3, 5, 3' center = 'true'>
+ <widget name = 'StopButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'EditButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'SwitchModeButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'FastReplayButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'TimeLabel'
+ width = '50'
+ height = '30'
+ />
+ </layout>
+ </dialog>
+
+ <dialog name = 'EditRecordDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
+ <widget name = 'Title'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'AuthorLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'AuthorEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NameLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NameEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NotesLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NotesEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'OK'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen_center'>
<layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
<widget name = 'Title'
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index 8bb03dea17..802998df3c 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -37,6 +37,9 @@
<def var = 'ShowChooserPageDisplay' value = '0'/>
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
+ <def var = 'RecorderDialog.ExtInfo.Visible' value = '0'/>
+
+ <def var = 'OnScreenDialog.ShowPics' value = '0'/>
<def var = 'KeyMapper.Spacing' value = '5'/>
<def var = 'KeyMapper.LabelWidth' value = '80'/>
@@ -99,6 +102,12 @@
size = '32, 18'
padding = '0, 0, 1, 0'
/>
+ <widget name = 'EditRecordLabel'
+ size = '60, Globals.Line.Height'
+ />
+ <widget name = 'EditRecord'
+ size = '120, 15'
+ />
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
@@ -1013,6 +1022,101 @@
</layout>
</dialog>
+ <dialog name = 'RecorderDialog' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 4' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'List' />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'>
+ <widget name = 'Edit'
+ type = 'Button'
+ />
+ <space />
+ <widget name = 'Record'
+ type = 'Button'
+ />
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space />
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'Playback'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'OnScreenDialog' overlays = 'screen_center'>
+ <layout type = 'horizontal' spacing = '5' padding = '3, 2, 3, 2' center = 'true'>
+ <widget name = 'StopButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'EditButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'SwitchModeButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'FastReplayButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'TimeLabel'
+ width = '50'
+ height = '16'
+ />
+ </layout>
+ </dialog>
+
+ <dialog name = 'EditRecordDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'AuthorLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'AuthorEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NameLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NameEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NotesLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NotesEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'OK'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen'>
<layout type = 'vertical' padding = '8, 8, 8, 8'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index dbd84992e6..0f10003e94 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
Binary files differ
diff --git a/gui/themes/scummmodern/editbtn.bmp b/gui/themes/scummmodern/editbtn.bmp
new file mode 100644
index 0000000000..49eb4035b5
--- /dev/null
+++ b/gui/themes/scummmodern/editbtn.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/editbtn_small.bmp b/gui/themes/scummmodern/editbtn_small.bmp
new file mode 100644
index 0000000000..8a0357fc2e
--- /dev/null
+++ b/gui/themes/scummmodern/editbtn_small.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/fastreplay.bmp b/gui/themes/scummmodern/fastreplay.bmp
new file mode 100644
index 0000000000..35ad2b4444
--- /dev/null
+++ b/gui/themes/scummmodern/fastreplay.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/fastreplay_small.bmp b/gui/themes/scummmodern/fastreplay_small.bmp
new file mode 100644
index 0000000000..8ef004c3bf
--- /dev/null
+++ b/gui/themes/scummmodern/fastreplay_small.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx
index 4d449f50ec..1b3bcea0d6 100644
--- a/gui/themes/scummmodern/scummmodern_gfx.stx
+++ b/gui/themes/scummmodern/scummmodern_gfx.stx
@@ -103,6 +103,14 @@
<bitmap filename = 'delbtn.bmp'/>
<bitmap filename = 'list.bmp'/>
<bitmap filename = 'grid.bmp'/>
+ <bitmap filename = 'stopbtn.bmp'/>
+ <bitmap filename = 'editbtn.bmp'/>
+ <bitmap filename = 'switchbtn.bmp'/>
+ <bitmap filename = 'fastreplay.bmp'/>
+ <bitmap filename = 'stopbtn_small.bmp'/>
+ <bitmap filename = 'editbtn_small.bmp'/>
+ <bitmap filename = 'switchbtn_small.bmp'/>
+ <bitmap filename = 'fastreplay_small.bmp'/>
</bitmaps>
<fonts>
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index 49c13cf1b0..b760e15919 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -43,6 +43,9 @@
<def var = 'ShowChooserPageDisplay' value = '1'/>
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '1'/>
+ <def var = 'RecorderDialog.ExtInfo.Visible' value = '1'/>
+
+ <def var = 'OnScreenDialog.ShowPics' value = '1'/>
<def var = 'KeyMapper.Spacing' value = '10'/>
<def var = 'KeyMapper.LabelWidth' value = '100'/>
@@ -106,6 +109,13 @@
size = '15, 18'
padding = '0, 3, 4, 0'
/>
+
+ <widget name = 'EditRecordLabel'
+ size = '60, 25'
+ />
+ <widget name = 'EditRecord'
+ size = '220, 25'
+ />
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
@@ -1032,6 +1042,126 @@
</layout>
</dialog>
+ <dialog name = 'RecorderDialog' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 32' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 0, 16' spacing = '16'>
+ <widget name = 'List' />
+ <layout type = 'vertical' padding = '0, 0, 0, 0'>
+ <widget name = 'Thumbnail'
+ width = '180'
+ height = '170'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <widget name = 'NextScreenShotButton'
+ width = '25'
+ height = '25'
+ />
+ <widget name = 'currentScreenshot'
+ width = '125'
+ height = '25'
+ textalign = 'center'
+ />
+ <widget name = 'PreviousScreenShotButton'
+ width = '25'
+ height = '25'
+ />
+ </layout>
+ <widget name = 'Author' height = 'Globals.Line.Height' />
+ <widget name = 'Notes' height = 'Globals.Line.Height' />
+ </layout>
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0'>
+ <space/>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '16'/>
+ <widget name = 'Edit'
+ type = 'Button'
+ />
+ <widget name = 'Record'
+ type = 'Button'
+ />
+ <widget name = 'Playback'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'OnScreenDialog' overlays = 'screen_center'>
+ <layout type = 'horizontal' spacing = '5' padding = '5, 3, 5, 3' center = 'true'>
+ <widget name = 'StopButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'EditButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'SwitchModeButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'FastReplayButton'
+ width = '32'
+ height = '32'
+ />
+ <widget name = 'TimeLabel'
+ width = '50'
+ height = '30'
+ />
+ </layout>
+ </dialog>
+
+ <dialog name = 'EditRecordDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
+ <widget name = 'Title'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'AuthorLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'AuthorEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NameLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NameEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NotesLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NotesEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'OK'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen_center'>
<layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 9658402f82..cee1e4af2b 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -35,6 +35,9 @@
<def var = 'ShowChooserPageDisplay' value = '0'/>
<def var = 'SaveLoadChooser.ExtInfo.Visible' value = '0'/>
+ <def var = 'RecorderDialog.ExtInfo.Visible' value = '0'/>
+
+ <def var = 'OnScreenDialog.ShowPics' value = '1'/>
<def var = 'Predictive.Button.Width' value = '45' />
<def var = 'Predictive.Button.Height' value = '15' />
@@ -97,6 +100,12 @@
size = '32, 18'
padding = '0, 0, 2, 0'
/>
+ <widget name = 'EditRecordLabel'
+ size = '60, Globals.Line.Height'
+ />
+ <widget name = 'EditRecord'
+ size = '120, 15'
+ />
</globals>
<dialog name = 'Launcher' overlays = 'screen'>
@@ -1012,6 +1021,122 @@
</layout>
</dialog>
+ <dialog name = 'SavenameDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8'>
+ <widget name = 'DescriptionText'
+ width = '320'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'Description'
+ height = '19'
+ />
+ <layout type = 'horizontal' padding = '0, 0, 16, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <space size = '96'/>
+ <widget name = 'Ok'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'RecorderDialog' overlays = 'screen' inset = '8' shading = 'dim'>
+ <layout type = 'vertical' padding = '8, 8, 8, 4' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <widget name = 'List' />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'>
+ <widget name = 'Edit'
+ type = 'Button'
+ />
+ <space />
+ <widget name = 'Record'
+ type = 'Button'
+ />
+ </layout>
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'>
+ <widget name = 'Delete'
+ type = 'Button'
+ />
+ <space />
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'Playback'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
+ <dialog name = 'OnScreenDialog' overlays = 'screen_center'>
+ <layout type = 'horizontal' spacing = '5' padding = '3, 2, 3, 2' center = 'true'>
+ <widget name = 'StopButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'EditButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'SwitchModeButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'FastReplayButton'
+ width = '16'
+ height = '16'
+ />
+ <widget name = 'TimeLabel'
+ width = '50'
+ height = '16'
+ />
+ </layout>
+ </dialog>
+
+ <dialog name = 'EditRecordDialog' overlays = 'screen_center'>
+ <layout type = 'vertical' padding = '8, 8, 8, 8' center = 'true'>
+ <widget name = 'Title'
+ height = 'Globals.Line.Height'
+ />
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'AuthorLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'AuthorEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NameLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NameEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 10'>
+ <widget name = 'NotesLabel'
+ type = 'EditRecordLabel'
+ />
+ <widget name = 'NotesEdit'
+ type = 'EditRecord'
+ />
+ </layout>
+ <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 0'>
+ <widget name = 'Cancel'
+ type = 'Button'
+ />
+ <widget name = 'OK'
+ type = 'Button'
+ />
+ </layout>
+ </layout>
+ </dialog>
+
<dialog name = 'ScummHelp' overlays = 'screen' inset = '8'>
<layout type = 'vertical' padding = '8, 8, 8, 8'>
<widget name = 'Title'
diff --git a/gui/themes/scummmodern/stopbtn.bmp b/gui/themes/scummmodern/stopbtn.bmp
new file mode 100644
index 0000000000..3575956694
--- /dev/null
+++ b/gui/themes/scummmodern/stopbtn.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/stopbtn_small.bmp b/gui/themes/scummmodern/stopbtn_small.bmp
new file mode 100644
index 0000000000..ffd5025279
--- /dev/null
+++ b/gui/themes/scummmodern/stopbtn_small.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/switchbtn.bmp b/gui/themes/scummmodern/switchbtn.bmp
new file mode 100644
index 0000000000..6bafa4a998
--- /dev/null
+++ b/gui/themes/scummmodern/switchbtn.bmp
Binary files differ
diff --git a/gui/themes/scummmodern/switchbtn_small.bmp b/gui/themes/scummmodern/switchbtn_small.bmp
new file mode 100644
index 0000000000..929b128884
--- /dev/null
+++ b/gui/themes/scummmodern/switchbtn_small.bmp
Binary files differ
diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp
index 4b266e8194..3677f02e47 100644
--- a/gui/widgets/edittext.cpp
+++ b/gui/widgets/edittext.cpp
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "common/system.h"
#include "gui/widgets/edittext.h"
#include "gui/gui-manager.h"
@@ -79,8 +80,13 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
}
if (setCaretPos(i))
draw();
-}
+#ifdef TIZEN
+ // Display the virtual keypad to allow text entry. Samsung app-store testers expected
+ // the keypad to be displayed when clicking the filter edit control in the laucher gui.
+ g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
+#endif
+}
void EditTextWidget::drawWidget() {
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0, ThemeEngine::kWidgetBackgroundEditText);
diff --git a/ports.mk b/ports.mk
index 7a3bf0fabd..892d2d57c3 100644
--- a/ports.mk
+++ b/ports.mk
@@ -139,6 +139,10 @@ ifdef USE_FAAD
OSX_STATIC_LIBS += $(STATICLIBPATH)/lib/libfaad.a
endif
+ifdef USE_MPEG2
+OSX_STATIC_LIBS += $(STATICLIBPATH)/lib/libmpeg2.a
+endif
+
ifdef USE_ZLIB
OSX_ZLIB ?= $(STATICLIBPATH)/lib/libz.a
endif
diff --git a/test/common/hash-str.h b/test/common/hash-str.h
new file mode 100644
index 0000000000..0391e7167f
--- /dev/null
+++ b/test/common/hash-str.h
@@ -0,0 +1,164 @@
+#include <cxxtest/TestSuite.h>
+#include "common/hash-str.h"
+
+/**
+ * Test suite for common/hash-str.h
+ * We test a number of case sensitive/insensitive hash and compare functions
+ * using example strings and known hashes, trying to tackle
+ * as much edge cases as possible.
+ */
+class HashStrTestSuite : public CxxTest::TestSuite {
+
+ public:
+ void test_case_sensitive_string_equal_to() {
+
+ // Name says it all.
+ // This verifies that the function returns true
+ // for exactly the same string, false for the same
+ // string in mixed case and false for some edge cases
+ // with various spacings plus one character replaced
+ // by itself+128 (if there's some processing done after
+ // conversion to 7-bit ASCII this might yield funny results).
+
+ const Common::String lower("test");
+ const Common::String lower1("test");
+ const Common::String mixed("tESt");
+ const Common::String spaced("test ");
+ const Common::String doublespaced("test ");
+ const Common::String tabbed("test\t");
+ const Common::String plus128("t\345est");
+ // 'e'+128 = 0xE5 = 0o345
+
+ Common::CaseSensitiveString_EqualTo css_et;
+ TS_ASSERT_EQUALS(css_et(lower, mixed), false);
+ TS_ASSERT_EQUALS(css_et(lower, lower1), true);
+ TS_ASSERT_EQUALS(css_et(lower, lower), true);
+
+ // Different sorts of whitespace are to be treated differently.
+ TS_ASSERT_EQUALS(css_et(lower, spaced), false);
+ TS_ASSERT_EQUALS(css_et(lower, tabbed), false);
+ TS_ASSERT_EQUALS(css_et(spaced, tabbed), false);
+ TS_ASSERT_EQUALS(css_et(spaced, doublespaced), false);
+ TS_ASSERT_EQUALS(css_et(lower, plus128), false);
+ }
+
+ void test_ignore_case_equal_to() {
+
+ // This should be probably called case_insensitive_string_equal_to
+ // or something,but it's basically the same thing as
+ // test_case_sensitive_string_equal_to, only it's case
+ // insensitive.
+
+ const Common::String lower("test");
+ const Common::String lower1("test");
+ const Common::String mixed("tESt");
+ const Common::String spaced("test ");
+ const Common::String mixedspaced("tESt ");
+ const Common::String doublespaced("test ");
+ const Common::String tabbed("test\t");
+ const Common::String plus128("t\345est");
+
+ Common::IgnoreCase_EqualTo ic_et;
+ TS_ASSERT_EQUALS(ic_et(lower, mixed), true);
+ TS_ASSERT_EQUALS(ic_et(lower, lower1), true);
+ TS_ASSERT_EQUALS(ic_et(lower, lower), true);
+ // Edge case:
+ TS_ASSERT_EQUALS(ic_et(spaced, mixedspaced), true);
+
+ // Different sorts of whitespace are to be treated differently.
+ TS_ASSERT_EQUALS(ic_et(lower, spaced), false);
+ TS_ASSERT_EQUALS(ic_et(lower, tabbed), false);
+ TS_ASSERT_EQUALS(ic_et(spaced, tabbed), false);
+ TS_ASSERT_EQUALS(ic_et(spaced, doublespaced), false);
+ TS_ASSERT_EQUALS(ic_et(lower, plus128), false);
+ }
+
+ void test_case_sensitive_string_hash() {
+
+ // Here we compute string hashes for different
+ // strings and see that the functor is case sensitive
+ // and does not ignore spaces.
+
+ const Common::String lower("test");
+ const Common::String lower1("test");
+ const Common::String mixed("tESt");
+ const Common::String spaced("test ");
+ const Common::String mixedspaced("tESt ");
+ const Common::String doublespaced("test ");
+ const Common::String tabbed("test\t");
+
+ Common::CaseSensitiveString_Hash css_h;
+ TS_ASSERT_EQUALS(css_h(lower), css_h(lower1));
+ TS_ASSERT_DIFFERS(css_h(mixed), css_h(lower));
+ TS_ASSERT_DIFFERS(css_h(spaced), css_h(lower));
+ TS_ASSERT_DIFFERS(css_h(tabbed), css_h(spaced));
+ TS_ASSERT_DIFFERS(css_h(spaced), css_h(doublespaced));
+ }
+
+ void test_ignore_case_hash() {
+ // Same as test_case_sensitive_string_hash, but case insensitive.
+ const Common::String lower("test");
+ const Common::String lower1("test");
+ const Common::String mixed("tESt");
+ const Common::String spaced("test ");
+ const Common::String mixedspaced("tESt ");
+ const Common::String doublespaced("test ");
+ const Common::String tabbed("test\t");
+
+ Common::IgnoreCase_Hash ic_h;
+ TS_ASSERT_EQUALS(ic_h(lower), ic_h(lower1));
+ TS_ASSERT_EQUALS(ic_h(mixed), ic_h(lower));
+ TS_ASSERT_EQUALS(ic_h(spaced), ic_h(mixedspaced));
+ TS_ASSERT_DIFFERS(ic_h(tabbed), ic_h(lower));
+ TS_ASSERT_DIFFERS(ic_h(spaced), ic_h(doublespaced));
+ }
+
+ void test_cpp_string_hash()
+ {
+ // We run the same tests with Hash<String>,
+ // a template specialization of Hash, also a functor.
+ // It is supposed to be case sensitive.
+
+ const Common::String lower("test");
+ const Common::String lower1("test");
+ const Common::String mixed("tESt");
+ const Common::String spaced("test ");
+ const Common::String mixedspaced("tESt ");
+ const Common::String doublespaced("test ");
+ const Common::String tabbed("test\t");
+
+ Common::Hash<Common::String> h;
+ TS_ASSERT_EQUALS(h(lower), h(lower1));
+ TS_ASSERT_DIFFERS(h(mixed), h(lower));
+ TS_ASSERT_DIFFERS(h(spaced), h(lower));
+ TS_ASSERT_DIFFERS(h(tabbed), h(spaced));
+ TS_ASSERT_DIFFERS(h(spaced), h(doublespaced));
+ }
+
+ void test_c_style_string_hash()
+ {
+ // Same as test_cpp_string_hash but with Hash<const char*>,
+ // a template specialization of Hash, also a functor,
+ // that works with C-Style strings.
+ // It is supposed to be case sensitive.
+
+ char lower[] = "test";
+ char lower1[] = "test";
+ char mixed[] = "tESt";
+ char spaced[] = "test ";
+ char mixedspaced[] = "tESt ";
+ char doublespaced[] = "test ";
+ char tabbed[] = "test\t";
+
+ Common::Hash<const char *> h;
+ TS_ASSERT_EQUALS(h(lower), h(lower1));
+ TS_ASSERT_DIFFERS(h(mixed), h(lower));
+ TS_ASSERT_DIFFERS(h(spaced), h(lower));
+ TS_ASSERT_DIFFERS(h(spaced), h(mixedspaced));
+ TS_ASSERT_DIFFERS(h(tabbed), h(spaced));
+ TS_ASSERT_DIFFERS(h(spaced), h(doublespaced));
+
+ }
+
+
+};
diff --git a/test/common/huffman.h b/test/common/huffman.h
new file mode 100644
index 0000000000..53353aaa60
--- /dev/null
+++ b/test/common/huffman.h
@@ -0,0 +1,144 @@
+#include <cxxtest/TestSuite.h>
+#include "common/huffman.h"
+#include "common/bitstream.h"
+#include "common/memstream.h"
+
+/**
+* A test suite for the Huffman decoder in common/huffman.h
+* The encoding used comes from the example on the Wikipedia page
+* for Huffman.
+* TODO: It could be improved by generating one at runtime.
+*/
+class HuffmanTestSuite : public CxxTest::TestSuite {
+ public:
+ void test_get_with_full_symbols() {
+
+ /*
+ * The class can be initialized with or without providing
+ * a max_length and a symbol table.
+ * We test with a table.
+ *
+ * Encoding (arbitrary, for testing purpouses):
+ * 0xA=010
+ * 0xB=011
+ * 0xC=11
+ * 0xD=00
+ * 0xE=10
+ */
+
+ uint32 codeCount = 5;
+ uint8 maxLength = 3;
+ const uint8 lengths[] = {3,3,2,2,2};
+ const uint32 codes[] = {0x2, 0x3, 0x3, 0x0, 0x2};
+ const uint32 symbols[] = {0xA, 0xB, 0xC, 0xD, 0xE};
+
+ Common::Huffman h(maxLength, codeCount, codes, lengths, symbols);
+
+ byte input[] = {0x4F, 0x20};
+ // Provided input...
+ uint32 expected[] = {0xA, 0xB, 0xC, 0xD, 0xE, 0xD, 0xD};
+ // ..and expected output.
+
+ /*
+ * What should be going on:
+ * 010 011 11 00 10 00 00 = A B C D E D D
+ * = 0100 1111 0010 0000 = 0x4F20
+ */
+
+ Common::MemoryReadStream ms(input, sizeof(input));
+ Common::BitStream8MSB bs(ms);
+
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[0]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[1]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[2]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[3]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[4]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[5]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[6]);
+ }
+
+ void test_get_without_symbols() {
+
+ /*
+ * This is basically the same as test_get_with_full_symbols, but
+ * I only pass the minimal required arguments.
+ * Specifically, I avoid passing the symbols table, so that
+ * array indices are used instead.
+ *
+ * Encoding becomes:
+ *
+ * 0=010
+ * 1=011
+ * 2=11
+ * 3=00
+ * 4=10
+ */
+
+ uint32 codeCount = 5;
+ const uint8 lengths[] = {3,3,2,2,2};
+ const uint32 codes[] = {0x2, 0x3, 0x3, 0x0, 0x2};
+
+ Common::Huffman h(0, codeCount, codes, lengths, 0);
+
+ byte input[] = {0x4F, 0x20};
+ uint32 expected[] = {0, 1, 2, 3, 4, 3 ,3};
+
+ Common::MemoryReadStream ms(input, sizeof(input));
+ Common::BitStream8MSB bs(ms);
+
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[0]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[1]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[2]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[3]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[4]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[5]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[6]);
+ }
+
+ void test_get_after_set_symbols() {
+
+ /*
+ * Another variation of test_get_with_full_symbols.
+ * I use the setSymbols method to define, a posteriori,
+ * an alphabet to be used in place of array indices.
+ * The encoding is, at first,
+ * 0=010
+ * 1=011
+ * 2=11
+ * 3=00
+ * 4=10
+ * (=array indices).
+ */
+
+ uint32 codeCount = 5;
+ const uint8 lengths[] = {3,3,2,2,2};
+ const uint32 codes[] = {0x2, 0x3, 0x3, 0x0, 0x2};
+
+ Common::Huffman h(0, codeCount, codes, lengths, 0);
+
+ const uint32 symbols[] = {0xA, 0xB, 0xC, 0xD, 0xE};
+ h.setSymbols(symbols);
+
+ byte input[] = {0x4F, 0x20};
+ uint32 expected[] = {0xA, 0xB, 0xC, 0xD, 0xE, 0xD, 0xD};
+
+ Common::MemoryReadStream ms(input, sizeof(input));
+ Common::BitStream8MSB bs(ms);
+
+ /* New symbols:
+ * A=010
+ * B=011
+ * C=11
+ * D=00
+ * E=10
+ */
+
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[0]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[1]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[2]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[3]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[4]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[5]);
+ TS_ASSERT_EQUALS(h.getSymbol(bs), expected[6]);
+ }
+};
diff --git a/test/common/rendermode.h b/test/common/rendermode.h
new file mode 100644
index 0000000000..e5e277f16b
--- /dev/null
+++ b/test/common/rendermode.h
@@ -0,0 +1,84 @@
+#include <cxxtest/TestSuite.h>
+#include "common/rendermode.h"
+#include "common/gui_options.h"
+#include "common/str.h"
+
+class RenderModeTestSuite : public CxxTest::TestSuite {
+ public:
+ void test_parse_render_mode_good() {
+ /*
+ * Tests for parseRenderMode.
+ * It takes a code (case-insensitive) and spits a RenderMode back at you.
+ * These cases should work - the inputs are standard, there's just some
+ * fun with caps being had in here.
+ */
+ TS_ASSERT_EQUALS(Common::parseRenderMode("fMTOwNs"), Common::kRenderFMTowns);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("hercGrEen"), Common::kRenderHercG);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("hercAmbeR"), Common::kRenderHercA);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("CgA"), Common::kRenderCGA);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("ega"), Common::kRenderEGA);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("Vga"), Common::kRenderVGA);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("AmigA"), Common::kRenderAmiga);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("pc9821"), Common::kRenderPC9821);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("PC9801"), Common::kRenderPC9801);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("0"), Common::kRenderDefault);
+ }
+
+
+ void test_parse_render_mode_bad() {
+ /*
+ * These cases, according to the specification, should return the default.
+ * It is only mentioned that the function must be case insensitive.
+ * Whitespaces, in particular, should not be automatically trimmed.
+ */
+ TS_ASSERT_EQUALS(Common::parseRenderMode("fmtowns "), Common::kRenderDefault);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("FM-TOWNS "), Common::kRenderDefault);
+ TS_ASSERT_EQUALS(Common::parseRenderMode(" cga"), Common::kRenderDefault);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("\tC g A"), Common::kRenderDefault);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("\t"), Common::kRenderDefault);
+ // This is the only interesting bit: if the function was really, really
+ // broken it could be tempted to test for +-0x20.
+ TS_ASSERT_EQUALS(Common::parseRenderMode("pc Y8 21 "), Common::kRenderDefault);
+ TS_ASSERT_EQUALS(Common::parseRenderMode(" PC\t9801 "), Common::kRenderDefault);
+ TS_ASSERT_EQUALS(Common::parseRenderMode("0"), Common::kRenderDefault);
+ }
+
+ void test_get_render_mode_code_back_and_forth() {
+ /*
+ * What does getRenderModeCode return?
+ * Notably, the output should not be in mixed case.
+ */
+ TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("FMTOWNS")), "fmtowns", 7);
+ TS_ASSERT_DIFFERS(Common::getRenderModeCode(Common::parseRenderMode("FMTOWNS")), "fmtowns");
+ TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("CGA")), "cga", 3);
+ TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("vga")), "vga", 3);
+ TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("Ega")), "ega", 3);
+ TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("AmiGa")), "amiga", 5);
+ TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("PC9821")), "pc9821", 6);
+ TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("PC9801")), "pc9801", 6);
+ // Slightly more interesting:
+ // Make sure that we get a null pointer for 0 (and not the "0" string or stuff)
+ char *null_p = 0;
+ TS_ASSERT_EQUALS(Common::getRenderModeCode(Common::kRenderDefault), null_p);
+ }
+
+ void test_render_2_guio() {
+ /*
+ * Verify that a rendermode is taken and the corresponding
+ * GUIO_xxxxx is returned.
+ */
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderHercG), GUIO_RENDERHERCGREEN);
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderHercA), GUIO_RENDERHERCAMBER);
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderCGA), GUIO_RENDERCGA);
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderEGA), GUIO_RENDEREGA);
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderVGA), GUIO_RENDERVGA);
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderAmiga), GUIO_RENDERAMIGA);
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderFMTowns), GUIO_RENDERFMTOWNS);
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderPC9821), GUIO_RENDERPC9821);
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderPC9801), GUIO_RENDERPC9801);
+ // renderMode2GUIO is supposed to return an empty string
+ // if given kRenderDefault as an argument
+ Common::String empty;
+ TS_ASSERT_EQUALS(Common::renderMode2GUIO(Common::kRenderDefault), empty);
+ }
+};
diff --git a/test/common/str.h b/test/common/str.h
index 2c563f3132..adc6a099e4 100644
--- a/test/common/str.h
+++ b/test/common/str.h
@@ -243,6 +243,14 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT_EQUALS(str, "012345678923456789012345678901");
}
+ void test_erase() {
+ Common::String str("01234567890123456789012345678901");
+ str.erase(18);
+ TS_ASSERT_EQUALS(str, "012345678901234567");
+ str.erase(7, 5);
+ TS_ASSERT_EQUALS(str, "0123456234567");
+ }
+
void test_sharing() {
Common::String str("01234567890123456789012345678901");
Common::String str2(str);
diff --git a/test/common/util.h b/test/common/util.h
new file mode 100644
index 0000000000..cd65307612
--- /dev/null
+++ b/test/common/util.h
@@ -0,0 +1,237 @@
+#include <cxxtest/TestSuite.h>
+#include "common/util.h"
+
+/**
+ * Test suite for the functions in common/util.h
+ */
+class UtilTestSuite : public CxxTest::TestSuite {
+ public:
+ void test_parsebool_yesno() {
+
+ // First test for the parseBool function.
+ // These are the mixed case yes/no cases that must work
+
+ bool valasbool;
+ bool success;
+
+ Common::String string_1("Yes");
+ success = Common::parseBool(string_1, valasbool);
+ TS_ASSERT_EQUALS(success, 1);
+ TS_ASSERT_EQUALS(valasbool, 1);
+
+ Common::String string_2("nO");
+ success = Common::parseBool(string_2, valasbool);
+ TS_ASSERT_EQUALS(success, 1);
+ TS_ASSERT_EQUALS(valasbool, 0);
+ }
+
+ void test_parsebool_truefalse() {
+
+ // First test for the parseBool function.
+ // These are the mixed case true/false cases that must work
+
+ bool valasbool;
+ bool success;
+
+ Common::String string_3("tRuE");
+ success = Common::parseBool(string_3, valasbool);
+ TS_ASSERT_EQUALS(success, 1);
+ TS_ASSERT_EQUALS(valasbool, 1);
+
+ Common::String string_4("fAlSe");
+ success = Common::parseBool(string_4, valasbool);
+ TS_ASSERT_EQUALS(success, 1);
+ TS_ASSERT_EQUALS(valasbool, 0);
+ }
+
+ void test_parsebool_onezero() {
+
+ // Third test for the parseBool function.
+ // These are the 1/0 cases that must work.
+ // Note that while 'a-z'+0x20 must work just fine,
+ // '0-1'+0x20 should NOT; this is addressed in
+ // parsebool_bad
+
+ bool valasbool;
+ bool success;
+
+ Common::String string_5("1");
+ success = Common::parseBool(string_5, valasbool);
+ TS_ASSERT_EQUALS(success, 1);
+ TS_ASSERT_EQUALS(valasbool, 1);
+
+ Common::String string_6("0");
+ success = Common::parseBool(string_6, valasbool);
+ TS_ASSERT_EQUALS(success, 1);
+ TS_ASSERT_EQUALS(valasbool, 0);
+
+ }
+
+ void test_parsebool_bad() {
+
+ bool valasbool;
+ bool success;
+
+ // Bad cases that should not return success #1:
+ // Random string
+ Common::String string_1("u_f1ght_l1k3_a_c0w");
+ success = Common::parseBool(string_1, valasbool);
+ TS_ASSERT_EQUALS(success, 0);
+
+ // Bad cases that should not return success #2, #3:
+ // The function should NOT accept trailing whitespaces:
+ Common::String string_2(" yes");
+ success = Common::parseBool(string_2, valasbool);
+ TS_ASSERT_EQUALS(success, 0);
+
+ Common::String string_3("yes ");
+ success = Common::parseBool(string_3, valasbool);
+ TS_ASSERT_EQUALS(success, 0);
+
+ // While 'a-z'+0x20 must work just fine,
+ // '0-1'+0x20 should NOT. '2' is not good either.
+
+ Common::String string_4("\x50");
+ success = Common::parseBool(string_4, valasbool);
+ TS_ASSERT_EQUALS(success, 0);
+
+ Common::String string_5("\x51");
+ success = Common::parseBool(string_5, valasbool);
+ TS_ASSERT_EQUALS(success, 0);
+
+ Common::String string_6("2");
+ success = Common::parseBool(string_6, valasbool);
+ TS_ASSERT_EQUALS(success, 0);
+ }
+
+ void test_is_al_num() {
+
+ // Test the isAlnum function
+ // Should return true if and only if the input is an alphanumeric char
+
+ TS_ASSERT_EQUALS(Common::isAlnum('a'), 1);
+ TS_ASSERT_EQUALS(Common::isAlnum('A'), 1);
+ TS_ASSERT_EQUALS(Common::isAlnum('z'), 1);
+ TS_ASSERT_EQUALS(Common::isAlnum('Z'), 1);
+ TS_ASSERT_EQUALS(Common::isAlnum('1'), 1);
+ TS_ASSERT_EQUALS(Common::isAlnum('0'), 1);
+ TS_ASSERT_EQUALS(Common::isAlnum('§'), 0);
+ TS_ASSERT_EQUALS(Common::isAlnum('$'), 0);
+ TS_ASSERT_EQUALS(Common::isAlnum(' '), 0);
+ TS_ASSERT_EQUALS(Common::isAlnum('\n'), 0);
+ TS_ASSERT_EQUALS(Common::isAlnum('\b'), 0);
+ TS_ASSERT_EQUALS(Common::isAlnum(0), 0);
+ TS_ASSERT_EQUALS(Common::isAlnum(255), 0);
+
+ }
+
+ void test_is_alpha() {
+
+ // Test the isAlpha function
+ // Should return true if and only if the input is an alphanumeric char
+
+ TS_ASSERT_EQUALS(Common::isAlpha('a'), 1);
+ TS_ASSERT_EQUALS(Common::isAlpha('A'), 1);
+ TS_ASSERT_EQUALS(Common::isAlpha('z'), 1);
+ TS_ASSERT_EQUALS(Common::isAlpha('Z'), 1);
+ TS_ASSERT_EQUALS(Common::isAlpha('1'), 0);
+ TS_ASSERT_EQUALS(Common::isAlpha('0'), 0);
+ TS_ASSERT_EQUALS(Common::isAlpha('§'), 0);
+ TS_ASSERT_EQUALS(Common::isAlpha('$'), 0);
+ TS_ASSERT_EQUALS(Common::isAlpha(' '), 0);
+ TS_ASSERT_EQUALS(Common::isAlpha('\n'), 0);
+ TS_ASSERT_EQUALS(Common::isAlpha('\b'), 0);
+ TS_ASSERT_EQUALS(Common::isAlpha(0), 0);
+ TS_ASSERT_EQUALS(Common::isAlpha(255), 0);
+
+ }
+
+ void test_is_digit() {
+
+ // Test the isDigit function
+ // Should return true if and only if the input is a single digit
+
+ TS_ASSERT_EQUALS(Common::isDigit('a'), 0);
+ TS_ASSERT_EQUALS(Common::isDigit('A'), 0);
+ TS_ASSERT_EQUALS(Common::isDigit('z'), 0);
+ TS_ASSERT_EQUALS(Common::isDigit('Z'), 0);
+ TS_ASSERT_EQUALS(Common::isDigit('1'), 1);
+ TS_ASSERT_EQUALS(Common::isDigit('0'), 1);
+ TS_ASSERT_EQUALS(Common::isDigit('§'), 0);
+ TS_ASSERT_EQUALS(Common::isDigit('$'), 0);
+ TS_ASSERT_EQUALS(Common::isDigit(' '), 0);
+ TS_ASSERT_EQUALS(Common::isDigit('\n'), 0);
+ TS_ASSERT_EQUALS(Common::isDigit('\b'), 0);
+ TS_ASSERT_EQUALS(Common::isDigit(0), 0);
+ TS_ASSERT_EQUALS(Common::isDigit(255), 0);
+
+ }
+
+ void test_is_lower() {
+
+ // Test the isLower function
+ // Should return true if and only if the input is a lowercase char
+
+ TS_ASSERT_EQUALS(Common::isLower('a'), 1);
+ TS_ASSERT_EQUALS(Common::isLower('A'), 0);
+ TS_ASSERT_EQUALS(Common::isLower('z'), 1);
+ TS_ASSERT_EQUALS(Common::isLower('Z'), 0);
+ TS_ASSERT_EQUALS(Common::isLower('1'), 0);
+ TS_ASSERT_EQUALS(Common::isLower('0'), 0);
+ TS_ASSERT_EQUALS(Common::isLower('§'), 0);
+ TS_ASSERT_EQUALS(Common::isLower('$'), 0);
+ TS_ASSERT_EQUALS(Common::isLower(' '), 0);
+ TS_ASSERT_EQUALS(Common::isLower('\n'), 0);
+ TS_ASSERT_EQUALS(Common::isLower('\b'), 0);
+ TS_ASSERT_EQUALS(Common::isLower(0), 0);
+ TS_ASSERT_EQUALS(Common::isLower(255), 0);
+
+ }
+
+
+ void test_is_upper() {
+
+ // Test the isUpper function
+ // Should return true if and only if the input is an uppercase char
+
+ TS_ASSERT_EQUALS(Common::isUpper('a'), 0);
+ TS_ASSERT_EQUALS(Common::isUpper('A'), 1);
+ TS_ASSERT_EQUALS(Common::isUpper('z'), 0);
+ TS_ASSERT_EQUALS(Common::isUpper('Z'), 1);
+ TS_ASSERT_EQUALS(Common::isUpper('1'), 0);
+ TS_ASSERT_EQUALS(Common::isUpper('0'), 0);
+ TS_ASSERT_EQUALS(Common::isUpper('§'), 0);
+ TS_ASSERT_EQUALS(Common::isUpper('$'), 0);
+ TS_ASSERT_EQUALS(Common::isUpper(' '), 0);
+ TS_ASSERT_EQUALS(Common::isUpper('\n'), 0);
+ TS_ASSERT_EQUALS(Common::isUpper('\b'), 0);
+ TS_ASSERT_EQUALS(Common::isUpper(0), 0);
+ TS_ASSERT_EQUALS(Common::isUpper(255), 0);
+
+ }
+ void test_is_space() {
+ // isSpace should return true iff the character is some kind of whitespace
+ // or tab character
+ for (int c = 0; c < 255; c++) {
+ if (c == ' ' || c == '\t' ||
+ c == '\r' || c == '\n' ||
+ c == '\v' || c == '\f') {
+ TS_ASSERT_EQUALS(Common::isSpace(c), 1);
+ } else {
+ TS_ASSERT_EQUALS(Common::isSpace(c), 0);
+ }
+ }
+ }
+
+ void test_is_print() {
+ // isPrint should return true iff the input is a printable ascii char.
+ // That is to say, 0x20 to 0x7E.
+ for (int c = 0; c < 255; c++) {
+ if (c >= 0x20 && c <= 0x7E) {
+ TS_ASSERT_EQUALS(Common::isPrint(c), 1);
+ } else {
+ TS_ASSERT_EQUALS(Common::isPrint(c), 0);
+ }
+ }
+ }
+};
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index 6fe9c773b8..ff728a8437 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -36,6 +36,7 @@
// Video Codecs
#include "video/codecs/cinepak.h"
#include "video/codecs/indeo3.h"
+#include "video/codecs/mpeg.h"
#include "video/codecs/msvideo1.h"
#include "video/codecs/msrle.h"
#include "video/codecs/truemotion1.h"
@@ -64,8 +65,8 @@ namespace Video {
#define ID_VEDT MKTAG('v','e','d','t')
#define ID_IDX1 MKTAG('i','d','x','1')
#define ID_STRD MKTAG('s','t','r','d')
-#define ID_00AM MKTAG('0','0','A','M')
//#define ID_INFO MKTAG('I','N','F','O')
+#define ID_ISFT MKTAG('I','S','F','T')
// Codec tags
#define ID_RLE MKTAG('R','L','E',' ')
@@ -75,6 +76,7 @@ namespace Video {
#define ID_CVID MKTAG('c','v','i','d')
#define ID_IV32 MKTAG('i','v','3','2')
#define ID_DUCK MKTAG('D','U','C','K')
+#define ID_MPG2 MKTAG('m','p','g','2')
static byte char2num(char c) {
c = tolower((byte)c);
@@ -89,17 +91,27 @@ static uint16 getStreamType(uint32 tag) {
return tag & 0xffff;
}
-AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _soundType(soundType) {
- _decodedHeader = false;
- _fileStream = 0;
- memset(&_ixInfo, 0, sizeof(_ixInfo));
- memset(&_header, 0, sizeof(_header));
+AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _frameRateOverride(0), _soundType(soundType) {
+ initCommon();
+}
+
+AVIDecoder::AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType)
+ : _frameRateOverride(frameRateOverride), _soundType(soundType) {
+ initCommon();
}
AVIDecoder::~AVIDecoder() {
close();
}
+void AVIDecoder::initCommon() {
+ _decodedHeader = false;
+ _foundMovieList = false;
+ _fileStream = 0;
+ memset(&_ixInfo, 0, sizeof(_ixInfo));
+ memset(&_header, 0, sizeof(_header));
+}
+
void AVIDecoder::runHandle(uint32 tag) {
assert(_fileStream);
if (_fileStream->eos())
@@ -137,6 +149,7 @@ void AVIDecoder::runHandle(uint32 tag) {
case ID_STRD: // Extra stream info, safe to ignore
case ID_VEDT: // Unknown, safe to ignore
case ID_JUNK: // Alignment bytes, should be ignored
+ case ID_ISFT: // Metadata, safe to ignore
{
uint32 junkSize = _fileStream->readUint32LE();
_fileStream->skip(junkSize + (junkSize & 1)); // Alignment
@@ -165,6 +178,13 @@ void AVIDecoder::handleList() {
debug(0, "Found LIST of type %s", tag2str(listType));
+ if (listType == ID_MOVI) {
+ // Found the 'movi' list
+ // We're done parsing everything
+ _foundMovieList = true;
+ return;
+ }
+
while ((_fileStream->pos() - curPos) < listSize)
runHandle(_fileStream->readUint32BE());
@@ -203,6 +223,11 @@ void AVIDecoder::handleStreamHeader() {
uint32 startPos = _fileStream->pos();
if (sHeader.streamType == ID_VIDS) {
+ if (_frameRateOverride != 0) {
+ sHeader.rate = _frameRateOverride.getNumerator();
+ sHeader.scale = _frameRateOverride.getDenominator();
+ }
+
BitmapInfoHeader bmInfo;
bmInfo.size = _fileStream->readUint32LE();
bmInfo.width = _fileStream->readUint32LE();
@@ -263,26 +288,24 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
_fileStream = stream;
_decodedHeader = false;
+ _foundMovieList = false;
// Read chunks until we have decoded the header
- while (!_decodedHeader)
+ while (!_decodedHeader && _fileStream->pos() < _fileStream->size())
runHandle(_fileStream->readUint32BE());
- uint32 nextTag = _fileStream->readUint32BE();
-
- // Throw out any JUNK section
- if (nextTag == ID_JUNK) {
- runHandle(ID_JUNK);
- nextTag = _fileStream->readUint32BE();
+ if (_fileStream->pos() >= _fileStream->size()) {
+ warning("Failed to find AVI header");
+ return false;
}
- // Ignore the 'movi' LIST
- if (nextTag == ID_LIST) {
- _fileStream->readUint32BE(); // Skip size
- if (_fileStream->readUint32BE() != ID_MOVI)
- error("Expected 'movi' LIST");
- } else {
- error("Expected 'movi' LIST");
+ // Then read until we find the movie list
+ while (!_foundMovieList && _fileStream->pos() < _fileStream->size())
+ runHandle(_fileStream->readUint32BE());
+
+ if (_fileStream->pos() >= _fileStream->size()) {
+ warning("Failed to find AVI 'movi' LIST");
+ return false;
}
return true;
@@ -294,6 +317,7 @@ void AVIDecoder::close() {
delete _fileStream;
_fileStream = 0;
_decodedHeader = false;
+ _foundMovieList = false;
delete[] _ixInfo.indices;
memset(&_ixInfo, 0, sizeof(_ixInfo));
@@ -428,6 +452,10 @@ Codec *AVIDecoder::AVIVideoTrack::createCodec() {
case ID_DUCK:
return new TrueMotion1Decoder(_bmInfo.width, _bmInfo.height);
#endif
+#ifdef USE_MPEG2
+ case ID_MPG2:
+ return new MPEGDecoder();
+#endif
default:
warning("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler));
}
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 34a67f4c28..6082232464 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -52,10 +52,13 @@ class Codec;
*
* Video decoder used in engines:
* - sci
+ * - sword1
+ * - sword2
*/
class AVIDecoder : public VideoDecoder {
public:
AVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
+ AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
virtual ~AVIDecoder();
bool loadStream(Common::SeekableReadStream *stream);
@@ -219,9 +222,11 @@ private:
AVIHeader _header;
Common::SeekableReadStream *_fileStream;
- bool _decodedHeader;
+ bool _decodedHeader, _foundMovieList;
Audio::Mixer::SoundType _soundType;
+ Common::Rational _frameRateOverride;
+ void initCommon();
void runHandle(uint32 tag);
void handleList();
diff --git a/video/codecs/codec.h b/video/codecs/codec.h
index c1194e461b..a4ad786bb0 100644
--- a/video/codecs/codec.h
+++ b/video/codecs/codec.h
@@ -51,7 +51,7 @@ public:
* containing the decoded frame.
*
* @return a pointer to the decoded frame
- * @note stream is not deleted
+ * @note stream is not deleted
*/
virtual const Graphics::Surface *decodeImage(Common::SeekableReadStream *stream) = 0;
diff --git a/video/codecs/indeo3.cpp b/video/codecs/indeo3.cpp
index 7bf7fc8235..28e1a9c620 100644
--- a/video/codecs/indeo3.cpp
+++ b/video/codecs/indeo3.cpp
@@ -32,8 +32,9 @@
#include "common/endian.h"
#include "common/stream.h"
#include "common/textconsole.h"
+#include "common/util.h"
-#include "graphics/conversion.h"
+#include "graphics/yuv_to_rgb.h"
#include "video/codecs/indeo3.h"
@@ -260,91 +261,61 @@ const Graphics::Surface *Indeo3Decoder::decodeImage(Common::SeekableReadStream *
delete[] inData;
- // Blit the frame onto the surface
const byte *srcY = _cur_frame->Ybuf;
const byte *srcU = _cur_frame->Ubuf;
const byte *srcV = _cur_frame->Vbuf;
- byte *dest = (byte *)_surface->pixels;
-
- const byte *srcUP = srcU;
- const byte *srcVP = srcV;
- const byte *srcUN = srcU + chromaWidth;
- const byte *srcVN = srcV + chromaWidth;
-
- uint32 scaleWidth = _surface->w / fWidth;
- uint32 scaleHeight = _surface->h / fHeight;
- for (uint32 y = 0; y < fHeight; y++) {
- byte *rowDest = dest;
-
- for (uint32 sH = 0; sH < scaleHeight; sH++) {
- for (uint32 x = 0; x < fWidth; x++) {
- uint32 xP = MAX<int32>((x >> 2) - 1, 0);
- uint32 xN = MIN<int32>((x >> 2) + 1, chromaWidth - 1);
-
- byte cY = srcY[x];
- byte cU = srcU[x >> 2];
- byte cV = srcV[x >> 2];
-
- if (((x % 4) == 0) && ((y % 4) == 0)) {
- cU = (((uint32) cU) + ((uint32) srcUP[xP])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVP[xP])) / 2;
- } else if (((x % 4) == 3) && ((y % 4) == 0)) {
- cU = (((uint32) cU) + ((uint32) srcUP[xN])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVP[xN])) / 2;
- } else if (((x % 4) == 0) && ((y % 4) == 3)) {
- cU = (((uint32) cU) + ((uint32) srcUN[xP])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVN[xP])) / 2;
- } else if (((x % 4) == 3) && ((y % 4) == 3)) {
- cU = (((uint32) cU) + ((uint32) srcUN[xN])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVN[xN])) / 2;
- } else if ( (x % 4) == 0) {
- cU = (((uint32) cU) + ((uint32) srcU[xP])) / 2;
- cV = (((uint32) cV) + ((uint32) srcV[xP])) / 2;
- } else if ( (x % 4) == 3) {
- cU = (((uint32) cU) + ((uint32) srcU[xN])) / 2;
- cV = (((uint32) cV) + ((uint32) srcV[xN])) / 2;
- } else if ( (y % 4) == 0) {
- cU = (((uint32) cU) + ((uint32) srcUP[x >> 2])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVP[x >> 2])) / 2;
- } else if ( (y % 4) == 3) {
- cU = (((uint32) cU) + ((uint32) srcUN[x >> 2])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVN[x >> 2])) / 2;
- }
+ // Create buffers for U/V with an extra row/column copied from the second-to-last
+ // row/column.
+ byte *tempU = new byte[(chromaWidth + 1) * (chromaHeight + 1)];
+ byte *tempV = new byte[(chromaWidth + 1) * (chromaHeight + 1)];
- byte r = 0, g = 0, b = 0;
- Graphics::YUV2RGB(cY, cU, cV, r, g, b);
+ for (uint i = 0; i < chromaHeight; i++) {
+ memcpy(tempU + (chromaWidth + 1) * i, srcU + chromaWidth * i, chromaWidth);
+ memcpy(tempV + (chromaWidth + 1) * i, srcV + chromaWidth * i, chromaWidth);
+ tempU[(chromaWidth + 1) * i + chromaWidth] = srcU[chromaWidth * (i + 1) - 1];
+ tempV[(chromaWidth + 1) * i + chromaWidth] = srcV[chromaWidth * (i + 1) - 1];
+ }
- const uint32 color = _pixelFormat.RGBToColor(r, g, b);
+ memcpy(tempU + (chromaWidth + 1) * chromaHeight, tempU + (chromaWidth + 1) * (chromaHeight - 1),
+ chromaWidth + 1);
+ memcpy(tempV + (chromaWidth + 1) * chromaHeight, tempV + (chromaWidth + 1) * (chromaHeight - 1),
+ chromaWidth + 1);
- for (uint32 sW = 0; sW < scaleWidth; sW++, rowDest += _surface->format.bytesPerPixel) {
- if (_surface->format.bytesPerPixel == 1)
- *((uint8 *)rowDest) = (uint8)color;
- else if (_surface->format.bytesPerPixel == 2)
- *((uint16 *)rowDest) = (uint16)color;
- }
- }
+ // Blit the frame onto the surface
+ uint32 scaleWidth = _surface->w / fWidth;
+ uint32 scaleHeight = _surface->h / fHeight;
- dest += _surface->pitch;
+ if (scaleWidth == 1 && scaleHeight == 1) {
+ // Shortcut: Don't need to scale so we can decode straight to the surface
+ YUVToRGBMan.convert410(_surface, Graphics::YUVToRGBManager::kScaleITU, srcY, tempU, tempV,
+ fWidth, fHeight, fWidth, chromaWidth + 1);
+ } else {
+ // Need to upscale, so decode to a temp surface first
+ Graphics::Surface tempSurface;
+ tempSurface.create(fWidth, fHeight, _surface->format);
+
+ YUVToRGBMan.convert410(&tempSurface, Graphics::YUVToRGBManager::kScaleITU, srcY, tempU, tempV,
+ fWidth, fHeight, fWidth, chromaWidth + 1);
+
+ // Upscale
+ for (int y = 0; y < _surface->h; y++) {
+ for (int x = 0; x < _surface->w; x++) {
+ if (_surface->format.bytesPerPixel == 1)
+ *((byte *)_surface->getBasePtr(x, y)) = *((byte *)tempSurface.getBasePtr(x / scaleWidth, y / scaleHeight));
+ else if (_surface->format.bytesPerPixel == 2)
+ *((uint16 *)_surface->getBasePtr(x, y)) = *((uint16 *)tempSurface.getBasePtr(x / scaleWidth, y / scaleHeight));
+ else if (_surface->format.bytesPerPixel == 4)
+ *((uint32 *)_surface->getBasePtr(x, y)) = *((uint32 *)tempSurface.getBasePtr(x / scaleWidth, y / scaleHeight));
+ }
}
- srcY += fWidth;
-
- if ((y & 3) == 3) {
- srcU += chromaWidth;
- srcV += chromaWidth;
-
- if (y > 0) {
- srcUP += chromaWidth;
- srcVP += chromaWidth;
- }
- if (y < (fHeight - 4U)) {
- srcUN += chromaWidth;
- srcVN += chromaWidth;
- }
- }
+ tempSurface.free();
}
+ delete[] tempU;
+ delete[] tempV;
+
return _surface;
}
diff --git a/video/codecs/mpeg.cpp b/video/codecs/mpeg.cpp
new file mode 100644
index 0000000000..4540b4182e
--- /dev/null
+++ b/video/codecs/mpeg.cpp
@@ -0,0 +1,107 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/debug.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "graphics/surface.h"
+#include "graphics/yuv_to_rgb.h"
+
+#include "video/codecs/mpeg.h"
+
+namespace Video {
+
+MPEGDecoder::MPEGDecoder() : Codec() {
+ _pixelFormat = g_system->getScreenFormat();
+ _surface = 0;
+
+ _mpegDecoder = mpeg2_init();
+
+ if (!_mpegDecoder)
+ error("Could not initialize libmpeg2");
+
+ _mpegInfo = mpeg2_info(_mpegDecoder);
+}
+
+MPEGDecoder::~MPEGDecoder() {
+ mpeg2_close(_mpegDecoder);
+
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ }
+}
+
+const Graphics::Surface *MPEGDecoder::decodeImage(Common::SeekableReadStream *stream) {
+ uint32 framePeriod;
+ decodePacket(stream, framePeriod);
+ return _surface;
+}
+
+bool MPEGDecoder::decodePacket(Common::SeekableReadStream *packet, uint32 &framePeriod, Graphics::Surface *dst) {
+ // Decode as much as we can out of this packet
+ uint32 size = 0xFFFFFFFF;
+ mpeg2_state_t state;
+ bool foundFrame = false;
+ framePeriod = 0;
+
+ do {
+ state = mpeg2_parse(_mpegDecoder);
+
+ switch (state) {
+ case STATE_BUFFER:
+ size = packet->read(_buffer, BUFFER_SIZE);
+ mpeg2_buffer(_mpegDecoder, _buffer, _buffer + size);
+ break;
+ case STATE_SLICE:
+ case STATE_END:
+ if (_mpegInfo->display_fbuf) {
+ foundFrame = true;
+ const mpeg2_sequence_t *sequence = _mpegInfo->sequence;
+
+ framePeriod += sequence->frame_period;
+
+ if (!dst) {
+ // If no destination is specified, use our internal storage
+ if (!_surface) {
+ _surface = new Graphics::Surface();
+ _surface->create(sequence->picture_width, sequence->picture_height, _pixelFormat);
+ }
+
+ dst = _surface;
+ }
+
+ YUVToRGBMan.convert420(dst, Graphics::YUVToRGBManager::kScaleITU, _mpegInfo->display_fbuf->buf[0],
+ _mpegInfo->display_fbuf->buf[1], _mpegInfo->display_fbuf->buf[2], sequence->picture_width,
+ sequence->picture_height, sequence->width, sequence->chroma_width);
+ }
+ break;
+ default:
+ break;
+ }
+ } while (size != 0);
+
+ return foundFrame;
+}
+
+} // End of namespace Video
diff --git a/video/codecs/mpeg.h b/video/codecs/mpeg.h
new file mode 100644
index 0000000000..0082844537
--- /dev/null
+++ b/video/codecs/mpeg.h
@@ -0,0 +1,98 @@
+/* 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.
+ *
+ */
+
+#ifdef USE_MPEG2
+
+#ifndef VIDEO_CODECS_MPEG_H
+#define VIDEO_CODECS_MPEG_H
+
+#include "video/codecs/codec.h"
+#include "graphics/pixelformat.h"
+
+#if defined(__PLAYSTATION2__)
+ typedef uint8 uint8_t;
+ typedef uint16 uint16_t;
+ typedef uint32 uint32_t;
+#elif defined(_WIN32_WCE)
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+#elif defined(_MSC_VER)
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ #if !defined(SDL_COMPILEDVERSION) || (SDL_COMPILEDVERSION < 1210)
+ typedef signed long int32_t;
+ typedef unsigned long uint32_t;
+ #endif
+#else
+# include <inttypes.h>
+#endif
+
+extern "C" {
+ #include <mpeg2dec/mpeg2.h>
+}
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace Video {
+
+// MPEG 1/2 video decoder
+
+class MPEGDecoder : public Codec {
+public:
+ MPEGDecoder();
+ ~MPEGDecoder();
+
+ // Codec interface
+ const Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
+ Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+ // MPEGPSDecoder call
+ bool decodePacket(Common::SeekableReadStream *packet, uint32 &framePeriod, Graphics::Surface *dst = 0);
+
+private:
+ Graphics::PixelFormat _pixelFormat;
+ Graphics::Surface *_surface;
+
+ enum {
+ BUFFER_SIZE = 4096
+ };
+
+ byte _buffer[BUFFER_SIZE];
+ mpeg2dec_t *_mpegDecoder;
+ const mpeg2_info_t *_mpegInfo;
+};
+
+} // End of namespace Video
+
+#endif // VIDEO_CODECS_MPEG_H
+
+#endif // USE_MPEG2
diff --git a/video/coktel_decoder.cpp b/video/coktel_decoder.cpp
index d24a021f3b..4c3b6f8414 100644
--- a/video/coktel_decoder.cpp
+++ b/video/coktel_decoder.cpp
@@ -2426,8 +2426,10 @@ void VMDDecoder::blit16(const Graphics::Surface &srcSurf, Common::Rect &rect) {
if ((r == 0) && (g == 0) && (b == 0))
c = 0;
- if (_surface.format.bytesPerPixel == 2)
+ if (_surface.format.bytesPerPixel == 2)
*((uint16 *)dstRow) = (uint16) c;
+ else if (_surface.format.bytesPerPixel == 4)
+ *((uint32 *)dstRow) = (uint32) c;
}
src += srcSurf .pitch;
@@ -2462,8 +2464,10 @@ void VMDDecoder::blit24(const Graphics::Surface &srcSurf, Common::Rect &rect) {
if ((r == 0) && (g == 0) && (b == 0))
c = 0;
- if (_surface.format.bytesPerPixel == 2)
+ if (_surface.format.bytesPerPixel == 2)
*((uint16 *)dstRow) = (uint16) c;
+ else if (_surface.format.bytesPerPixel == 4)
+ *((uint32 *)dstRow) = (uint32) c;
}
src += srcSurf .pitch;
diff --git a/video/module.mk b/video/module.mk
index 287e14ce18..a491947aaf 100644
--- a/video/module.mk
+++ b/video/module.mk
@@ -31,5 +31,10 @@ MODULE_OBJS += \
theora_decoder.o
endif
+ifdef USE_MPEG2
+MODULE_OBJS += \
+ codecs/mpeg.o
+endif
+
# Include common rules
include $(srcdir)/rules.mk